Skip to content

Commit 5ace0f5

Browse files
committed
[Domain] issue 16,17
1 parent d7cbca4 commit 5ace0f5

8 files changed

Lines changed: 228 additions & 0 deletions

File tree

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ add_library(safecrowd_domain STATIC
9494
src/domain/ImportValidationService.h
9595
src/domain/ImportValidationService.cpp
9696
src/domain/ImportContracts.h
97+
src/domain/AgentComponents.h
98+
src/domain/CompressionSystem.cpp
99+
src/domain/Metrics.h
100+
src/domain/Snapshot.cpp
101+
src/domain/Snapshot.h
97102
)
98103

99104
target_include_directories(safecrowd_domain

src/domain/AgentComponents.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
#include "domain/Geometry2D.h"
3+
4+
namespace safecrowd::domain {
5+
6+
// 에이전트의 위치를 나타내는 컴포넌트
7+
struct Position {
8+
Point2D value;
9+
};
10+
11+
// 에이전트의 고유 특성을 나타내는 컴포넌트
12+
struct Agent {
13+
float radius = 0.25f;
14+
float maxSpeed = 1.5f;
15+
};
16+
17+
struct Velocity {
18+
Point2D value;
19+
};
20+
21+
} // namespace safecrowd::domain

src/domain/CompressionSystem.cpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#include "domain/CompressionSystem.h"
2+
#include "domain/FacilityLayout2D.h"
3+
#include "domain/AgentComponents.h"
4+
#include "domain/metrics.h"
5+
#include <algorithm>
6+
#include <cmath>
7+
8+
namespace safecrowd::domain {
9+
10+
static float distanceBetween(const Point2D& p1, const Point2D& p2) {
11+
float dx = static_cast<float>(p1.x - p2.x);
12+
float dy = static_cast<float>(p1.y - p2.y);
13+
return std::sqrt(dx * dx + dy * dy);
14+
}
15+
16+
static float distancePointToSegment(const Point2D& p, const Point2D& a, const Point2D& b) {
17+
float l2 = static_cast<float>(std::pow(b.x - a.x, 2) + std::pow(b.y - a.y, 2));
18+
if (l2 == 0.0f) return distanceBetween(p, a);
19+
20+
float t = std::clamp(static_cast<float>(((p.x - a.x) * (b.x - a.x) + (p.y - a.y) * (b.y - a.y)) / l2), 0.0f, 1.0f);
21+
Point2D projection = { a.x + t * (b.x - a.x), a.y + t * (b.y - a.y) };
22+
return distanceBetween(p, projection);
23+
}
24+
25+
void CompressionSystem::update(engine::ComponentRegistry& registry, float dt) {
26+
// 필요한 스토리지들을 로드
27+
auto& posStorage = registry.storageFor<Position>();
28+
auto& agentStorage = registry.storageFor<Agent>();
29+
auto& compStorage = registry.storageFor<CompressionData>();
30+
31+
// Barrier2D 스토리지가 있는지 확인
32+
if (!registry.isRegistered<Barrier2D>()) return;
33+
auto& barrierStorage = registry.storageFor<Barrier2D>();
34+
35+
// Position을 가진 모든 엔티티를 순회
36+
for (const auto& entity : posStorage.getEntities()) {
37+
// Agent와 CompressionData 컴포넌트가 모두 있는지 확인
38+
if (!agentStorage.contains(entity) || !compStorage.contains(entity)) continue;
39+
40+
const auto& pos = posStorage.get(entity);
41+
const auto& agent = agentStorage.get(entity);
42+
auto& compression = compStorage.get(entity);
43+
44+
float currentForce = 0.0f;
45+
46+
// [군중 간 압박]
47+
for (const auto& otherEntity : posStorage.getEntities()) {
48+
if (entity.index == otherEntity.index && entity.generation == otherEntity.generation) continue;
49+
if (!agentStorage.contains(otherEntity)) continue;
50+
51+
const auto& otherPos = posStorage.get(otherEntity);
52+
const auto& otherAgent = agentStorage.get(otherEntity);
53+
54+
float dist = distanceBetween(pos.value, otherPos.value);
55+
float combinedRadius = agent.radius + otherAgent.radius;
56+
57+
if (dist < combinedRadius) {
58+
currentForce += (combinedRadius - dist);
59+
}
60+
}
61+
62+
// [벽/장애물 압박]
63+
for (const auto& barrierEntity : barrierStorage.getEntities()) {
64+
const auto& barrier = barrierStorage.get(barrierEntity);
65+
const auto& vertices = barrier.geometry.vertices;
66+
if (vertices.size() < 2) continue;
67+
68+
for (size_t i = 0; i < vertices.size() - 1; ++i) {
69+
float distToWall = distancePointToSegment(pos.value, vertices[i], vertices[i + 1]);
70+
if (distToWall < agent.radius) {
71+
currentForce += (agent.radius - distToWall);
72+
}
73+
}
74+
if (barrier.geometry.closed) {
75+
float distToWall = distancePointToSegment(pos.value, vertices.back(), vertices.front());
76+
if (distToWall < agent.radius) {
77+
currentForce += (agent.radius - distToWall);
78+
}
79+
}
80+
}
81+
82+
compression.force = currentForce;
83+
84+
// [고위험 상태 업데이트]
85+
const float FORCE_THRESHOLD = 0.5f;
86+
if (compression.force > FORCE_THRESHOLD) {
87+
compression.exposure += dt;
88+
}
89+
else {
90+
compression.exposure = std::max(0.0f, compression.exposure - dt * 0.5f);
91+
}
92+
93+
const float EXPOSURE_THRESHOLD = 2.0f;
94+
compression.isCritical = (compression.force > FORCE_THRESHOLD) &&
95+
(compression.exposure > EXPOSURE_THRESHOLD);
96+
}
97+
}
98+
99+
} // namespace safecrowd::domain

src/domain/CompressionSystem.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#pragma once
2+
3+
#include "engine/ComponentRegistry.h"
4+
5+
namespace safecrowd::domain {
6+
7+
// 시스템 클래스 선언
8+
class CompressionSystem {
9+
public:
10+
// 업데이트 함수 선언
11+
void update(engine::ComponentRegistry& registry, float dt);
12+
};
13+
14+
} // namespace safecrowd::domain

src/domain/Metrics.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#pragma once
2+
3+
namespace safecrowd::domain {
4+
// 특정 에이전트가 받는 물리적/시간적 압박 상태를 담음
5+
struct CompressionData {
6+
// CompressionForce: 주변 객체와의 접촉으로 인해 발생하는 즉각적인 하중
7+
float force = 0.0f;
8+
9+
// CompressionExposure: 위험 임계값 이상의 압박이 지속된 누적 시간 (단위: sec)
10+
float exposure = 0.0f;
11+
12+
// CompressionCriticalState: 하중과 지속시간을 종합한 고위험 판정 플래그
13+
bool isCritical = false;
14+
};
15+
16+
} // namespace safecrowd::domain

src/domain/Snapshot.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#include "domain/snapshot.h"
2+
#include "domain/AgentComponents.h"
3+
#include "domain/metrics.h"
4+
#include "engine/ComponentRegistry.h"
5+
6+
namespace safecrowd::domain {
7+
8+
// 인자 타입을 safecrowd::engine::ComponentRegistry로 명확히 지정 (E0276 해결)
9+
SimulationSnapshot buildSnapshot(const safecrowd::engine::ComponentRegistry& registry, uint64_t frame, float time) {
10+
SimulationSnapshot snapshot;
11+
snapshot.frameIndex = frame;
12+
snapshot.simulationTime = time;
13+
14+
// 우리 엔진의 저장소(Storage)에서 데이터를 로드
15+
auto& posStorage = registry.storageFor<Position>();
16+
auto& compStorage = registry.storageFor<CompressionData>();
17+
18+
snapshot.agentCount = static_cast<uint32_t>(posStorage.size());
19+
snapshot.agents.reserve(snapshot.agentCount);
20+
21+
// Position을 가진 모든 엔티티를 순회하며 스냅샷 생성
22+
for (const auto& entity : posStorage.getEntities()) {
23+
// 해당 엔티티에 압박 지표 데이터도 있는지 확인
24+
if (!compStorage.contains(entity)) continue;
25+
26+
const auto& pos = posStorage.get(entity);
27+
const auto& metrics = compStorage.get(entity);
28+
29+
// AgentSnapshot 구조체에 맞춰 데이터 삽입
30+
snapshot.agents.push_back({
31+
static_cast<uint32_t>(entity.index), // id
32+
pos.value, // position (Point2D)
33+
metrics // metrics (CompressionData)
34+
});
35+
}
36+
37+
return snapshot;
38+
}
39+
40+
} // namespace safecrowd::domain

src/domain/Snapshot.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#pragma once
2+
#include <vector>
3+
#include <cstdint>
4+
#include "domain/Geometry2D.h"
5+
#include "domain/metrics.h"
6+
7+
namespace safecrowd::engine {
8+
class ComponentRegistry;
9+
}
10+
11+
namespace safecrowd::domain {
12+
13+
struct AgentSnapshot {
14+
uint32_t id;
15+
Point2D position;
16+
CompressionData metrics;
17+
};
18+
19+
struct SimulationSnapshot {
20+
uint64_t frameIndex = 0;
21+
float simulationTime = 0.0f;
22+
uint32_t agentCount = 0;
23+
std::vector<AgentSnapshot> agents;
24+
};
25+
26+
// 네임스페이스를 safecrowd::engine으로 명시
27+
SimulationSnapshot buildSnapshot(const safecrowd::engine::ComponentRegistry& registry, uint64_t frame, float time);
28+
29+
} // namespace safecrowd::domain

src/engine/PackedComponentStorage.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ class PackedComponentStorage final : public IComponentStorage {
6161
return components_.size();
6262
}
6363

64+
[[nodiscard]] const std::vector<Entity>& getEntities() const noexcept {
65+
return entities_;
66+
}
67+
6468
private:
6569
struct EntityHash {
6670
[[nodiscard]] std::size_t operator()(const Entity& entity) const noexcept {

0 commit comments

Comments
 (0)