Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ configure_project_target(ecs_engine)
add_library(safecrowd_domain STATIC
src/domain/SafeCrowdDomain.h
src/domain/SafeCrowdDomain.cpp
src/domain/Geometry2D.h
src/domain/RawImportModel.h
src/domain/CanonicalGeometry.h
src/domain/FacilityLayout2D.h
src/domain/ImportIssue.h
src/domain/ImportIssue.cpp
src/domain/ImportResult.h
src/domain/ImportOrchestrator.h
src/domain/ImportContracts.h
)

target_include_directories(safecrowd_domain
Expand All @@ -90,6 +99,7 @@ if (BUILD_TESTING)
tests/PackedComponentStorageTests.cpp
tests/SafeCrowdDomainTests.cpp
tests/EcsCoreTests.cpp
tests/ImportContractsTests.cpp
)

target_include_directories(safecrowd_tests
Expand Down
69 changes: 69 additions & 0 deletions src/domain/CanonicalGeometry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#pragma once

#include <string>
#include <vector>

#include "domain/Geometry2D.h"

namespace safecrowd::domain {

enum class OpeningKind {
Unknown,
Doorway,
Passage,
Exit,
};

enum class VerticalLinkKind {
Unknown,
Stair,
Ramp,
Elevator,
};

struct WalkableSurface2D {
std::string id{};
Polygon2D polygon{};
std::vector<std::string> sourceIds{};
};

struct WallSegment2D {
std::string id{};
LineSegment2D segment{};
double thickness{0.0};
std::vector<std::string> sourceIds{};
};

struct Opening2D {
std::string id{};
OpeningKind kind{OpeningKind::Unknown};
LineSegment2D span{};
double width{0.0};
std::vector<std::string> sourceIds{};
};

struct Obstacle2D {
std::string id{};
Polygon2D footprint{};
std::vector<std::string> sourceIds{};
};

struct VerticalLink2D {
std::string id{};
VerticalLinkKind kind{VerticalLinkKind::Unknown};
Point2D anchor{};
std::string targetLevelId{};
double width{0.0};
std::vector<std::string> sourceIds{};
};

struct CanonicalGeometry {
std::string levelId{};
std::vector<WalkableSurface2D> walkableAreas{};
std::vector<WallSegment2D> walls{};
std::vector<Opening2D> openings{};
std::vector<Obstacle2D> obstacles{};
std::vector<VerticalLink2D> verticalLinks{};
};

} // namespace safecrowd::domain
97 changes: 97 additions & 0 deletions src/domain/FacilityLayout2D.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#pragma once

#include <cstddef>
#include <string>
#include <vector>

#include "domain/Geometry2D.h"

namespace safecrowd::domain {

enum class ZoneKind {
Unknown,
Room,
Corridor,
Exit,
Intersection,
Stair,
};

enum class ConnectionKind {
Unknown,
Doorway,
Opening,
Exit,
Stair,
Ramp,
};

enum class TravelDirection {
Bidirectional,
ForwardOnly,
ReverseOnly,
Closed,
};

enum class ControlKind {
Unknown,
Gate,
ExitControl,
BarrierToggle,
};

struct ElementProvenance {
std::vector<std::string> sourceIds{};
std::vector<std::string> canonicalIds{};
};

struct Zone2D {
std::string id{};
ZoneKind kind{ZoneKind::Unknown};
std::string label{};
Polygon2D area{};
std::size_t defaultCapacity{0};
bool isStair{false};
bool isRamp{false};
ElementProvenance provenance{};
};

struct Connection2D {
std::string id{};
ConnectionKind kind{ConnectionKind::Unknown};
std::string fromZoneId{};
std::string toZoneId{};
double effectiveWidth{0.0};
TravelDirection directionality{TravelDirection::Bidirectional};
bool isStair{false};
bool isRamp{false};
LineSegment2D centerSpan{};
ElementProvenance provenance{};
};

struct Barrier2D {
std::string id{};
Polyline2D geometry{};
bool blocksMovement{true};
ElementProvenance provenance{};
};

struct ControlPoint2D {
std::string id{};
ControlKind kind{ControlKind::Unknown};
std::string targetId{};
bool defaultOpen{true};
ElementProvenance provenance{};
};

struct FacilityLayout2D {
std::string id{};
std::string name{};
std::string levelId{};
std::vector<Zone2D> zones{};
std::vector<Connection2D> connections{};
std::vector<Barrier2D> barriers{};
std::vector<ControlPoint2D> controls{};
};

} // namespace safecrowd::domain
27 changes: 27 additions & 0 deletions src/domain/Geometry2D.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#include <vector>

namespace safecrowd::domain {

struct Point2D {
double x{0.0};
double y{0.0};
};

struct LineSegment2D {
Point2D start{};
Point2D end{};
};

struct Polyline2D {
std::vector<Point2D> vertices{};
bool closed{false};
};

struct Polygon2D {
std::vector<Point2D> outline{};
std::vector<std::vector<Point2D>> holes{};
};

} // namespace safecrowd::domain
9 changes: 9 additions & 0 deletions src/domain/ImportContracts.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include "domain/CanonicalGeometry.h"
#include "domain/FacilityLayout2D.h"
#include "domain/Geometry2D.h"
#include "domain/ImportIssue.h"
#include "domain/ImportOrchestrator.h"
#include "domain/ImportResult.h"
#include "domain/RawImportModel.h"
55 changes: 55 additions & 0 deletions src/domain/ImportIssue.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include "domain/ImportIssue.h"

namespace safecrowd::domain {

bool ImportIssue::blocksSimulation() const noexcept {
return isBlocking || severity == ImportIssueSeverity::Error;
}

const char* toString(ImportIssueSeverity severity) noexcept {
switch (severity) {
case ImportIssueSeverity::Info:
return "Info";
case ImportIssueSeverity::Warning:
return "Warning";
case ImportIssueSeverity::Error:
return "Error";
}

return "Unknown";
}

const char* toString(ImportIssueCode code) noexcept {
switch (code) {
case ImportIssueCode::Unknown:
return "Unknown";
case ImportIssueCode::UnsupportedEntity:
return "UnsupportedEntity";
case ImportIssueCode::MissingSourceGeometry:
return "MissingSourceGeometry";
case ImportIssueCode::InvalidGeometry:
return "InvalidGeometry";
case ImportIssueCode::DisconnectedWalkableArea:
return "DisconnectedWalkableArea";
case ImportIssueCode::MissingExit:
return "MissingExit";
case ImportIssueCode::WidthBelowMinimum:
return "WidthBelowMinimum";
case ImportIssueCode::UnmappedElement:
return "UnmappedElement";
}

return "Unknown";
}

bool hasBlockingImportIssue(const std::vector<ImportIssue>& issues) noexcept {
for (const auto& issue : issues) {
if (issue.blocksSimulation()) {
return true;
}
}

return false;
}

} // namespace safecrowd::domain
40 changes: 40 additions & 0 deletions src/domain/ImportIssue.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

#include <string>
#include <vector>

namespace safecrowd::domain {

enum class ImportIssueSeverity {
Info,
Warning,
Error,
};

enum class ImportIssueCode {
Unknown,
UnsupportedEntity,
MissingSourceGeometry,
InvalidGeometry,
DisconnectedWalkableArea,
MissingExit,
WidthBelowMinimum,
UnmappedElement,
};

struct ImportIssue {
ImportIssueSeverity severity{ImportIssueSeverity::Warning};
ImportIssueCode code{ImportIssueCode::Unknown};
std::string message{};
std::string sourceId{};
std::string targetId{};
bool isBlocking{false};

bool blocksSimulation() const noexcept;
};

const char* toString(ImportIssueSeverity severity) noexcept;
const char* toString(ImportIssueCode code) noexcept;
bool hasBlockingImportIssue(const std::vector<ImportIssue>& issues) noexcept;

} // namespace safecrowd::domain
23 changes: 23 additions & 0 deletions src/domain/ImportOrchestrator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once

#include <filesystem>

#include "domain/ImportResult.h"

namespace safecrowd::domain {

struct ImportRequest {
std::filesystem::path sourcePath{};
ImportedFileFormat requestedFormat{ImportedFileFormat::Unknown};
bool preserveRawModel{true};
bool runValidation{true};
};

class ImportOrchestrator {
public:
virtual ~ImportOrchestrator() = default;

virtual ImportResult importFile(const ImportRequest& request) = 0;
};

} // namespace safecrowd::domain
42 changes: 42 additions & 0 deletions src/domain/ImportResult.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#pragma once

#include <optional>
#include <vector>

#include "domain/CanonicalGeometry.h"
#include "domain/FacilityLayout2D.h"
#include "domain/ImportIssue.h"
#include "domain/RawImportModel.h"

namespace safecrowd::domain {

enum class ImportReviewStatus {
NotRequired,
Pending,
Approved,
Rejected,
};

struct ImportTraceRef {
std::string targetId{};
std::vector<std::string> sourceIds{};
std::vector<std::string> canonicalIds{};
};

struct ImportResult {
std::optional<RawImportModel> rawModel{};
std::optional<CanonicalGeometry> canonicalGeometry{};
std::optional<FacilityLayout2D> layout{};
std::vector<ImportIssue> issues{};
std::vector<ImportTraceRef> traceRefs{};
ImportReviewStatus reviewStatus{ImportReviewStatus::Pending};

bool readyForSimulation() const noexcept {
return layout.has_value()
&& !hasBlockingImportIssue(issues)
&& (reviewStatus == ImportReviewStatus::NotRequired
|| reviewStatus == ImportReviewStatus::Approved);
}
};

} // namespace safecrowd::domain
Loading
Loading