Skip to content

Commit 14ffcaf

Browse files
authored
define import domain contracts (#67)
1 parent 75b2330 commit 14ffcaf

13 files changed

Lines changed: 702 additions & 11 deletions

CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@ configure_project_target(ecs_engine)
6464
add_library(safecrowd_domain STATIC
6565
src/domain/SafeCrowdDomain.h
6666
src/domain/SafeCrowdDomain.cpp
67+
src/domain/Geometry2D.h
68+
src/domain/RawImportModel.h
69+
src/domain/CanonicalGeometry.h
70+
src/domain/FacilityLayout2D.h
71+
src/domain/ImportIssue.h
72+
src/domain/ImportIssue.cpp
73+
src/domain/ImportResult.h
74+
src/domain/ImportOrchestrator.h
75+
src/domain/ImportContracts.h
6776
)
6877

6978
target_include_directories(safecrowd_domain
@@ -90,6 +99,7 @@ if (BUILD_TESTING)
9099
tests/PackedComponentStorageTests.cpp
91100
tests/SafeCrowdDomainTests.cpp
92101
tests/EcsCoreTests.cpp
102+
tests/ImportContractsTests.cpp
93103
)
94104

95105
target_include_directories(safecrowd_tests

src/domain/CanonicalGeometry.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#pragma once
2+
3+
#include <string>
4+
#include <vector>
5+
6+
#include "domain/Geometry2D.h"
7+
8+
namespace safecrowd::domain {
9+
10+
enum class OpeningKind {
11+
Unknown,
12+
Doorway,
13+
Passage,
14+
Exit,
15+
};
16+
17+
enum class VerticalLinkKind {
18+
Unknown,
19+
Stair,
20+
Ramp,
21+
Elevator,
22+
};
23+
24+
struct WalkableSurface2D {
25+
std::string id{};
26+
Polygon2D polygon{};
27+
std::vector<std::string> sourceIds{};
28+
};
29+
30+
struct WallSegment2D {
31+
std::string id{};
32+
LineSegment2D segment{};
33+
double thickness{0.0};
34+
std::vector<std::string> sourceIds{};
35+
};
36+
37+
struct Opening2D {
38+
std::string id{};
39+
OpeningKind kind{OpeningKind::Unknown};
40+
LineSegment2D span{};
41+
double width{0.0};
42+
std::vector<std::string> sourceIds{};
43+
};
44+
45+
struct Obstacle2D {
46+
std::string id{};
47+
Polygon2D footprint{};
48+
std::vector<std::string> sourceIds{};
49+
};
50+
51+
struct VerticalLink2D {
52+
std::string id{};
53+
VerticalLinkKind kind{VerticalLinkKind::Unknown};
54+
Point2D anchor{};
55+
std::string targetLevelId{};
56+
double width{0.0};
57+
std::vector<std::string> sourceIds{};
58+
};
59+
60+
struct CanonicalGeometry {
61+
std::string levelId{};
62+
std::vector<WalkableSurface2D> walkableAreas{};
63+
std::vector<WallSegment2D> walls{};
64+
std::vector<Opening2D> openings{};
65+
std::vector<Obstacle2D> obstacles{};
66+
std::vector<VerticalLink2D> verticalLinks{};
67+
};
68+
69+
} // namespace safecrowd::domain

src/domain/FacilityLayout2D.h

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#pragma once
2+
3+
#include <cstddef>
4+
#include <string>
5+
#include <vector>
6+
7+
#include "domain/Geometry2D.h"
8+
9+
namespace safecrowd::domain {
10+
11+
enum class ZoneKind {
12+
Unknown,
13+
Room,
14+
Corridor,
15+
Exit,
16+
Intersection,
17+
Stair,
18+
};
19+
20+
enum class ConnectionKind {
21+
Unknown,
22+
Doorway,
23+
Opening,
24+
Exit,
25+
Stair,
26+
Ramp,
27+
};
28+
29+
enum class TravelDirection {
30+
Bidirectional,
31+
ForwardOnly,
32+
ReverseOnly,
33+
Closed,
34+
};
35+
36+
enum class ControlKind {
37+
Unknown,
38+
Gate,
39+
ExitControl,
40+
BarrierToggle,
41+
};
42+
43+
struct ElementProvenance {
44+
std::vector<std::string> sourceIds{};
45+
std::vector<std::string> canonicalIds{};
46+
};
47+
48+
struct Zone2D {
49+
std::string id{};
50+
ZoneKind kind{ZoneKind::Unknown};
51+
std::string label{};
52+
Polygon2D area{};
53+
std::size_t defaultCapacity{0};
54+
bool isStair{false};
55+
bool isRamp{false};
56+
ElementProvenance provenance{};
57+
};
58+
59+
struct Connection2D {
60+
std::string id{};
61+
ConnectionKind kind{ConnectionKind::Unknown};
62+
std::string fromZoneId{};
63+
std::string toZoneId{};
64+
double effectiveWidth{0.0};
65+
TravelDirection directionality{TravelDirection::Bidirectional};
66+
bool isStair{false};
67+
bool isRamp{false};
68+
LineSegment2D centerSpan{};
69+
ElementProvenance provenance{};
70+
};
71+
72+
struct Barrier2D {
73+
std::string id{};
74+
Polyline2D geometry{};
75+
bool blocksMovement{true};
76+
ElementProvenance provenance{};
77+
};
78+
79+
struct ControlPoint2D {
80+
std::string id{};
81+
ControlKind kind{ControlKind::Unknown};
82+
std::string targetId{};
83+
bool defaultOpen{true};
84+
ElementProvenance provenance{};
85+
};
86+
87+
struct FacilityLayout2D {
88+
std::string id{};
89+
std::string name{};
90+
std::string levelId{};
91+
std::vector<Zone2D> zones{};
92+
std::vector<Connection2D> connections{};
93+
std::vector<Barrier2D> barriers{};
94+
std::vector<ControlPoint2D> controls{};
95+
};
96+
97+
} // namespace safecrowd::domain

src/domain/Geometry2D.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#pragma once
2+
3+
#include <vector>
4+
5+
namespace safecrowd::domain {
6+
7+
struct Point2D {
8+
double x{0.0};
9+
double y{0.0};
10+
};
11+
12+
struct LineSegment2D {
13+
Point2D start{};
14+
Point2D end{};
15+
};
16+
17+
struct Polyline2D {
18+
std::vector<Point2D> vertices{};
19+
bool closed{false};
20+
};
21+
22+
struct Polygon2D {
23+
std::vector<Point2D> outline{};
24+
std::vector<std::vector<Point2D>> holes{};
25+
};
26+
27+
} // namespace safecrowd::domain

src/domain/ImportContracts.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
3+
#include "domain/CanonicalGeometry.h"
4+
#include "domain/FacilityLayout2D.h"
5+
#include "domain/Geometry2D.h"
6+
#include "domain/ImportIssue.h"
7+
#include "domain/ImportOrchestrator.h"
8+
#include "domain/ImportResult.h"
9+
#include "domain/RawImportModel.h"

src/domain/ImportIssue.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include "domain/ImportIssue.h"
2+
3+
namespace safecrowd::domain {
4+
5+
bool ImportIssue::blocksSimulation() const noexcept {
6+
return isBlocking || severity == ImportIssueSeverity::Error;
7+
}
8+
9+
const char* toString(ImportIssueSeverity severity) noexcept {
10+
switch (severity) {
11+
case ImportIssueSeverity::Info:
12+
return "Info";
13+
case ImportIssueSeverity::Warning:
14+
return "Warning";
15+
case ImportIssueSeverity::Error:
16+
return "Error";
17+
}
18+
19+
return "Unknown";
20+
}
21+
22+
const char* toString(ImportIssueCode code) noexcept {
23+
switch (code) {
24+
case ImportIssueCode::Unknown:
25+
return "Unknown";
26+
case ImportIssueCode::UnsupportedEntity:
27+
return "UnsupportedEntity";
28+
case ImportIssueCode::MissingSourceGeometry:
29+
return "MissingSourceGeometry";
30+
case ImportIssueCode::InvalidGeometry:
31+
return "InvalidGeometry";
32+
case ImportIssueCode::DisconnectedWalkableArea:
33+
return "DisconnectedWalkableArea";
34+
case ImportIssueCode::MissingExit:
35+
return "MissingExit";
36+
case ImportIssueCode::WidthBelowMinimum:
37+
return "WidthBelowMinimum";
38+
case ImportIssueCode::UnmappedElement:
39+
return "UnmappedElement";
40+
}
41+
42+
return "Unknown";
43+
}
44+
45+
bool hasBlockingImportIssue(const std::vector<ImportIssue>& issues) noexcept {
46+
for (const auto& issue : issues) {
47+
if (issue.blocksSimulation()) {
48+
return true;
49+
}
50+
}
51+
52+
return false;
53+
}
54+
55+
} // namespace safecrowd::domain

src/domain/ImportIssue.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#pragma once
2+
3+
#include <string>
4+
#include <vector>
5+
6+
namespace safecrowd::domain {
7+
8+
enum class ImportIssueSeverity {
9+
Info,
10+
Warning,
11+
Error,
12+
};
13+
14+
enum class ImportIssueCode {
15+
Unknown,
16+
UnsupportedEntity,
17+
MissingSourceGeometry,
18+
InvalidGeometry,
19+
DisconnectedWalkableArea,
20+
MissingExit,
21+
WidthBelowMinimum,
22+
UnmappedElement,
23+
};
24+
25+
struct ImportIssue {
26+
ImportIssueSeverity severity{ImportIssueSeverity::Warning};
27+
ImportIssueCode code{ImportIssueCode::Unknown};
28+
std::string message{};
29+
std::string sourceId{};
30+
std::string targetId{};
31+
bool isBlocking{false};
32+
33+
bool blocksSimulation() const noexcept;
34+
};
35+
36+
const char* toString(ImportIssueSeverity severity) noexcept;
37+
const char* toString(ImportIssueCode code) noexcept;
38+
bool hasBlockingImportIssue(const std::vector<ImportIssue>& issues) noexcept;
39+
40+
} // namespace safecrowd::domain

src/domain/ImportOrchestrator.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma once
2+
3+
#include <filesystem>
4+
5+
#include "domain/ImportResult.h"
6+
7+
namespace safecrowd::domain {
8+
9+
struct ImportRequest {
10+
std::filesystem::path sourcePath{};
11+
ImportedFileFormat requestedFormat{ImportedFileFormat::Unknown};
12+
bool preserveRawModel{true};
13+
bool runValidation{true};
14+
};
15+
16+
class ImportOrchestrator {
17+
public:
18+
virtual ~ImportOrchestrator() = default;
19+
20+
virtual ImportResult importFile(const ImportRequest& request) = 0;
21+
};
22+
23+
} // namespace safecrowd::domain

src/domain/ImportResult.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#pragma once
2+
3+
#include <optional>
4+
#include <vector>
5+
6+
#include "domain/CanonicalGeometry.h"
7+
#include "domain/FacilityLayout2D.h"
8+
#include "domain/ImportIssue.h"
9+
#include "domain/RawImportModel.h"
10+
11+
namespace safecrowd::domain {
12+
13+
enum class ImportReviewStatus {
14+
NotRequired,
15+
Pending,
16+
Approved,
17+
Rejected,
18+
};
19+
20+
struct ImportTraceRef {
21+
std::string targetId{};
22+
std::vector<std::string> sourceIds{};
23+
std::vector<std::string> canonicalIds{};
24+
};
25+
26+
struct ImportResult {
27+
std::optional<RawImportModel> rawModel{};
28+
std::optional<CanonicalGeometry> canonicalGeometry{};
29+
std::optional<FacilityLayout2D> layout{};
30+
std::vector<ImportIssue> issues{};
31+
std::vector<ImportTraceRef> traceRefs{};
32+
ImportReviewStatus reviewStatus{ImportReviewStatus::Pending};
33+
34+
bool readyForSimulation() const noexcept {
35+
return layout.has_value()
36+
&& !hasBlockingImportIssue(issues)
37+
&& (reviewStatus == ImportReviewStatus::NotRequired
38+
|| reviewStatus == ImportReviewStatus::Approved);
39+
}
40+
};
41+
42+
} // namespace safecrowd::domain

0 commit comments

Comments
 (0)