13#ifdef CARLA_ROAD_GENERATOR_EXTRA_LOG
23#ifdef CARLA_ROAD_GENERATOR_EXTRA_LOG
25 static void ResetIndices() {
26 GraphNode::ResetIndex();
27 GraphHalfEdge::ResetIndex();
28 GraphFace::ResetIndex();
38 static std::pair<DoublyConnectedEdgeList::HalfEdge *, DoublyConnectedEdgeList::HalfEdge *>
43 auto normalize = [](
auto a) {
44 constexpr float twoPi = 2.0 * 3.14159265359;
46 while (a >= 1.0) a -= 1.0;
47 while (a < 0.0) a += 1.0;
50 auto angle = Dcel::GetAngle(halfEdge);
51 std::map<
decltype(angle), Dcel::HalfEdge *> edgeMap;
53 auto &firstHalfEdge = Dcel::GetLeavingHalfEdge(Dcel::GetSource(halfEdge));
54 auto *edge = &firstHalfEdge;
56 if (edge != &halfEdge) {
58 auto a = normalize(alpha - angle);
59 edgeMap.insert({a, edge});
61 edge = &Dcel::GetNextInNode(*edge);
62 }
while (edge != &firstHalfEdge);
63 check(!edgeMap.empty());
64 return {edgeMap.rbegin()->second, edgeMap.begin()->second};
78 Nodes.emplace_back(Position0);
79 Nodes.emplace_back(Position1);
101#ifdef CARLA_ROAD_GENERATOR_EXTRA_LOG
114 Nodes.emplace_back(NodePosition);
115 auto &newNode =
Nodes.back();
121 edge0.Source = &newNode;
122 edge0.Target = &OtherNode;
125 edge1.Source = &OtherNode;
126 edge1.Target = &newNode;
137 edge1.Face = next->
Face;
141 newNode.LeavingHalfEdge = &edge0;
155 auto &newNode =
Nodes.back();
157 auto &node0 = *edge.
Source;
160 edge0.Source = &newNode;
161 edge0.Target = &node0;
166 edge1.Source = &node0;
167 edge1.Target = &newNode;
185 node0.LeavingHalfEdge = &edge1;
186 newNode.LeavingHalfEdge = &edge0;
195 Faces.emplace_back();
196 auto &newFace =
Faces.back();
202 edge0.Source = &Node0;
203 edge0.Target = &Node1;
205 edge1.Source = &Node1;
206 edge1.Target = &Node0;
224 auto &oldFace = *next1->
Face;
226 newFace.HalfEdge = &edge1;
229 auto fixFace = [](
Face &face) {
231 auto *edge = &firstEdge;
235 }
while (edge != &firstEdge);
250 auto dir = trg - src;
251 return std::atan2(
static_cast<double>(dir.y),
static_cast<double>(dir.x));
254#ifdef CARLA_ROAD_GENERATOR_EXTRA_LOG
256 void DoublyConnectedEdgeList::PrintToLog()
const
258 std::wstringstream sout;
260 sout <<
"iterate all nodes: ";
262 auto p = node.GetPosition();
263 sout << node <<
"{" << p.x <<
"," << p.y <<
"} ";
268 sout <<
"iterate all faces: ";
275 sout <<
"iterate all edges: ";
280 sout << edge <<
"{" << src <<
"->" << trg <<
"," << face <<
"} ";
285 sout <<
"iterate nodes in face: ";
287 sout << face <<
"{ ";
289 const auto *edge = &firstEdge;
293 }
while (edge != &firstEdge);
299 sout <<
"iterate edges in node: ";
301 sout << node <<
"{ ";
303 const auto *edge = &firstEdge;
307 }
while (edge != &firstEdge);
312 UE_LOG(LogCarla, Log, TEXT(
"\n%s"), sout.str().c_str());
UE_LOG(LogCarla, Log, TEXT("UActorDispatcher::Destroying actor: '%s' %x"), *Id, Actor)
简单的双连通边链表结构。它只允许添加元素,不允许删除元素。
ListView< FaceIterator > GetFaces()
Node & AddNode(const Position &NodePosition, Node &OtherNode)
{
Face & ConnectNodes(Node &Node0, Node &Node1)
用一对边连接两个节点。
ListView< HalfEdgeIterator > GetHalfEdges()
HalfEdgeContainer HalfEdges
DoublyConnectedEdgeList(const Position &Position0, const Position &Position1)
创建一个有2个节点、2个边和1个面的双连通边链表DoublyConnectedEdgeList。
static float GetAngle(const HalfEdge &halfEdge)
返回 half-edge 的角度,范围为 [-pi, pi]
ListView< NodeIterator > GetNodes()
static HalfEdge & GetHalfEdge(Face &face)
static Node & GetTarget(HalfEdge &halfEdge)
static HalfEdge & GetLeavingHalfEdge(Node &node)
static Face & GetFace(HalfEdge &halfEdge)
static Node & GetSource(HalfEdge &halfEdge)
static HalfEdge & GetNextInNode(HalfEdge &halfEdge)
static HalfEdge & GetNextInFace(HalfEdge &halfEdge)
~DoublyConnectedEdgeList()
Node & SplitEdge(const Position &Position, HalfEdge &HalfEdge)
在 位置分割 HalfEdge (和它的配对)
static std::pair< DoublyConnectedEdgeList::HalfEdge *, DoublyConnectedEdgeList::HalfEdge * > FindPositionInNode(DoublyConnectedEdgeList::HalfEdge &halfEdge)
返回一对 {prev, next},其中 prev/next 是围绕边的源节点逆时针方向的前一条/后一条边。即,边的位置介于 prev 和 next 之间
const DoublyConnectedEdgeList::Position & GetPosition() const