Lots of progress on octrees

This commit is contained in:
2022-07-11 02:32:12 -04:00
parent 227de3666d
commit d54d6e4433
11 changed files with 3691 additions and 309 deletions

View File

@@ -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 &center, 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(); }
};