LCOV - code coverage report
Current view: top level - core/tess - SPTessTypes.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 505 685 73.7 %
Date: 2024-05-12 00:16:13 Functions: 63 88 71.6 %

          Line data    Source code
       1             : /**
       2             : Copyright (c) 2022 Roman Katuntsev <sbkarr@stappler.org>
       3             : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       4             : 
       5             : Permission is hereby granted, free of charge, to any person obtaining a copy
       6             : of this software and associated documentation files (the "Software"), to deal
       7             : in the Software without restriction, including without limitation the rights
       8             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       9             : copies of the Software, and to permit persons to whom the Software is
      10             : furnished to do so, subject to the following conditions:
      11             : 
      12             : The above copyright notice and this permission notice shall be included in
      13             : all copies or substantial portions of the Software.
      14             : 
      15             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      18             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      20             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      21             : THE SOFTWARE.
      22             : **/
      23             : 
      24             : #include "SPTessTypes.h"
      25             : #include "SPLog.h"
      26             : 
      27             : namespace STAPPLER_VERSIONIZED stappler::geom {
      28             : 
      29             : static constexpr VerboseFlag TessTypesVerbose = VerboseFlag::None;
      30             : static constexpr bool IntersectDebug = false;
      31             : static constexpr bool DictDebug = false;
      32             : 
      33             : int TessVerboseInfo = std::ios_base::xalloc();
      34             : 
      35    89880108 : bool EdgeDictNode::operator < (const EdgeDictNode &other) const {
      36    89880108 :         if (value.y == other.value.y) {
      37    11947265 :                 return edge->direction < other.edge->direction;
      38             :         } else {
      39    77932843 :                 return value.y < other.value.y;
      40             :         }
      41             : }
      42             : 
      43     2616737 : bool EdgeDictNode::operator < (const Edge &other) const {
      44     2616737 :         auto &left = other.getLeftVec();
      45     2617038 :         if (value.y == left.y) {
      46          20 :                 return edge->direction < other.direction; // dst.y
      47             :         } else {
      48     2617018 :                 return value.y < left.y;
      49             :         }
      50             : }
      51             : 
      52    14420123 : bool EdgeDictNode::operator < (const Vec2 &other) const {
      53    14420123 :         return value.y < other.y;
      54             : }
      55             : 
      56    10531885 : bool EdgeDictNode::operator <= (const EdgeDictNode &other) const {
      57    10531885 :         if (value.y == other.value.y) {
      58    10525113 :                 return value.w == other.value.w || edge->direction < other.edge->direction; // dst.y
      59             :         } else {
      60        6797 :                 return value.y < other.value.y;
      61             :         }
      62             : }
      63             : 
      64           0 : bool EdgeDictNode::operator== (const EdgeDictNode &other) const {
      65           0 :         return value.y == other.value.y && value.w == other.value.w;
      66             : }
      67             : 
      68     9584141 : void Vertex::insertBefore(HalfEdge *eOrig) {
      69     9584141 :         _edge = eOrig;
      70             : 
      71             :         /* fix other edges on this vertex loop */
      72             :         HalfEdge *e = eOrig;
      73             :         do {
      74     9584141 :                 e->setOrigin(this);
      75     9588701 :                 e = e->_originNext;
      76     9588701 :         } while( e != eOrig );
      77     9588701 : }
      78             : 
      79           0 : void Vertex::removeFromList(Vertex *newOrg) {
      80           0 :         HalfEdge *e, *eStart = _edge;
      81             :         e = eStart;
      82             :         do {
      83           0 :                 e->setOrigin(newOrg);
      84           0 :                 e = e->_originNext;
      85           0 :         } while( e != eStart );
      86           0 : }
      87             : 
      88           0 : void Vertex::foreach(const Callback<void(const HalfEdge &)> &cb) const {
      89           0 :         auto e = _edge;
      90             :         do {
      91           0 :                 cb(*e);
      92           0 :                 e = e->_originNext;
      93           0 :         } while( e != _edge );
      94           0 : }
      95             : 
      96      520400 : void Vertex::relocate(const Vec2 &vec) {
      97      520400 :         _origin = vec;
      98      520400 :         auto e = _edge;
      99             :         do {
     100     1041200 :                 e->origin = vec;
     101     1041200 :                 e = e->_originNext;
     102     1041200 :         } while( e != _edge );
     103      520400 : }
     104             : 
     105           0 : void FaceEdge::foreach(const Callback<void(const FaceEdge &)> &cb) const {
     106             :         auto e = this;
     107             :         do {
     108           0 :                 cb(*e);
     109           0 :                 e = e->_next;
     110           0 :         } while( e != this );
     111           0 : }
     112             : 
     113     9236827 : void HalfEdge::splitEdgeLoops(HalfEdge *eOrg, HalfEdge *eNew, Vertex *v) {
     114     9236827 :         eNew->sym()->copyOrigin(eOrg->sym());
     115     9242975 :         eOrg->sym()->setOrigin(v);
     116     9242747 :         eNew->setOrigin(v);
     117             : 
     118     9246556 :         HalfEdge *a = eOrg, *b = eOrg->sym(), // original edge
     119     9245900 :                         *c = eNew, *d = eNew->sym(), // new edge
     120     9248605 :                         *e = eOrg->_leftNext, // next edge in left loop
     121     9248605 :                         *g = b->_originNext, *h = g->sym(); // prev edge in right loop
     122             : 
     123     9250114 :         e->_originNext = d; d->_originNext = g; // vertex cycle around dest vertex;
     124     9250114 :         c->_originNext = b; b->_originNext = c; // cycle around new vertex;
     125     9250114 :         a->_leftNext = c; c->_leftNext = e; // left face loop
     126     9250114 :         h->_leftNext = d; d->_leftNext = b; // right face loop
     127     9250114 :         c->_winding = a->_winding; d->_winding = b->_winding;
     128     9250114 :         c->_realWinding = a->_realWinding; d->_realWinding = b->_realWinding;
     129     9250114 : }
     130             : 
     131      164824 : void HalfEdge::joinEdgeLoops(HalfEdge *eOrg, HalfEdge *oPrev) {
     132             :         // connect eOrg into vertex
     133      164824 :         HalfEdge *a = eOrg, *b = eOrg->sym(), // original edge
     134             :                                 *e = oPrev, // next edge in left loop
     135      164833 :                                 *g = oPrev->_originNext, *h = g->sym(); // prev edge in right loop
     136             : 
     137      164832 :         e->_originNext = b; b->_originNext = g; // cycle around new vertex;
     138      164832 :         a->_leftNext = e; h->_leftNext = b; // left and right loops
     139      164832 : }
     140             : 
     141   292313285 : HalfEdge *HalfEdge::sym() const {
     142   292313285 :         return (HalfEdge *)((char *)this - sizeof(HalfEdge) * isRight);
     143             : }
     144             : 
     145        1050 : uint32_t HalfEdge::getIndex() const {
     146        1050 :         return ((uintptr_t)this >> 5) % 1024;
     147             : }
     148             : 
     149    27919396 : void HalfEdge::setOrigin(const Vertex *v) {
     150    27919396 :         origin = v->_origin;
     151    27919396 :         vertex = v->_uniqueIdx;
     152    27919396 : }
     153             : 
     154    26459228 : void HalfEdge::copyOrigin(const HalfEdge *e) {
     155    26459228 :         origin = e->origin;
     156    26459228 :         vertex = e->vertex;
     157    26459228 : }
     158             : 
     159     2357178 : HalfEdge *HalfEdge::getOriginNext() const {
     160     2357178 :         return _originNext;
     161             : }
     162             : 
     163     1881165 : HalfEdge *HalfEdge::getOriginPrev() const {
     164     1881165 :         return sym()->_leftNext;
     165             : }
     166             : 
     167           0 : HalfEdge *HalfEdge::getDestinationNext() const {
     168           0 :         return sym()->_originNext->sym();
     169             : }
     170             : 
     171           0 : HalfEdge *HalfEdge::getDestinationPrev() const {
     172           0 :         return _leftNext->sym();
     173             : }
     174             : 
     175    54483625 : HalfEdge *HalfEdge::getLeftLoopNext() const {
     176    54483625 :         return _leftNext;
     177             : }
     178             : 
     179    40088845 : HalfEdge *HalfEdge::getLeftLoopPrev() const {
     180    40088845 :         return _originNext->sym();
     181             : }
     182             : 
     183           0 : HalfEdge *HalfEdge::getRightLoopNext() const {
     184           0 :         return sym()->_leftNext->sym();
     185             : }
     186             : 
     187           0 : HalfEdge *HalfEdge::getRightLoopPrev() const {
     188           0 :         return sym()->_originNext;
     189             : }
     190             : 
     191   121790555 : const Vec2 &HalfEdge::getOrgVec() const {
     192   121790555 :         return origin;
     193             : }
     194             : 
     195    85291366 : const Vec2 &HalfEdge::getDstVec() const {
     196    85291366 :         return sym()->origin;
     197             : }
     198             : 
     199           0 : float HalfEdge::getLength() const {
     200           0 :         return origin.distance(sym()->origin);
     201             : }
     202             : 
     203   177685542 : Edge *HalfEdge::getEdge() const {
     204   177685542 :         return (Edge *)((char *)this - sizeof(HalfEdge) * edgeOffset);
     205             : }
     206             : 
     207     9590838 : bool HalfEdge::goesLeft() const {
     208     9590838 :         return ((Edge *)((char *)this - sizeof(HalfEdge) * edgeOffset))->inverted != static_cast<bool>(edgeOffset);
     209             : }
     210             : 
     211    81641690 : bool HalfEdge::goesRight() const {
     212    81641690 :         return ((Edge *)((char *)this - sizeof(HalfEdge) * edgeOffset))->inverted == static_cast<bool>(edgeOffset);
     213             : }
     214             : 
     215     8719214 : void HalfEdge::foreachOnFace(const Callback<void(HalfEdge &)> &cb) {
     216             :         auto e = this;
     217             :         do {
     218    26081132 :                 cb(*e);
     219    26067988 :                 e = e->_leftNext;
     220    26067988 :         } while( e != this );
     221     8706070 : }
     222             : 
     223           0 : void HalfEdge::foreachOnVertex(const Callback<void(HalfEdge &)> &cb) {
     224             :         auto e = this;
     225             :         do {
     226           0 :                 cb(*e);
     227           0 :                 e = e->_originNext;
     228           0 :         } while( e != this );
     229           0 : }
     230             : 
     231           0 : void HalfEdge::foreachOnFace(const Callback<void(const HalfEdge &)> &cb) const {
     232             :         auto e = this;
     233             :         do {
     234           0 :                 cb(*e);
     235           0 :                 e = e->_leftNext;
     236           0 :         } while( e != this );
     237           0 : }
     238             : 
     239           0 : void HalfEdge::foreachOnVertex(const Callback<void(const HalfEdge &)> &cb) const {
     240             :         auto e = this;
     241             :         do {
     242           0 :                 cb(*e);
     243           0 :                 e = e->_originNext;
     244           0 :         } while( e != this );
     245           0 : }
     246             : 
     247           0 : float HalfEdge::getDirection() const {
     248           0 :         return getEdge()->direction;
     249             : }
     250             : 
     251    18092797 : Edge::Edge() {
     252    18122895 :         left.isRight = -1;
     253    18122895 :         left.edgeOffset = 0;
     254    18122895 :         left._originNext = &left;
     255    18122895 :         left._leftNext = &right;
     256    18122895 :         right.isRight = 1;
     257    18122895 :         right.edgeOffset = 1;
     258    18122895 :         right._originNext = &right;
     259    18122895 :         right._leftNext = &left;
     260    18122895 : }
     261             : 
     262    20913585 : const Vec2 &Edge::getLeftVec() const {
     263    20913585 :         return inverted ? right.getOrgVec() : left.getOrgVec();
     264             : }
     265             : 
     266    18307128 : const Vec2 &Edge::getRightVec() const {
     267    18307128 :         return inverted ? left.getOrgVec() : right.getOrgVec();
     268             : }
     269             : 
     270     9333321 : const Vec2 &Edge::getOrgVec() const {
     271     9333321 :         return left.origin;
     272             : }
     273             : 
     274     9331025 : const Vec2 &Edge::getDstVec() const {
     275     9331025 :         return right.origin;
     276             : }
     277             : 
     278           0 : uint32_t Edge::getLeftOrg() const {
     279           0 :         return inverted ? right.vertex : left.vertex;
     280             : }
     281             : 
     282    71838871 : uint32_t Edge::getRightOrg() const {
     283    71838871 :         return inverted ? left.vertex : right.vertex;
     284             : }
     285             : 
     286   120760638 : void Edge::updateInfo() {
     287   120760638 :         if (std::isnan(direction)) {
     288    18259756 :                 inverted = !EdgeGoesRight(&left);
     289    36595270 :                 direction = EdgeDirection(getRightVec() - getLeftVec());
     290             :         }
     291   120663478 : };
     292             : 
     293           0 : int16_t Edge::getLeftWinding() const {
     294           0 :         return inverted ? right._realWinding : left._realWinding;
     295             : }
     296             : 
     297           0 : int16_t Edge::getRightWinding() const {
     298           0 :         return inverted ? left._realWinding : right._realWinding;
     299             : }
     300             : 
     301      128404 : ObjectAllocator::ObjectAllocator(memory::pool_t *pool) : _pool(pool), _vertexes(pool) {
     302      128375 :         _vertexes.reserve(VertexSetPrealloc);
     303      128241 : }
     304             : 
     305    18127044 : Edge *ObjectAllocator::allocEdge() {
     306             :         Edge *edge = nullptr;
     307    18127044 :         if (!_freeEdges) {
     308      617138 :                 preallocateEdges(EdgeAllocBatch);
     309             :         }
     310             : 
     311    18126381 :         auto node = _freeEdges;
     312    18126381 :         _freeEdges = (Edge *)node->node;
     313    18126381 :         edge = new (node) Edge();
     314             : 
     315    18129706 :         return edge;
     316             : }
     317             : 
     318     9650888 : Vertex *ObjectAllocator::allocVertex() {
     319     9650888 :         Vertex *vertex = nullptr;
     320     9650888 :         if (!_freeVertexes) {
     321      362577 :                 preallocateVertexes(VertexAllocBatch);
     322             :         }
     323             : 
     324     9650543 :         auto node = _freeVertexes;
     325     9650543 :         _freeVertexes = (Vertex *)node->_edge;
     326     9650543 :         vertex = new (node) Vertex();
     327     9607122 :         vertex->_uniqueIdx = _vertexes.size();
     328             : 
     329     9572640 :         _vertexes.emplace_back(vertex);
     330             : 
     331     9578921 :         return vertex;
     332             : }
     333             : 
     334      113432 : FaceEdge *ObjectAllocator::allocFaceEdge() {
     335             :         FaceEdge *face = nullptr;
     336      113432 :         if (!_freeFaces) {
     337        7079 :                 preallocateFaceEdges(VertexAllocBatch);
     338             :         }
     339             : 
     340      113416 :         auto node = _freeFaces;
     341      113416 :         _freeFaces = node->_next;
     342      113416 :         face = new (node) FaceEdge();
     343      113076 :         return face;
     344             : }
     345             : 
     346      445925 : void ObjectAllocator::releaseEdge(Edge *eDel) {
     347      445925 :         removeEdgeFromVec(_edgesOfInterests, &eDel->left);
     348      445152 :         removeEdgeFromVec(_edgesOfInterests, &eDel->right);
     349      445139 :         removeEdgeFromVec(_faceEdges, &eDel->left);
     350      445214 :         removeEdgeFromVec(_faceEdges, &eDel->right);
     351             : 
     352      445250 :         auto lVertex = _vertexes[eDel->left.vertex];
     353      444814 :         if (lVertex && lVertex->_edge == &eDel->left) {
     354      159729 :                 lVertex->_edge = eDel->left._originNext;
     355             :         }
     356             : 
     357      444814 :         auto rVertex = _vertexes[eDel->right.vertex];
     358      444640 :         if (rVertex && rVertex->_edge == &eDel->right) {
     359         853 :                 rVertex->_edge = eDel->right._originNext;
     360             :         }
     361             : 
     362      444640 :         if (eDel->node) {
     363           0 :                 const_cast<EdgeDictNode *>(eDel->node)->edge = nullptr;
     364             :         }
     365             : 
     366      444640 :         eDel->~Edge();
     367             : 
     368      444640 :         eDel->node = (EdgeDictNode *)_freeEdges;
     369      444640 :         eDel->invalidated = true;
     370      444640 :         _freeEdges = eDel;
     371      444640 : }
     372             : 
     373           0 : void ObjectAllocator::releaseVertex(uint32_t vDelId, uint32_t vNewId) {
     374           0 :         auto it1 = _vertexes[vDelId];
     375           0 :         auto it2 = _vertexes[vNewId];
     376             : 
     377           0 :         if (it1 && it2) {
     378             :                 auto vDel = it1;
     379             : 
     380           0 :                 vDel->removeFromList(it2);
     381           0 :                 vDel->~Vertex();
     382           0 :                 _vertexes[vDelId] = nullptr;
     383             : 
     384           0 :                 vDel->_edge = (HalfEdge *)_freeVertexes;
     385           0 :                 _freeVertexes = vDel;
     386             :         }
     387           0 : }
     388             : 
     389      709350 : void ObjectAllocator::releaseVertex(Vertex *vDel) {
     390      709350 :         if (vDel) {
     391             :                 if constexpr (TessTypesVerbose != VerboseFlag::None) {
     392             :                         std::cout << "releaseVertex: " << vDel->_uniqueIdx << ": " << vDel->_exportIdx << "\n";
     393             :                 }
     394      707750 :                 if (vDel->_exportIdx != maxOf<uint32_t>()) {
     395           0 :                         _exportVertexes[vDel->_exportIdx] = nullptr;
     396             :                 }
     397             : 
     398      707739 :                 _vertexes[vDel->_uniqueIdx] = nullptr;
     399      707666 :                 vDel->~Vertex();
     400             : 
     401      707666 :                 vDel->_edge = (HalfEdge *)_freeVertexes;
     402      707666 :                 _freeVertexes = vDel;
     403             :         }
     404      709266 : }
     405             : 
     406      180602 : void ObjectAllocator::trimVertexes() {
     407             :         size_t offset = 0;
     408      186084 :         for (auto it = _vertexes.rbegin(); it != _vertexes.rend(); ++ it) {
     409      184651 :                 if (*it == nullptr) {
     410        5482 :                         ++ offset;
     411             :                 } else {
     412             :                         break;
     413             :                 }
     414             :         }
     415             : 
     416      180033 :         if (offset > 0) {
     417        2930 :                 _vertexes.resize(_vertexes.size() - offset);
     418             :         }
     419      180032 : }
     420             : 
     421      362513 : void ObjectAllocator::preallocateVertexes(uint32_t n) {
     422      362513 :         if (auto vertsMem = (Vertex *)memory::pool::palloc(_pool, sizeof(Vertex) * n)) {
     423    11944901 :                 for (uint32_t i = 0; i < n; ++ i) {
     424    11582880 :                         auto mem = vertsMem + i;
     425    11582880 :                         mem->_edge = (HalfEdge *)(mem + 1);
     426             :                 }
     427             : 
     428      362021 :                 Vertex *vtmp = _freeVertexes;
     429      362021 :                 _freeVertexes = vertsMem;
     430      362021 :                 (vertsMem + n - 1)->_edge = (HalfEdge *)vtmp;
     431             :         }
     432             : 
     433      362021 :         _vertexes.reserve(n);
     434      362207 :         _exportVertexes.reserve(n);
     435      362205 : }
     436             : 
     437      617163 : void ObjectAllocator::preallocateEdges(uint32_t n) {
     438      617163 :         if (auto edgesMem = (Edge *)memory::pool::palloc(_pool, sizeof(Edge) * n)) {
     439    20340266 :                 for (uint32_t i = 0; i < n; ++ i) {
     440    19723808 :                         auto mem = edgesMem + i;
     441    19723808 :                         mem->node = (EdgeDictNode *)(mem + 1);
     442             :                 }
     443             : 
     444      616458 :                 Edge *etmp = _freeEdges;
     445      616458 :                 _freeEdges = edgesMem;
     446      616458 :                 (edgesMem + n - 1)-> node = (EdgeDictNode *)(etmp);
     447             :         }
     448      616458 : }
     449             : 
     450        7075 : void ObjectAllocator::preallocateFaceEdges(uint32_t n) {
     451        7075 :         if (auto edgesMem = (FaceEdge *)memory::pool::palloc(_pool, sizeof(FaceEdge) * n)) {
     452      232659 :                 for (uint32_t i = 0; i < n; ++ i) {
     453      225600 :                         auto mem = edgesMem + i;
     454      225600 :                         mem->_next = (FaceEdge *)(mem + 1);
     455             :                 }
     456             : 
     457        7059 :                 FaceEdge *etmp = _freeFaces;
     458        7059 :                 _freeFaces = edgesMem;
     459        7059 :                 (edgesMem + n - 1)->_next = (FaceEdge *)(etmp);
     460             :         }
     461        7059 : }
     462             : 
     463     1780081 : void ObjectAllocator::removeEdgeFromVec(memory::vector<HalfEdge *> &vec, HalfEdge *e) {
     464     1780081 :         auto eOIt = std::find(vec.begin(), vec.end(), e);
     465     1779270 :         if (eOIt != vec.end()) {
     466          65 :                 *eOIt = nullptr;
     467             :         }
     468     1778653 : }
     469             : 
     470      128804 : VertexPriorityQueue::Heap::Heap(memory::pool_t *p, uint32_t s) : max(s), pool(p) {
     471      128804 :         nodes = (Node *)memory::pool::palloc(pool, (max + 1) * sizeof(Node));
     472      128670 :         handles = (Elem *)memory::pool::palloc(pool, (max + 1) * sizeof(Elem));
     473             : 
     474      128710 :         nodes[1].handle = 1; /* so that Minimum() returns NULL */
     475      128710 :         handles[1].key = nullptr;
     476      128710 : }
     477             : 
     478      128734 : VertexPriorityQueue::Heap::~Heap() {
     479      128734 :         memory::pool::free(pool, nodes, (max + 1) * sizeof(Node));
     480      128744 :         memory::pool::free(pool, handles, (max + 1) * sizeof(Elem));
     481      128761 : }
     482             : 
     483      128876 : void VertexPriorityQueue::Heap::init() {
     484             :         /* This method of building a heap is O(n), rather than O(n lg n). */
     485             : 
     486      128876 :         for (uint32_t i = size; i >= 1; --i) {
     487           0 :                 floatDown( i );
     488             :         }
     489             : 
     490      128876 :         initialized = true;
     491      128876 : }
     492             : 
     493             : /* returns INV_HANDLE iff out of memory */
     494       82426 : VertexPriorityQueue::Handle VertexPriorityQueue::Heap::insert(Key keyNew) {
     495             :         uint32_t curr;
     496             :         Handle free;
     497             : 
     498       82426 :         curr = ++size;
     499       82426 :         if ((curr * 2) > max) {
     500           0 :                 Node *saveNodes = nodes;
     501           0 :                 Elem *saveHandles = handles;
     502             : 
     503             :                 // If the heap overflows, double its size.
     504             :                 auto tmpSize = max;
     505             : 
     506           0 :                 max <<= 1;
     507             : 
     508           0 :                 nodes = (Node*) memory::pool::palloc(pool, ((max + 1) * sizeof(Node)));
     509           0 :                 if (nodes != NULL) {
     510           0 :                         memcpy(nodes, saveNodes, ((tmpSize + 1) * sizeof(Node)));
     511             :                 }
     512             : 
     513           0 :                 handles = (Elem*) memory::pool::palloc(pool, ((max + 1) * sizeof(Elem)));
     514           0 :                 if (handles != NULL) {
     515           0 :                         memcpy(handles, saveHandles, (size_t) ((tmpSize + 1) * sizeof(Elem)));
     516             :                 }
     517             : 
     518           0 :                 memory::pool::free(pool, saveNodes, (tmpSize + 1) * sizeof(Node));
     519           0 :                 memory::pool::free(pool, saveHandles, (tmpSize + 1) * sizeof(Elem));
     520             :         }
     521             : 
     522       82426 :         if (freeList == 0) {
     523       39060 :                 free = curr;
     524             :         } else {
     525             :                 free = freeList;
     526       43366 :                 freeList = handles[free].node;
     527             :         }
     528             : 
     529       82426 :         nodes[curr].handle = free;
     530       82426 :         handles[free].node = curr;
     531       82426 :         handles[free].key = keyNew;
     532             : 
     533       82426 :         if (initialized) {
     534       82422 :                 floatUp(curr);
     535             :         }
     536       82431 :         SPASSERT(free != InvalidHandle, "pqHeapInsert");
     537       82431 :         return free;
     538             : }
     539             : 
     540             : /* really pqHeapExtractMin */
     541      211100 : VertexPriorityQueue::Key VertexPriorityQueue::Heap::extractMin() {
     542      211100 :         Node *n = nodes;
     543      211100 :         Elem *h = handles;
     544      211100 :         Handle hMin = n[1].handle;
     545      211100 :         Key min = h[hMin].key;
     546             : 
     547      211100 :         if (size > 0) {
     548       82409 :                 n[1].handle = n[size].handle;
     549       82409 :                 h[n[1].handle].node = 1;
     550             : 
     551       82409 :                 h[hMin].key = NULL;
     552       82409 :                 h[hMin].node = freeList;
     553       82409 :                 freeList = hMin;
     554             : 
     555       82409 :                 if (--size > 0) {
     556       21354 :                         floatDown(1);
     557             :                 }
     558             :         }
     559      211100 :         if (min) {
     560       82408 :                 min->_queueHandle = maxOf<QueueHandle>();
     561             :         }
     562      211097 :         return min;
     563             : }
     564             : 
     565             : /* really pqHeapDelete */
     566           0 : void VertexPriorityQueue::Heap::remove(Handle hCurr) {
     567           0 :         Node *n = nodes;
     568           0 :         Elem *h = handles;
     569             :         uint32_t curr;
     570             : 
     571           0 :         SPASSERT( hCurr >= 1 && hCurr <= Handle(max) && h[hCurr].key != nullptr, "pqHeapDelete");
     572             : 
     573           0 :         curr = h[hCurr].node;
     574           0 :         n[curr].handle = n[size].handle;
     575           0 :         h[n[curr].handle].node = curr;
     576             : 
     577           0 :         if (curr <= --size) {
     578           0 :                 if (curr <= 1 || VertLeq(h[n[curr >> 1].handle].key, h[n[curr].handle].key)) {
     579           0 :                         floatDown(curr);
     580             :                 } else {
     581           0 :                         floatUp(curr);
     582             :                 }
     583             :         }
     584           0 :         h[hCurr].key = NULL;
     585           0 :         h[hCurr].node = freeList;
     586           0 :         freeList = hCurr;
     587           0 : }
     588             : 
     589             : 
     590       21354 : void VertexPriorityQueue::Heap::floatDown(int curr) {
     591       21354 :         Node *n = nodes;
     592       21354 :         Elem *h = handles;
     593             :         Handle hCurr, hChild;
     594             :         uint32_t child;
     595             : 
     596       21354 :         hCurr = n[curr].handle;
     597             :         for (;;) {
     598       23804 :                 child = curr << 1;
     599       23804 :                 if (child < size && VertLeq(h[n[child + 1].handle].key, h[n[child].handle].key)) {
     600             :                         ++child;
     601             :                 }
     602             : 
     603       23804 :                 SPASSERT(child <= this->max, "FloatDown");
     604             : 
     605       23804 :                 hChild = n[child].handle;
     606       23804 :                 if (child > size || VertLeq(h[hCurr].key, h[hChild].key)) {
     607       21354 :                         n[curr].handle = hCurr;
     608       21354 :                         h[hCurr].node = curr;
     609             :                         break;
     610             :                 }
     611        2450 :                 n[curr].handle = hChild;
     612        2450 :                 h[hChild].node = curr;
     613        2450 :                 curr = child;
     614             :         }
     615       21354 : }
     616             : 
     617       82424 : void VertexPriorityQueue::Heap::floatUp(int curr) {
     618       82424 :         Node *n = nodes;
     619       82424 :         Elem *h = handles;
     620             :         Handle hCurr, hParent;
     621             :         uint32_t parent;
     622             : 
     623       82424 :         hCurr = n[curr].handle;
     624             :         for (;;) {
     625       94073 :                 parent = curr >> 1;
     626       94073 :                 hParent = n[parent].handle;
     627       94073 :                 if (parent == 0 || VertLeq(h[hParent].key, h[hCurr].key)) {
     628       82424 :                         n[curr].handle = hCurr;
     629       82424 :                         h[hCurr].node = curr;
     630             :                         break;
     631             :                 }
     632       11649 :                 n[curr].handle = hParent;
     633       11649 :                 h[hParent].node = curr;
     634             :                 curr = parent;
     635             :         }
     636       82424 : }
     637             : 
     638      128888 : VertexPriorityQueue::VertexPriorityQueue(memory::pool_t *p, const memory::vector<Vertex *> &vec)
     639      128888 : : heap(p, vec.size()), max(vec.size()), pool(p) {
     640      128697 :         keys = (Key*) memory::pool::palloc(p, max * sizeof(Key));
     641             : 
     642     9719614 :         for (auto &v : vec) {
     643     9590368 :                 if (v) {
     644     9430816 :                         v->_queueHandle = insert(v);
     645     9431346 :                         if (v->_queueHandle == InvalidHandle) {
     646           0 :                                 return;
     647             :                         }
     648             :                 }
     649             :         }
     650             : 
     651      128888 :         if (init()) {
     652      128948 :                 initialized = true;
     653             :         }
     654           0 : }
     655             : 
     656      128713 : VertexPriorityQueue::~VertexPriorityQueue() {
     657      128713 :         memory::pool::free(pool, keys, max * sizeof(Key));
     658      128730 : }
     659             : 
     660             : 
     661             : #define LT(x,y)     (! VertLeq(y,x))
     662             : #define GT(x,y)     (! VertLeq(x,y))
     663             : #define KeySwap(a,b)   if(1){Key *tmp = *a; *a = *b; *b = tmp;}else
     664             : 
     665      128899 : bool VertexPriorityQueue::init() {
     666             :         Key **p, **r, **i, **j, *piv;
     667             :         struct {
     668             :                 Key **p, **r;
     669             :         } Stack[50], *top = Stack;
     670             :         unsigned int seed = 2016473283;
     671             : 
     672             :         /* Create an array of indirect pointers to the keys, so that we
     673             :          * the handles we have returned are still valid. */
     674             :         /*
     675             :          pq->order = (PQkey **)memAlloc( (size_t)
     676             :          (pq->size * sizeof(pq->order[0])) );
     677             :          */
     678      128899 :         order = (Key**) memory::pool::palloc(pool, size_t((size + 1) * sizeof(Key*)));
     679             : 
     680             :         p = order;
     681      128823 :         r = p + size - 1;
     682     9580064 :         for (piv = keys, i = p; i <= r; ++piv, ++i) {
     683     9451241 :                 *i = piv;
     684             :         }
     685             : 
     686             :         /* Sort the indirect pointers in descending order,
     687             :          * using randomized Quicksort */
     688      128823 :         top->p = p;
     689      128823 :         top->r = r;
     690             :         ++top;
     691     1723974 :         while (--top >= Stack) {
     692     1595151 :                 p = top->p;
     693     1595151 :                 r = top->r;
     694     3062539 :                 while (r > p + 10) {
     695     1467388 :                         seed = seed * 1539415821 + 1;
     696     1467388 :                         i = p + seed % (r - p + 1);
     697     1467388 :                         piv = *i;
     698     1467388 :                         *i = *p;
     699     1467388 :                         *p = piv;
     700     1467388 :                         i = p - 1;
     701     1467388 :                         j = r + 1;
     702             :                         do {
     703             :                                 do {
     704    25065100 :                                         ++i;
     705    25065100 :                                 } while (GT(**i, *piv));
     706             :                                 do {
     707    25893817 :                                         --j;
     708    25893817 :                                 } while (LT(**j, *piv));
     709    10241130 :                                 KeySwap(i, j);
     710    10241130 :                         } while (i < j);
     711     1467388 :                         KeySwap(i, j); /* Undo last swap */
     712     1467388 :                         if (i - p < r - j) {
     713      738393 :                                 top->p = j + 1;
     714      738393 :                                 top->r = r;
     715      738393 :                                 ++top;
     716             :                                 r = i - 1;
     717             :                         } else {
     718      728995 :                                 top->p = p;
     719      728995 :                                 top->r = i - 1;
     720      728995 :                                 ++top;
     721             :                                 p = j + 1;
     722             :                         }
     723             :                 }
     724             :                 /* Insertion sort small lists */
     725     9388158 :                 for (i = p + 1; i <= r; ++i) {
     726     7793007 :                         piv = *i;
     727    24195776 :                         for (j = i; j > p && LT(**(j - 1), *piv); --j) {
     728    16402769 :                                 *j = *(j - 1);
     729             :                         }
     730     7793007 :                         *j = piv;
     731             :                 }
     732             :         }
     733      128823 :         max = size;
     734      128823 :         initialized = true;
     735             : 
     736      128823 :         heap.init();
     737             : 
     738             : #ifndef NDEBUG
     739      128875 :         p = order;
     740      128875 :         r = p + size - 1;
     741     9448573 :         for (i = p; i < r; ++i) {
     742     9319578 :                 SPASSERT( VertLeq( **(i+1), **i ), "pqInit");
     743             :         }
     744             : #endif
     745             : 
     746      128935 :         return 1;
     747             : }
     748             : 
     749             : #undef LT
     750             : #undef GT
     751             : #undef KeySwap
     752             : 
     753           0 : bool VertexPriorityQueue::empty() const {
     754           0 :         return size == 0 && heap.empty();
     755             : }
     756             : 
     757     9513217 : VertexPriorityQueue::Handle VertexPriorityQueue::insert(Key keyNew) {
     758             :         int curr;
     759             : 
     760     9513217 :         if (initialized) {
     761       82428 :                 return heap.insert(keyNew);
     762             :         }
     763     9430789 :         curr = size;
     764     9430789 :         if( ++ size >= max ) {
     765       82973 :                 Key *saveKey = keys;
     766             :                 // If the heap overflows, double its size.
     767             :                 auto tmpSize = max;
     768       82973 :                 max <<= 1;
     769       82973 :                 keys = (Key*) memory::pool::palloc(pool, max * sizeof(Key));
     770       82968 :                 if (keys) {
     771       82968 :                         memcpy(keys, saveKey, (size_t) (tmpSize * sizeof(Key)));
     772             :                 }
     773             : 
     774       82968 :                 memory::pool::free(pool, saveKey, tmpSize * sizeof(Key));
     775             :         }
     776     9430786 :         SPASSERT(curr != InvalidHandle, "pqInsert");
     777     9430786 :         keys[curr] = keyNew;
     778             : 
     779             :         /* Negative handles index the sorted array. */
     780     9430786 :         return -(curr+1);
     781             : }
     782             : 
     783      278620 : void VertexPriorityQueue::remove(Handle curr) {
     784      278620 :         if (curr >= 0) {
     785           0 :                 heap.remove(curr);
     786           0 :                 return;
     787             :         }
     788      278620 :         curr = -(curr + 1);
     789      278620 :         SPASSERT(curr < Handle(max) && keys[curr] != nullptr, "pqDelete");
     790             : 
     791      278620 :         keys[curr] = nullptr;
     792      348232 :         while (size > 0 && *(order[size - 1]) == nullptr) {
     793       69612 :                 --size;
     794             :         }
     795             : }
     796             : 
     797     9258541 : VertexPriorityQueue::Key VertexPriorityQueue::extractMin() {
     798             :         Key sortMin, heapMin;
     799             : 
     800     9258541 :         if (size == 0) {
     801      128678 :                 return heap.extractMin();
     802             :         }
     803     9129863 :         sortMin = *(order[size - 1]);
     804     9129863 :         if (!heap.empty()) {
     805      254871 :                 heapMin = heap.getMin();
     806             :                 if (VertLeq(heapMin, sortMin)) {
     807       82406 :                         return heap.extractMin();
     808             :                 }
     809             :         }
     810             :         do {
     811     9222286 :                 --size;
     812     9222286 :         } while (size > 0 && *(order[size - 1]) == NULL);
     813     9047457 :         sortMin->_queueHandle = maxOf<QueueHandle>();
     814     9039735 :         return sortMin;
     815             : }
     816             : 
     817     9132747 : VertexPriorityQueue::Key VertexPriorityQueue::getMin() const {
     818             :         Key sortMin, heapMin;
     819             : 
     820     9132747 :         if (size == 0) {
     821      128075 :                 return heap.getMin();
     822             :         }
     823     9004672 :         sortMin = *(order[size - 1]);
     824     9004672 :         if (!heap.empty()) {
     825      193819 :                 heapMin = heap.getMin();
     826             :                 if (VertLeq(heapMin, sortMin)) {
     827       44343 :                         return heapMin;
     828             :                 }
     829             :         }
     830             :         return sortMin;
     831             : }
     832             : 
     833      128780 : EdgeDict::EdgeDict(memory::pool_t *p, uint32_t size) : nodes(p), pool(p) {
     834      128876 :         nodes.reserve(size);
     835      128858 :         nodes.set_memory_persistent(true);
     836      128869 : }
     837             : 
     838     9247375 : const EdgeDictNode * EdgeDict::push(Edge *edge, int16_t windingAbove) {
     839             :         if constexpr (DictDebug) {
     840             :                 std::cout << "\t\tDict push: " << *edge << "\n";
     841             :         }
     842             : 
     843             :         const EdgeDictNode *ret;
     844     9247375 :         auto &dst = edge->getDstVec();
     845     9249269 :         auto &org = edge->getOrgVec();
     846             : 
     847     9251190 :         if (org == event) {
     848     4781387 :                 auto norm = dst - event;
     849     4780115 :                 ret = & (*nodes.emplace(EdgeDictNode{
     850             :                         event, norm,
     851     4799155 :                         Vec4(event.x, event.y, dst.x, dst.y),
     852             :                         edge, windingAbove,
     853     4787163 :                         std::abs(norm.x) > std::numeric_limits<float>::epsilon()
     854     4791493 :                 }).first);
     855     4506891 :         } else if (dst == event) {
     856     4508837 :                 auto norm = org - event;
     857     4507490 :                 ret = & (*nodes.emplace(EdgeDictNode{
     858             :                         event, norm,
     859     4526563 :                         Vec4(event.x, event.y, org.x, org.y),
     860             :                         edge, windingAbove,
     861     4516794 :                         std::abs(norm.x) > std::numeric_limits<float>::epsilon()
     862     4518367 :                 }).first);
     863             :         } else {
     864             :                 ret = nullptr;
     865           0 :                 std::cout << "Fail to add edge: " << *edge << " for " << event << "\n";
     866             :         }
     867             : 
     868             :         /*for (auto &it : nodes) {
     869             :                 std::cout << "Edge: " << it.org << " - " << Vec2(it.value.z, it.value.w)
     870             :                                 << " - " << Vec2(it.value.x, it.value.y) << " - " << it.windingAbove << "\n";
     871             :         }*/
     872             : 
     873     9287605 :         return ret;
     874             : }
     875             : 
     876     9217373 : void EdgeDict::pop(const EdgeDictNode *node) {
     877             :         if constexpr (DictDebug) {
     878             :                 std::cout << "\t\tDict pop: " << *node->edge << "\n";
     879             :                 for (auto &it : nodes) {
     880             :                         std::cout << "\t\t\t\tpop: " << it << "\n";
     881             :                 }
     882             :         }
     883             : 
     884     9217373 :         auto it = nodes.lower_bound(*node);
     885     9184279 :         auto end = nodes.end();
     886    10558930 :         while (it != end && *it <= *node && &(*it) != node) {
     887     1369102 :                 ++ it;
     888             :         }
     889     9171142 :         if (it != end && &(*it) == node) {
     890     9167429 :                 it->edge->node = nullptr;
     891     9164612 :                 nodes.erase(it);
     892             :         }
     893     9149680 : }
     894             : 
     895     8874329 : void EdgeDict::update(Vertex *v, float tolerance) {
     896             :         if constexpr (DictDebug) {
     897             :                 for (auto &it : nodes) {
     898             :                         std::cout << "\t\t\t\tupdate: " << it << "\n";
     899             :                 }
     900             :         }
     901             : 
     902     8874329 :         event = v->_origin;
     903     8874329 :         auto it = nodes.begin();
     904    77821278 :         while (it != nodes.end()) {
     905    69020289 :                 auto &n = *it;
     906    68712324 :                 if (it->edge->getRightOrg() == v->_uniqueIdx) {
     907             :                         //if (n.helper.type == VertexType::Merge) {
     908     9259196 :                                 n.value.x = n.value.z;
     909     9259196 :                                 n.value.y = n.value.w;
     910             :                         /*} else {
     911             :                                 if constexpr (DictDebug) {
     912             :                                         std::cout << "\t\t\tDict pop (v): " << *it->edge << "\n";
     913             :                                 }
     914             :                                 it->edge->node = nullptr;
     915             :                                 it = nodes.erase(it);
     916             :                                 continue;
     917             :                         }*/
     918    59829021 :                 } else if (n.horizontal) {
     919    59825784 :                         const float tValue = (event.x - n.org.x) / (n.norm.x);
     920             :                         // std::cout << "\t\t\t: " << *it->edge << " " << tValue << "\n";
     921    59825784 :                         if (tValue < 0.0f || tValue > 1.0f) {
     922             :                                 if constexpr (DictDebug) {
     923             :                                         std::cout << "\t\t\tDict pop (t): " << *it->edge << "\n";
     924             :                                 }
     925       60199 :                                 it->edge->node = nullptr;
     926       60198 :                                 it = nodes.erase(it);
     927       70157 :                                 continue;
     928             :                         } else {
     929    59765585 :                                 n.value.x = n.org.x + n.norm.x * tValue;
     930    59765585 :                                 n.value.y = n.org.y + n.norm.y * tValue;
     931             :                         }
     932             :                 } else {
     933        3237 :                         const float sValue = (event.y - n.org.y) / (n.norm.y);
     934             :                         // std::cout << "\t\t\t: " << *it->edge << " " << sValue << "\n";
     935        3237 :                         if (sValue < 0.0f || sValue > 1.0f) {
     936             :                                 if constexpr (DictDebug) {
     937             :                                         std::cout << "\t\t\tDict pop (s): " << *it->edge << "\n";
     938             :                                 }
     939        2772 :                                 it->edge->node = nullptr;
     940        2773 :                                 it = nodes.erase(it);
     941        2771 :                                 continue;
     942             :                         } else {
     943         465 :                                 n.value.x = n.org.x + n.norm.x * sValue;
     944         465 :                                 n.value.y = n.org.y + n.norm.y * sValue;
     945             :                         }
     946             :                 }
     947             : 
     948    69025246 :                 auto curr = n.current();
     949    69237974 :                 auto dst = n.dst();
     950    69334094 :                 if (curr.x == dst.x && std::abs(curr.y - dst.y) < tolerance) {
     951    12565039 :                         if (n.value.y < event.y) {
     952             :                                 if constexpr (DictDebug) {
     953             :                                         std::cout << "\t\t\tDict pop (y): " << *it->edge << "\n";
     954             :                                 }
     955        7195 :                                 it->edge->node = nullptr;
     956        7197 :                                 it = nodes.erase(it);
     957        7189 :                                 continue;
     958             :                         }
     959             :                 }
     960             : 
     961    69313511 :                 ++ it;
     962             :         }
     963     8924981 : }
     964             : 
     965     8925396 : const EdgeDictNode * EdgeDict::checkForIntersects(Vertex *v, Vec2 &intersectPoint, IntersectionEvent &ev, float tolerance) const {
     966     8925396 :         if (nodes.empty()) {
     967             :                 return nullptr;
     968             :         }
     969             : 
     970     8769788 :         auto &org = v->_origin;
     971             : 
     972             :         if constexpr (IntersectDebug) {
     973             :                 std::cout << "\t\t\t\tcheckForIntersects: " << *v << "\n";
     974             :         }
     975             : 
     976    78447868 :         for (auto &n : nodes) {
     977    69099624 :                 auto nCurr = n.current();
     978    69429510 :                 auto nDst = n.dst();
     979             : 
     980             :                 if constexpr (IntersectDebug) {
     981             :                         std::cout << "\t\t\t\t\t: " << *n.edge << "\n";
     982             :                 }
     983             : 
     984    69676473 :                 if (VertEq(nCurr, org, tolerance) && !VertEq(n.org, org, tolerance)) {
     985     9321821 :                         if (VertEq(nCurr, nDst, tolerance)) {
     986     9321217 :                                 continue; // no intersection, just line end
     987             :                         }
     988         604 :                         intersectPoint = event;
     989         604 :                         ev = IntersectionEvent::EventIsIntersection;
     990         604 :                         return &n;
     991             :                 }
     992             :         }
     993             : 
     994     8807107 :         return nullptr;
     995             : }
     996             : 
     997     9413359 : const EdgeDictNode * EdgeDict::checkForIntersects(HalfEdge *edge, Vec2 &intersectPoint, IntersectionEvent &ev, float tolerance) const {
     998     9413359 :         if (nodes.empty()) {
     999             :                 return nullptr;
    1000             :         }
    1001             : 
    1002     9102096 :         auto &org = edge->getOrgVec(); // == event
    1003     9105414 :         auto &dst = edge->getDstVec();
    1004             : 
    1005     9109314 :         auto simdVec1 = simd::load(org.x, org.y, dst.x, dst.y);
    1006             : 
    1007             :         if constexpr (IntersectDebug) {
    1008             :                 std::cout << "\t\t\t\tcheckForIntersects: " << *edge << "\n";
    1009             :         }
    1010             : 
    1011    81284520 :         for (auto &n : nodes) {
    1012    71606287 :                 auto nCurr = n.current();
    1013    71921978 :                 auto nDst = n.dst();
    1014             :                 if constexpr (IntersectDebug) {
    1015             :                         std::cout << "\t\t\t\t\t: " << *n.edge << "\n";
    1016             :                 }
    1017             :                 // overlap check should be made in mergeVertexes
    1018             :                 // so, should never happen
    1019   144095064 :                 if (VertEq(n.org, org, tolerance) || VertEq(nDst, org, tolerance)) {
    1020     9265996 :                         continue; // common org, not interested
    1021    64410201 :                 } else if (VertEq(nCurr, org, tolerance)) {
    1022           0 :                         if (VertEq(nCurr, nDst, tolerance)) {
    1023           0 :                                 continue; // no intersection, just line end
    1024             :                         }
    1025           0 :                         intersectPoint = event;
    1026           0 :                         ev = IntersectionEvent::EventIsIntersection;
    1027       82664 :                         return &n;
    1028             :                 }
    1029             : 
    1030    64433121 :                 if (VertEq(dst, nDst, tolerance)) {
    1031     1449410 :                         continue; // common dst
    1032             :                 }
    1033             : 
    1034             :                 simd::f32x4 intersect;
    1035             :                 if (simd::isVec2BboxIntersects(simdVec1, simd::load(&n.value.x), intersect)) {
    1036             :                         Vec4 isect; simd::store(&isect.x, intersect);
    1037    31829677 :                         if (VertEq(nCurr, nDst, tolerance)) {
    1038       55096 :                                 if (std::abs(isect.x) < tolerance) {
    1039         349 :                                         if (std::abs(isect.y) < tolerance) {
    1040           0 :                                                 intersectPoint = nCurr;
    1041           0 :                                                 ev = IntersectionEvent::EdgeConnection1; // n ends on edge;
    1042           0 :                                                 return &n;
    1043             :                                         }
    1044             :                                 } else {
    1045       54729 :                                         auto S = (nDst.x - org.x) / (isect.x);
    1046       54729 :                                         if (S >= 0.0f && S <= 1.0f) {
    1047       54713 :                                                 auto y = org.y + S * isect.y;
    1048       54713 :                                                 if (std::abs(nDst.y - y) <= tolerance) {
    1049           0 :                                                         intersectPoint = nCurr;
    1050           0 :                                                         ev = IntersectionEvent::EdgeConnection1; // n ends on edge;
    1051           0 :                                                         return &n;
    1052             :                                                 }
    1053             :                                         }
    1054             :                                 }
    1055             :                                 continue;
    1056       55078 :                         }
    1057             : 
    1058    31774581 :                         const float denom = isect.w * isect.x - isect.z * isect.y; // crossProduct2Vector(A, B, C, D);
    1059    31774581 :                         if (denom != 0.0f) {
    1060    30360811 :                                 const auto CAx = org.x - n.value.x;
    1061    30360811 :                                 const auto CAy = org.y - n.value.y;
    1062             : 
    1063    30360811 :                                 auto S = (CAy * isect.z - CAx * isect.w) / denom;
    1064    30360811 :                                 auto T = (CAy * isect.x - CAx * isect.y) / denom;
    1065             : 
    1066             :                                 //if (S > 0.5f) { S = 1.0f - S; }
    1067             :                                 //if (T > 0.5f) { T = 1.0f - T; }
    1068             : 
    1069    30360811 :                                 if (S >= 0.0f && S <= 1.0f && T >= 0.0f && T <= 1.0f) {
    1070       82666 :                                         intersectPoint = Vec2(org.x + S * isect.x, org.y + S * isect.y);
    1071       82667 :                                         if (VertEq(intersectPoint, dst, tolerance)) {
    1072         134 :                                                 ev = IntersectionEvent::EdgeConnection2; // edge ends on n;
    1073       82530 :                                         } else if (VertEq(intersectPoint, nDst, tolerance)) {
    1074         107 :                                                 intersectPoint = nDst;
    1075         107 :                                                 ev = IntersectionEvent::EdgeConnection1; // n ends on edge;
    1076             :                                         } else {
    1077       82423 :                                                 ev = IntersectionEvent::Regular;
    1078             :                                         }
    1079       82664 :                                         return &n;
    1080             :                                 }
    1081             :                         }
    1082             :                 }
    1083             :         }
    1084             : 
    1085     9043131 :         return nullptr;
    1086             : }
    1087             : 
    1088      991510 : const EdgeDictNode * EdgeDict::getEdgeBelow(const Edge *e) const {
    1089             :         if constexpr (DictDebug) {
    1090             :                 auto nIt = nodes.begin();
    1091             :                 while (nIt != nodes.end()) {
    1092             :                         std::cout << "\t\t\t\t" << (void *)nIt._node << " " << *nIt << "\n";
    1093             :                         ++ nIt;
    1094             :                 }
    1095             :         }
    1096             : 
    1097      991510 :         if (nodes.empty()) {
    1098             :                 return nullptr;
    1099             :         }
    1100             : 
    1101      848059 :         auto it = nodes.lower_bound(*e); // first not less then e
    1102      847713 :         if (it == nodes.begin()) {
    1103             :                 // first edge in dict greater or equal then e, no edges below
    1104             :                 return nullptr;
    1105             :         } else {
    1106      773826 :                 -- it;
    1107      773897 :                 while (it != nodes.begin() && it->current() == event) {
    1108           0 :                         -- it;
    1109             :                 }
    1110             :                 // edge before it is less then e
    1111      774012 :                 return &(*it);
    1112             :         }
    1113             : }
    1114             : 
    1115     4453512 : const EdgeDictNode * EdgeDict::getEdgeBelow(const Vec2 &vec, uint32_t vertex) const {
    1116             :         if constexpr (DictDebug) {
    1117             :                 for (auto &it : nodes) {
    1118             :                         std::cout << "\t\t\t\t" << it << "\n";
    1119             :                 }
    1120             :         }
    1121             : 
    1122     4453512 :         if (nodes.empty()) {
    1123             :                 return nullptr;
    1124             :         }
    1125             : 
    1126     4448645 :         auto it = nodes.lower_bound(vec); // first not less then e
    1127     4440681 :         if (it == nodes.begin()) {
    1128             :                 // first edge in dict greater or equal then e, no edges below
    1129             :                 return nullptr;
    1130             :         } else {
    1131     4438020 :                 -- it;
    1132     4440804 :                 while (it != nodes.begin() && (it->edge->getRightOrg() == vertex || it->current() == vec)) {
    1133           4 :                         -- it;
    1134             :                 }
    1135             :                 // edge before it is less then e
    1136     4447359 :                 return &(*it);
    1137             :         }
    1138             : }
    1139             : 
    1140           0 : std::ostream &operator<<(std::ostream &out, const Vertex &v) {
    1141           0 :         switch (VerboseFlag(out.iword( TessVerboseInfo ))) {
    1142           0 :         case VerboseFlag::None:
    1143           0 :                 out << "Vertex (" << v._uniqueIdx << ") : " << v._origin;
    1144           0 :                 break;
    1145           0 :         case VerboseFlag::General:
    1146           0 :                 out << "Vertex (" << v._uniqueIdx << ") : " << v._origin;
    1147           0 :                 break;
    1148           0 :         case VerboseFlag::Full:
    1149           0 :                 out << "Vertex (" << v._uniqueIdx << ") : " << v._origin << "\n";
    1150           0 :                 v.foreach([&] (const HalfEdge &e) {
    1151           0 :                         Vec2 orgVec = e.origin;
    1152           0 :                         Vec2 dstVec = e.sym()->origin;
    1153           0 :                         uint32_t orgIdx = e.vertex;
    1154           0 :                         uint32_t dstIdx = e.sym()->vertex;
    1155             : 
    1156           0 :                         out << "\tEdge (" << e.getIndex() << ":" << e.sym()->getIndex() << ") : " << orgVec << " - " << dstVec << "\n";
    1157           0 :                         out << "\t\tDir: (" << e.getIndex() << "; org: " << orgIdx << "; left: " << e._leftNext->getIndex()
    1158           0 :                                         << "; ccw: " << e._originNext->getIndex() << ")\n";
    1159           0 :                         out << "\t\tSym: (" << e.sym()->getIndex() << "; org: " << dstIdx << "; left: " << e.sym()->_leftNext->getIndex()
    1160           0 :                                         << "; ccw: " << e.sym()->_originNext->getIndex() << ")\n";
    1161           0 :                 });
    1162           0 :                 break;
    1163             :         }
    1164             : 
    1165           0 :         return out;
    1166             : }
    1167             : 
    1168         525 : std::ostream &operator<<(std::ostream &out, const HalfEdge &e) {
    1169         525 :         Vec2 orgVec = e.origin;
    1170         525 :         Vec2 dstVec = e.sym()->origin;
    1171         525 :         uint32_t orgIdx = e.vertex;
    1172         525 :         uint32_t dstIdx = e.sym()->vertex;
    1173             : 
    1174         525 :         switch (VerboseFlag(out.iword( TessVerboseInfo ))) {
    1175         525 :         case VerboseFlag::None:
    1176         525 :                 out << "Edge (" << e.getIndex() << ":" << e.sym()->getIndex() << ") : " << orgVec << " - " << dstVec
    1177         525 :                         << "; " << e.vertex << " - " << e.sym()->vertex;
    1178             :                 break;
    1179           0 :         case VerboseFlag::General:
    1180           0 :                 out << "Edge (" << e.getIndex() << ":" << e.sym()->getIndex() << ") : " << orgVec << " - " << dstVec
    1181           0 :                         << "; " << e.vertex << " - " << e.sym()->vertex
    1182           0 :                         << " winding: " << e._realWinding << ":" << e._winding << ";";
    1183           0 :                 if (e.goesLeft()) {
    1184           0 :                         out << " goes left; ";
    1185           0 :                 } else if (e.goesRight()) {
    1186           0 :                         out << " goes right; ";
    1187             :                 } else {
    1188           0 :                         out << " unknown direction; ";
    1189             :                 }
    1190           0 :                 out << (void *)&e;
    1191             :                 break;
    1192           0 :         case VerboseFlag::Full:
    1193           0 :                 out << "Edge (" << e.getIndex() << ":" << e.sym()->getIndex() << ") : " << orgVec << " - " << dstVec
    1194           0 :                         << "; " << e.vertex << " - " << e.sym()->vertex
    1195           0 :                         << " winding: " << e._realWinding << ":" << e._winding << ";\n";
    1196           0 :                 out << "\tDir: (" << e.getIndex() << "; org: " << orgIdx << "; left: " << e._leftNext->getIndex()
    1197           0 :                                 << "; ccw: " << e._originNext->getIndex() << ")";
    1198           0 :                 if (e.goesLeft()) {
    1199           0 :                         out << " goes left;";
    1200           0 :                 } else if (e.goesRight()) {
    1201           0 :                         out << " goes right;";
    1202             :                 } else {
    1203           0 :                         out << " unknown direction;";
    1204             :                 }
    1205           0 :                 out << "\n";
    1206           0 :                 out << "\tSym: (" << e.sym()->getIndex() << "; org: " << dstIdx << "; left: " << e.sym()->_leftNext->getIndex()
    1207           0 :                                 << "; ccw: " << e.sym()->_originNext->getIndex() << ")";
    1208           0 :                 if (e.sym()->goesLeft()) {
    1209           0 :                         out << " goes left; ";
    1210           0 :                 } else if (e.sym()->goesRight()) {
    1211           0 :                         out << " goes right; ";
    1212             :                 } else {
    1213           0 :                         out << " unknown direction; ";
    1214             :                 }
    1215           0 :                 out << (void *)&e << "\n";
    1216             :                 break;
    1217             :         }
    1218         525 :         return out;
    1219             : }
    1220             : 
    1221           0 : std::ostream &operator<<(std::ostream &out, const FaceEdge &e) {
    1222           0 :         Vec2 orgVec = e._vertex->_origin;
    1223           0 :         Vec2 dstVec = e._next->_vertex->_origin;
    1224           0 :         uint32_t orgIdx = e._vertex->_uniqueIdx;
    1225           0 :         uint32_t dstIdx = e._next->_vertex->_uniqueIdx;
    1226           0 :         out << "FaceEdge (" << orgIdx << " - " << dstIdx << ") : " << orgVec << " - " << dstVec << ";";
    1227           0 :         return out;
    1228             : }
    1229             : 
    1230           0 : std::ostream &operator<<(std::ostream &stream, VerboseFlag e) {
    1231           0 :         stream.iword( TessVerboseInfo ) = toInt(e);
    1232           0 :         return stream;
    1233             : }
    1234             : 
    1235           0 : std::ostream &operator<<(std::ostream &stream, const EdgeDictNode &e) {
    1236           0 :         stream << "EdgeDictNode(" << e.org << "; " << e.dst() << "; cur: " << e.current() << ");";
    1237           0 :         return stream;
    1238             : }
    1239             : 
    1240           0 : std::ostream &operator<<(std::ostream &stream, const Edge &e) {
    1241           0 :         if (e.inverted) {
    1242           0 :                 stream << e.right;
    1243             :         } else {
    1244           0 :                 stream << e.left;
    1245             :         }
    1246           0 :         return stream;
    1247             : }
    1248             : 
    1249             : }

Generated by: LCOV version 1.14