Lots of progress on octrees
This commit is contained in:
@@ -76,21 +76,94 @@
|
||||
#include "wrap-vector.hpp"
|
||||
#include "wrap-map.hpp"
|
||||
#include "wrap-string.hpp"
|
||||
|
||||
#include "wrap-bytell-hash-map.hpp"
|
||||
#include "util.hpp"
|
||||
#include "luastack.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
class PlaneMap;
|
||||
class PlaneTree;
|
||||
|
||||
class PlaneItem : public eng::nevernew {
|
||||
class PlaneScan : public eng::nevernew {
|
||||
public:
|
||||
friend class PlaneMap;
|
||||
friend class PlaneTree;
|
||||
enum Shape { BOX, CYLINDER, SPHEROID };
|
||||
private:
|
||||
// The plane to scan.
|
||||
eng::string plane_;
|
||||
|
||||
// The bounding box of the scan.
|
||||
util::XYZ lo_, hi_, center_;
|
||||
|
||||
// If you scan a cylinder or spheroid, it actually
|
||||
// scans the bounding box first, then clips out
|
||||
// the parts that aren't correct.
|
||||
Shape shape_;
|
||||
|
||||
// When true, the items are sorted by ID.
|
||||
// WARNING: setting this to false can create
|
||||
// nondeterminism. Scans by lua should always be sorted.
|
||||
bool sorted_;
|
||||
|
||||
// The special ID, if nonzero, is either PREPENDED to the
|
||||
// results, or OMITTED from the results, depending on omit_special.
|
||||
int64_t special_;
|
||||
bool omit_special_;
|
||||
|
||||
// If this is true, items on the nowhere plane are not scanned.
|
||||
bool omit_nowhere_;
|
||||
|
||||
private:
|
||||
PlaneMap *pmap_;
|
||||
// Derived variables. These are populated by PlaneTree::scan.
|
||||
uint64_t bblo_;
|
||||
uint64_t bbhi_;
|
||||
|
||||
public:
|
||||
PlaneScan() : plane_(""), shape_(BOX), sorted_(true), special_(0), omit_special_(0), omit_nowhere_(false) {}
|
||||
|
||||
// Convert a lua table into a scan configuration.
|
||||
void configure(LuaStack &LS, LuaSlot slot);
|
||||
|
||||
// Set the bounding box given two corners.
|
||||
void set_bbox_given_two_corners(const util::XYZ &a, const util::XYZ &b) {
|
||||
lo_.x = std::min(a.x, b.x);
|
||||
lo_.y = std::min(a.y, b.y);
|
||||
lo_.z = std::min(a.z, b.z);
|
||||
hi_.x = std::max(a.x, b.x);
|
||||
hi_.y = std::max(a.y, b.y);
|
||||
hi_.z = std::max(a.z, b.z);
|
||||
center_ = (lo_ + hi_) * 0.5;
|
||||
}
|
||||
|
||||
// Set the bounding box given a center and a radius.
|
||||
void set_bbox_given_center_radius(const util::XYZ ¢er, float r) {
|
||||
util::XYZ offset(r, r, r);
|
||||
lo_ = center - offset;
|
||||
hi_ = center + offset;
|
||||
center_ = center;
|
||||
}
|
||||
|
||||
void set_plane(std::string_view p) { plane_ = p; }
|
||||
void set_shape(Shape s) { shape_ = s; }
|
||||
void set_sorted(bool s) { sorted_ = s; }
|
||||
void set_special(int64_t id, bool omit) { special_ = id; omit_special_ = omit; }
|
||||
void set_omit_nowhere(bool b) { omit_nowhere_ = b; }
|
||||
};
|
||||
|
||||
class PlaneItem : public eng::nevernew {
|
||||
friend class PlaneTree;
|
||||
friend class PlaneMap;
|
||||
private:
|
||||
PlaneTree *tree_;
|
||||
PlaneItem *prev_;
|
||||
PlaneItem *next_;
|
||||
int64_t id_;
|
||||
eng::string plane_;
|
||||
float x_, y_, z_;
|
||||
int64_t id_;
|
||||
|
||||
public:
|
||||
PlaneItem();
|
||||
@@ -105,43 +178,49 @@ public:
|
||||
const float y() const { return y_; }
|
||||
const float z() const { return z_; }
|
||||
|
||||
void untrack();
|
||||
void track(PlaneMap *pmap);
|
||||
void untrack() { track(nullptr); }
|
||||
|
||||
void set_pos(const eng::string &plane, float x, float y, float z);
|
||||
void set_xyz(float x, float y, float z) { set_pos(plane_, x, y, z); }
|
||||
void set_xyz(float x, float y, float z);
|
||||
};
|
||||
|
||||
class PlaneMap : public eng::nevernew {
|
||||
friend class PlaneItem;
|
||||
private:
|
||||
using EltVec = eng::vector<PlaneItem *>;
|
||||
using Plane = eng::map<int64_t, EltVec>;
|
||||
eng::map<eng::string, Plane> planes_;
|
||||
void remove(const eng::string &plane, int64_t cell, PlaneItem *client);
|
||||
void insert(const eng::string &plane, int64_t cell, PlaneItem *client);
|
||||
|
||||
friend class PlaneTree;
|
||||
public:
|
||||
using IdVector = util::IdVector;
|
||||
|
||||
private:
|
||||
float default_radius_;
|
||||
eng::map<eng::string, std::unique_ptr<PlaneTree>> planes_;
|
||||
|
||||
public:
|
||||
// No special code is needed for construction or destruction.
|
||||
PlaneMap();
|
||||
~PlaneMap();
|
||||
|
||||
// Caution: scan_radius is not deterministically ordered unless sort=true.
|
||||
//
|
||||
// exclude_nowhere - if true, and plane="nowhere", nothing is scanned.
|
||||
// special - an ID that is considered special. If zero, there is no special ID.
|
||||
// omit - if true, remove the special ID from the list.
|
||||
// if false, prepend the special ID to the head of the list.
|
||||
//
|
||||
IdVector scan_radius(const eng::string &plane, float x, float y, float radius, bool exclude_nowhere, int64_t special, bool omit) const;
|
||||
IdVector scan_radius_unsorted(const eng::string &plane, float x, float y, float radius, bool exclude_nowhere, int64_t special, bool omit) const;
|
||||
// The 'insert' and 'remove' operators are inside class
|
||||
// PlaneItem. See PlaneItem::track and PlaneItem::untrack.
|
||||
|
||||
// Scan the PlaneMap for items, return their IDs.
|
||||
IdVector scan(const PlaneScan &s) const;
|
||||
|
||||
// Set the default radius for all planes.
|
||||
// Maybe we'll make it adaptive some day.
|
||||
void set_default_radius(float r) { default_radius_ = r; }
|
||||
|
||||
// Return a debug string for the specified plane.
|
||||
// This is for unit testing.
|
||||
eng::string tree_debug_string(const eng::string &plane) const;
|
||||
eng::string outliers_debug_string(const eng::string &plane) const;
|
||||
|
||||
// Untrack all planeitems. This is for unit testing.
|
||||
void untrack_all();
|
||||
|
||||
private:
|
||||
// unit testing stuff.
|
||||
friend int lfn_unittests_planemap(lua_State *L);
|
||||
EltVec get_cell(const eng::string &plane, int64_t cell) const;
|
||||
int total_cells() const;
|
||||
void clear() { planes_.clear(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user