Open source Star Ruler 2 source code!
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
tidy class RegionData {
|
||||
vec3d position;
|
||||
double radius;
|
||||
};
|
||||
|
||||
tidy class RegionMap {
|
||||
planed plane;
|
||||
RegionMap@ back, front;
|
||||
array<RegionData@> regs;
|
||||
bool xSplit;
|
||||
double maxRegionSize = 0;
|
||||
|
||||
RegionMap() {
|
||||
xSplit = true;
|
||||
}
|
||||
|
||||
RegionMap(bool useXSplit) {
|
||||
xSplit = useXSplit;
|
||||
}
|
||||
|
||||
RegionData@ findClosest(const vec3d& point, double& nearest) const {
|
||||
RegionData@ closest;
|
||||
if(back !is null) {
|
||||
double dist = plane.distFromPlane(point);
|
||||
|
||||
if(dist > 0.0) {
|
||||
if(dist > -nearest)
|
||||
@closest = front.findClosest(point, nearest);
|
||||
if(dist < nearest) {
|
||||
RegionData@ c = back.findClosest(point, nearest);
|
||||
if(c !is null)
|
||||
@closest = c;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(dist < nearest)
|
||||
@closest = back.findClosest(point, nearest);
|
||||
if(dist > -nearest) {
|
||||
RegionData@ c = front.findClosest(point, nearest);
|
||||
if(c !is null)
|
||||
@closest = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(uint i = 0, cnt = regs.length; i < cnt; ++i) {
|
||||
RegionData@ reg = regs[i];
|
||||
double dist = reg.position.distanceTo(point) - reg.radius;
|
||||
if(dist < nearest) {
|
||||
@closest = reg;
|
||||
nearest = dist;
|
||||
}
|
||||
}
|
||||
|
||||
return closest;
|
||||
}
|
||||
|
||||
RegionData@ findRegion(const vec3d& point) const {
|
||||
if(back !is null) {
|
||||
double dist = plane.distFromPlane(point);
|
||||
if(dist < maxRegionSize) {
|
||||
RegionData@ region = back.findRegion(point);
|
||||
if(region !is null)
|
||||
return region;
|
||||
}
|
||||
if(dist > -maxRegionSize) {
|
||||
RegionData@ region = front.findRegion(point);
|
||||
if(region !is null)
|
||||
return region;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
for(uint i = 0, cnt = regs.length; i < cnt; ++i) {
|
||||
RegionData@ region = regs[i];
|
||||
if(point.distanceToSQ(region.position) < region.radius * region.radius)
|
||||
return region;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void addSystem(const vec3d& position, double radius) {
|
||||
RegionData dat;
|
||||
dat.position = position;
|
||||
dat.radius = radius;
|
||||
addRegion(dat);
|
||||
}
|
||||
|
||||
bool hasExisting(const vec3d& position, double radius) {
|
||||
double closest = INFINITY;
|
||||
auto@ dat = findClosest(position, closest);
|
||||
if(dat is null)
|
||||
return false;
|
||||
return dat.position.distanceToSQ(position) < radius * radius;
|
||||
}
|
||||
|
||||
void addRegion(RegionData@ region) {
|
||||
if(region.radius > maxRegionSize)
|
||||
maxRegionSize = region.radius;
|
||||
|
||||
if(back !is null) {
|
||||
if(plane.inFront(region.position))
|
||||
front.addRegion(region);
|
||||
else
|
||||
back.addRegion(region);
|
||||
}
|
||||
else {
|
||||
regs.insertLast(region);
|
||||
//Once we have enough regions, split into two nodes
|
||||
if(regs.length > 4) {
|
||||
//TODO: Decide a better middle point (median, rather than mean)
|
||||
vec3d avg;
|
||||
for(uint i = 0, cnt = regs.length; i < cnt; ++i)
|
||||
avg += regs[i].position;
|
||||
avg /= double(regs.length);
|
||||
|
||||
if(xSplit)
|
||||
plane = planed(avg, vec3d_front());
|
||||
else
|
||||
plane = planed(avg, vec3d_right());
|
||||
|
||||
@back = RegionMap(!xSplit);
|
||||
@front = RegionMap(!xSplit);
|
||||
|
||||
for(uint i = 0, cnt = regs.length; i < cnt; ++i)
|
||||
addRegion(regs[i]);
|
||||
regs.length = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user