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();
41 static std::pair<DoublyConnectedEdgeList::HalfEdge *, DoublyConnectedEdgeList::HalfEdge *>
46 auto normalize = [](
auto a) {
47 constexpr float twoPi = 2.0 * 3.14159265359;
49 while (a >= 1.0) a -= 1.0;
50 while (a < 0.0) a += 1.0;
53 auto angle = Dcel::GetAngle(halfEdge);
54 std::map<
decltype(angle), Dcel::HalfEdge *> edgeMap;
56 auto &firstHalfEdge = Dcel::GetLeavingHalfEdge(Dcel::GetSource(halfEdge));
57 auto *edge = &firstHalfEdge;
59 if (edge != &halfEdge) {
61 auto a = normalize(alpha - angle);
62 edgeMap.insert({a, edge});
64 edge = &Dcel::GetNextInNode(*edge);
65 }
while (edge != &firstHalfEdge);
66 check(!edgeMap.empty());
67 return {edgeMap.rbegin()->second, edgeMap.begin()->second};
81 Nodes.emplace_back(Position0);
82 Nodes.emplace_back(Position1);
104#ifdef CARLA_ROAD_GENERATOR_EXTRA_LOG
117 Nodes.emplace_back(NodePosition);
118 auto &newNode =
Nodes.back();
124 edge0.Source = &newNode;
125 edge0.Target = &OtherNode;
128 edge1.Source = &OtherNode;
129 edge1.Target = &newNode;
140 edge1.Face = next->
Face;
144 newNode.LeavingHalfEdge = &edge0;
158 auto &newNode =
Nodes.back();
160 auto &node0 = *edge.
Source;
163 edge0.Source = &newNode;
164 edge0.Target = &node0;
169 edge1.Source = &node0;
170 edge1.Target = &newNode;
188 node0.LeavingHalfEdge = &edge1;
189 newNode.LeavingHalfEdge = &edge0;
198 Faces.emplace_back();
199 auto &newFace =
Faces.back();
205 edge0.Source = &Node0;
206 edge0.Target = &Node1;
208 edge1.Source = &Node1;
209 edge1.Target = &Node0;
227 auto &oldFace = *next1->
Face;
229 newFace.HalfEdge = &edge1;
232 auto fixFace = [](
Face &face) {
234 auto *edge = &firstEdge;
238 }
while (edge != &firstEdge);
253 auto dir = trg - src;
254 return std::atan2(
static_cast<double>(dir.y),
static_cast<double>(dir.x));
257#ifdef CARLA_ROAD_GENERATOR_EXTRA_LOG
259 void DoublyConnectedEdgeList::PrintToLog()
const
261 std::wstringstream sout;
263 sout <<
"iterate all nodes: ";
265 auto p = node.GetPosition();
266 sout << node <<
"{" << p.x <<
"," << p.y <<
"} ";
271 sout <<
"iterate all faces: ";
278 sout <<
"iterate all edges: ";
283 sout << edge <<
"{" << src <<
"->" << trg <<
"," << face <<
"} ";
288 sout <<
"iterate nodes in face: ";
290 sout << face <<
"{ ";
292 const auto *edge = &firstEdge;
296 }
while (edge != &firstEdge);
302 sout <<
"iterate edges in node: ";
304 sout << node <<
"{ ";
306 const auto *edge = &firstEdge;
310 }
while (edge != &firstEdge);
315 UE_LOG(LogCarla, Log, TEXT(
"\n%s"), sout.str().c_str());
Simple doubly-connected edge list structure.
ListView< FaceIterator > GetFaces()
Node & AddNode(const Position &NodePosition, Node &OtherNode)
{
Face & ConnectNodes(Node &Node0, Node &Node1)
Connect two nodes by a pair of edges.
ListView< HalfEdgeIterator > GetHalfEdges()
HalfEdgeContainer HalfEdges
DoublyConnectedEdgeList(const Position &Position0, const Position &Position1)
Create a DoublyConnectedEdgeList with two nodes, two edges and one face.
static float GetAngle(const HalfEdge &halfEdge)
Return the angle [-pi, pi] of the half-edge.
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)
Split HalfEdge (and its pair) at Position.
static std::pair< DoublyConnectedEdgeList::HalfEdge *, DoublyConnectedEdgeList::HalfEdge * > FindPositionInNode(DoublyConnectedEdgeList::HalfEdge &halfEdge)
Return the pair {prev, next}, where prev/next is the previous/next edge counterclockwise around edge'...
const DoublyConnectedEdgeList::Position & GetPosition() const