Skip to content

Commit cec66b2

Browse files
committed
--add semantic region creation and bindings.
1 parent 1290ce7 commit cec66b2

4 files changed

Lines changed: 177 additions & 17 deletions

File tree

src/esp/bindings/SceneBindings.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,26 @@ void initSceneBindings(py::module& m) {
160160
.def_property_readonly(
161161
"id", &SemanticRegion::id,
162162
"The ID of the region, of the form ``<level_id>_<region_id>``")
163+
.def_property_readonly("name", &SemanticRegion::name,
164+
"The unique name of this region")
163165
.def_property_readonly("level", &SemanticRegion::level)
164166
.def_property_readonly("aabb", &SemanticRegion::aabb)
165167
.def_property_readonly("category", &SemanticRegion::category,
166168
"The semantic category of the region")
167169
.def_property_readonly("objects", &SemanticRegion::objects,
168-
"All objects in the region");
170+
"All objects in the region")
171+
.def_property_readonly("poly_loop_points",
172+
&SemanticRegion::getPolyLoopPoints,
173+
"The points making up the polyloop for this "
174+
"region, coplanar and parallel to the floor.")
175+
.def_property_readonly("floor_height", &SemanticRegion::getFloorHeight,
176+
"The height above the x-z plane for the floor of "
177+
"the semantic region.")
178+
.def_property_readonly("extrusion_height",
179+
&SemanticRegion::getExtrusionHeight,
180+
"The height of the extrusion above the floor.")
181+
.def("contains", &SemanticRegion::contains, "point"_a,
182+
"Check whether the given point is contained in the given region.");
169183

170184
// ==== SemanticObject ====
171185
semanticObject

src/esp/scene/SemanticScene.cpp

Lines changed: 99 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// LICENSE file in the root directory of this source tree.
44

55
#include "SemanticScene.h"
6+
#include <Magnum/EigenIntegration/GeometryIntegration.h>
7+
#include <Magnum/EigenIntegration/Integration.h>
68
#include "GibsonSemanticScene.h"
79
#include "Mp3dSemanticScene.h"
810
#include "ReplicaSemanticScene.h"
@@ -145,22 +147,103 @@ bool SemanticScene::
145147
ESP_DEBUG(Mn::Debug::Flag::NoSpace)
146148
<< "Semantic Attributes : `" << semanticAttr->getHandle() << "` has "
147149
<< semanticAttr->getNumRegionInstances() << " regions defined.";
148-
149-
} // if semantic attributes specifes region annotations
150-
} // if semanticAttrs are not null
150+
// Build Semantic regions for each SemanticRegion attributes instance
151+
const auto regionInstances = semanticAttr->getRegionInstances();
152+
for (const auto regionInstance : regionInstances) {
153+
auto regionPtr = SemanticRegion::create();
154+
// Unique name
155+
regionPtr->name_ = regionInstance->getHandle();
156+
// Build a category
157+
regionPtr->category_ =
158+
LoopRegionCategory::create(-1, regionInstance->getLabel());
159+
// Set y heights
160+
regionPtr->extrusionHeight_ = regionInstance->getExtrusionHeight();
161+
regionPtr->floorHeight_ = regionInstance->getFloorHeight();
162+
// Set bbox
163+
const Mn::Vector3 min = regionInstance->getMinBounds();
164+
const Mn::Vector3 max = regionInstance->getMaxBounds();
165+
regionPtr->setBBox(min, max);
166+
// Set polyloop points and precalc polyloop edge vectors
167+
const std::vector<Mn::Vector3> loopPoints =
168+
regionInstance->getPolyLoop();
169+
170+
std::size_t numPts = loopPoints.size();
171+
regionPtr->polyLoopPoints_ = std::vector<Mn::Vector2>(numPts);
172+
// Save points and edges
173+
for (std::size_t i = 0; i < numPts; ++i) {
174+
Mn::Vector2 pt = {loopPoints[i].x(), loopPoints[i].z()};
175+
regionPtr->polyLoopPoints_[i] = pt;
176+
}
177+
}
178+
} else { // if semantic attributes specifes region annotations
179+
ESP_DEBUG(Mn::Debug::Flag::NoSpace)
180+
<< "Semantic Attributes : `" << semanticAttr->getHandle()
181+
<< "` does not have any regions defined.";
182+
}
183+
} else {
184+
ESP_DEBUG(Mn::Debug::Flag::NoSpace) << "Semantic attributes do not exist.";
185+
} // if semanticAttrs exist or not
151186

152187
return loadSuccess;
153188

154189
} // SemanticScene::loadSemanticSceneDescriptor
155190

191+
bool SemanticRegion::contains(const Mn::Vector3& pt) const {
192+
auto checkPt = [&](float x, float x0, float x1, float y, float y0,
193+
float y1) -> bool {
194+
float interp = ((y - y0) / (y1 - y0));
195+
return (y < y0) != (y < y1) && (x < x0 + interp * (x1 - x0));
196+
};
197+
198+
// First check height
199+
if ((pt.y() < floorHeight_) || (pt.y() > (floorHeight_ + extrusionHeight_))) {
200+
return false;
201+
}
202+
203+
// next check bbox
204+
if (!bbox_.contains(Mn::EigenIntegration::cast<vec3f>(pt))) {
205+
return false;
206+
}
207+
208+
// Lastly, count casts across edges.
209+
int count = 0;
210+
int numPts = polyLoopPoints_.size();
211+
for (int i = 0; i < numPts; ++i) {
212+
const auto stPt = polyLoopPoints_[i];
213+
const auto endPt = polyLoopPoints_[(i + 1) % numPts];
214+
if (stPt == endPt) {
215+
// Skip points that are equal.
216+
continue;
217+
}
218+
// If two consecutive y values are equal, rotate the cast by 90.
219+
bool checkCrossing =
220+
(endPt.y() == stPt.y()
221+
? checkPt(pt.y(), stPt.y(), endPt.y(), pt.x(), stPt.x(), endPt.x())
222+
: checkPt(pt.x(), stPt.x(), endPt.x(), pt.y(), stPt.y(),
223+
endPt.y()));
224+
if (checkCrossing) {
225+
++count;
226+
}
227+
}
228+
229+
// Want odd crossings for being inside
230+
return (count % 2 == 1);
231+
} // SemanticRegion::contains
232+
233+
void SemanticRegion::setBBox(const Mn::Vector3& min, const Mn::Vector3& max) {
234+
bbox_ = box3f(Mn::EigenIntegration::cast<vec3f>(min),
235+
Mn::EigenIntegration::cast<vec3f>(max));
236+
} // SemanticRegion::setBBox
237+
156238
namespace {
157239
/**
158-
* @brief Build an AABB for a given set of vertex indices in @p verts list, and
159-
* return in a std::pair, along with the count of verts used to build the AABB.
240+
* @brief Build an AABB for a given set of vertex indices in @p verts list,
241+
* and return in a std::pair, along with the count of verts used to build the
242+
* AABB.
160243
* @param colorInt Semantic Color of object
161244
* @param verts The mesh's vertex buffer.
162-
* @param setOfIDXs set of vertex IDXs in the vertex buffer being used to build
163-
* the resultant AABB.
245+
* @param setOfIDXs set of vertex IDXs in the vertex buffer being used to
246+
* build the resultant AABB.
164247
*/
165248
CCSemanticObject::ptr buildCCSemanticObjForSetOfVerts(
166249
uint32_t colorInt,
@@ -189,8 +272,8 @@ CCSemanticObject::ptr buildCCSemanticObjForSetOfVerts(
189272
} // buildCCSemanticObjForSetOfVerts
190273

191274
/**
192-
* @brief build per-SSD object vector of known semantic IDs - doing this in case
193-
* semanticIDs are not contiguous.
275+
* @brief build per-SSD object vector of known semantic IDs - doing this in
276+
* case semanticIDs are not contiguous.
194277
*/
195278

196279
std::vector<int> getObjsIdxToIDMap(
@@ -236,8 +319,8 @@ SemanticScene::buildCCBasedSemanticObjs(
236319
}
237320
}
238321

239-
// only map to semantic ID if semanticScene exists, otherwise return map with
240-
// objects keyed by hex color
322+
// only map to semantic ID if semanticScene exists, otherwise return map
323+
// with objects keyed by hex color
241324
if (!semanticScene) {
242325
return semanticCCObjsByVertTag;
243326
}
@@ -432,8 +515,9 @@ std::vector<uint32_t> SemanticScene::buildSemanticOBBs(
432515
// number of unique ssdObjs mappings.
433516

434517
for (int vertIdx = 0; vertIdx < vertSemanticIDs.size(); ++vertIdx) {
435-
// semantic ID on vertex - valid values are 1->semanticIDToSSOBJidx.size().
436-
// Invalid/unknown semantic ids are > semanticIDToSSOBJidx.size()
518+
// semantic ID on vertex - valid values are
519+
// 1->semanticIDToSSOBJidx.size(). Invalid/unknown semantic ids are >
520+
// semanticIDToSSOBJidx.size()
437521
const auto semanticID = vertSemanticIDs[vertIdx];
438522
if ((semanticID >= 0) && (semanticID < semanticIDToSSOBJidx.size())) {
439523
const auto vert = vertices[vertIdx];
@@ -473,7 +557,8 @@ std::vector<uint32_t> SemanticScene::buildSemanticOBBs(
473557
center = .5f * (vertMax[semanticID] + vertMin[semanticID]);
474558
dims = vertMax[semanticID] - vertMin[semanticID];
475559
ESP_VERY_VERBOSE() << Cr::Utility::formatString(
476-
"{} Semantic ID : {} : color : {} tag : {} present in {} verts | BB "
560+
"{} Semantic ID : {} : color : {} tag : {} present in {} verts | "
561+
"BB "
477562
"Center [{} {} {}] Dims [{} {} {}]",
478563
msgPrefix, semanticID, geo::getColorAsString(ssdObj.getColor()),
479564
ssdObj.id(), vertCounts[semanticID], center.x(), center.y(),

src/esp/scene/SemanticScene.h

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,29 @@ class SemanticLevel {
432432
ESP_SMART_POINTERS(SemanticLevel)
433433
};
434434

435+
class LoopRegionCategory : public SemanticCategory {
436+
public:
437+
LoopRegionCategory(const int id, const std::string& name)
438+
: id_(id), name_(name) {}
439+
440+
int index(const std::string& /*mapping*/) const override { return id_; }
441+
442+
std::string name(const std::string& mapping) const override {
443+
if (mapping == "category" || mapping.empty()) {
444+
return name_;
445+
} else {
446+
ESP_ERROR() << "Unknown mapping type:" << mapping;
447+
return "UNKNOWN";
448+
}
449+
}
450+
451+
protected:
452+
int id_;
453+
std::string name_;
454+
ESP_SMART_POINTERS(LoopRegionCategory)
455+
456+
}; // class LoopRegionCategory
457+
435458
//! Represents a region (typically room) in a level of a house
436459
class SemanticRegion {
437460
public:
@@ -443,15 +466,33 @@ class SemanticRegion {
443466
return "_" + std::to_string(index_);
444467
}
445468
}
469+
470+
std::string name() const { return name_; }
471+
446472
int getIndex() const { return index_; }
447473
SemanticLevel::ptr level() const { return level_; }
448474

449475
const std::vector<std::shared_ptr<SemanticObject>>& objects() const {
450476
return objects_;
451477
}
452478

479+
/**
480+
* @brief Test whether this region contains the passed point
481+
*/
482+
virtual bool contains(const Mn::Vector3& point) const;
483+
484+
void setBBox(const Mn::Vector3& min, const Mn::Vector3& max);
485+
453486
box3f aabb() const { return bbox_; }
454487

488+
const std::vector<Mn::Vector2>& getPolyLoopPoints() const {
489+
return polyLoopPoints_;
490+
}
491+
492+
double getExtrusionHeight() const { return extrusionHeight_; }
493+
494+
double getFloorHeight() const { return floorHeight_; }
495+
455496
SemanticCategory::ptr category() const { return category_; }
456497

457498
protected:
@@ -460,8 +501,17 @@ class SemanticRegion {
460501
std::shared_ptr<SemanticCategory> category_;
461502
vec3f position_;
462503
box3f bbox_;
463-
vec3f floorNormal_;
464-
std::vector<vec3f> floorPoints_;
504+
505+
std::string name_;
506+
507+
// Extrusion-based regions
508+
double extrusionHeight_{};
509+
// Floor height
510+
double floorHeight_{};
511+
512+
// poly loop points
513+
std::vector<Mn::Vector2> polyLoopPoints_;
514+
465515
std::vector<std::shared_ptr<SemanticObject>> objects_;
466516
std::shared_ptr<SemanticLevel> level_;
467517
friend SemanticScene;

src/esp/sim/Simulator.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,17 @@ bool Simulator::createSceneInstance(const std::string& activeSceneName) {
326326
"failed due to specified semantic tag `{}` not being found in "
327327
"SemanticAttributesManager. Aborting",
328328
activeSceneName, currSemanticAttrHandle));
329+
if (semanticAttr) {
330+
ESP_VERY_VERBOSE(Mn::Debug::Flag::NoSpace)
331+
<< "Scene Instance `" << activeSceneName
332+
<< "` has Semantic attr handle : `" << currSemanticAttrHandle
333+
<< "` which tagged attributes : `" << semanticAttr->getHandle() << "`";
334+
} else {
335+
ESP_VERY_VERBOSE(Mn::Debug::Flag::NoSpace)
336+
<< "Scene Instance `" << activeSceneName
337+
<< "` has Semantic attr handle : `" << currSemanticAttrHandle
338+
<< "` which did not reference any attributes";
339+
}
329340
// - Load semantic scene
330341
resourceManager_->loadSemanticScene(semanticAttr, activeSceneName);
331342

0 commit comments

Comments
 (0)