mirror of
https://github.com/mapbox/tippecanoe.git
synced 2025-03-23 20:35:16 +00:00
Upgrade to Clipper 3eb6a85910aff
This commit is contained in:
parent
707036fe79
commit
a989611515
2
Makefile
2
Makefile
@ -3,7 +3,7 @@ MANDIR ?= $(PREFIX)/share/man/man1/
|
||||
|
||||
# inherit from env if set
|
||||
CC := $(CC)
|
||||
CXX := $(CXX)
|
||||
CXX := $(CXX) -std=c++11
|
||||
CFLAGS := $(CFLAGS)
|
||||
CXXFLAGS := $(CXXFLAGS)
|
||||
LDFLAGS := $(LDFLAGS)
|
||||
|
@ -1704,6 +1704,17 @@ bool Clipper::ExecuteInternal()
|
||||
if (m_StrictSimple)
|
||||
{
|
||||
DoSimplePolygons();
|
||||
m_StrictSimple = false;
|
||||
for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i)
|
||||
{
|
||||
OutRec *outRec = m_PolyOuts[i];
|
||||
if (!outRec->Pts || outRec->IsOpen)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
FixupOutPolygon(*outRec);
|
||||
}
|
||||
m_StrictSimple = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2651,9 +2662,13 @@ OutPt* Clipper::GetLastOutPt(TEdge *e)
|
||||
|
||||
void Clipper::ProcessHorizontals()
|
||||
{
|
||||
TEdge* horzEdge;
|
||||
while (PopEdgeFromSEL(horzEdge))
|
||||
ProcessHorizontal(horzEdge);
|
||||
m_Maxima.sort();
|
||||
TEdge* horzEdge;
|
||||
while (PopEdgeFromSEL(horzEdge))
|
||||
{
|
||||
ProcessHorizontal(horzEdge);
|
||||
}
|
||||
m_Maxima.clear();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@ -3180,6 +3195,7 @@ void Clipper::DoMaxima(TEdge *e)
|
||||
void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
|
||||
{
|
||||
TEdge* e = m_ActiveEdges;
|
||||
MaximaList next_maxima;
|
||||
while( e )
|
||||
{
|
||||
//1. process maxima, treating them as if they're 'bent' horizontal edges,
|
||||
@ -3194,7 +3210,11 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
|
||||
|
||||
if(IsMaximaEdge)
|
||||
{
|
||||
if (m_StrictSimple) m_Maxima.push_back(e->Top.X);
|
||||
if (m_StrictSimple)
|
||||
{
|
||||
m_Maxima.push_back(e->Top.X);
|
||||
next_maxima.push_back(e->Top.X);
|
||||
}
|
||||
TEdge* ePrev = e->PrevInAEL;
|
||||
DoMaxima(e);
|
||||
if( !ePrev ) e = m_ActiveEdges;
|
||||
@ -3244,11 +3264,25 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
|
||||
e = e->NextInAEL;
|
||||
}
|
||||
}
|
||||
if (m_StrictSimple)
|
||||
{
|
||||
MinimaList::iterator lm = m_CurrentLM;
|
||||
while (lm != m_MinimaList.end() && lm->Y == topY)
|
||||
{
|
||||
if (lm->LeftBound && lm->RightBound)
|
||||
{
|
||||
m_Maxima.push_back(lm->LeftBound->Bot.X);
|
||||
}
|
||||
++lm;
|
||||
}
|
||||
}
|
||||
|
||||
//3. Process horizontals at the Top of the scanbeam ...
|
||||
m_Maxima.sort();
|
||||
ProcessHorizontals();
|
||||
m_Maxima.clear();
|
||||
if (m_StrictSimple && !next_maxima.empty())
|
||||
{
|
||||
m_Maxima.insert(m_Maxima.end(), next_maxima.begin(), next_maxima.end());
|
||||
}
|
||||
|
||||
//4. Promote intermediate vertices ...
|
||||
e = m_ActiveEdges;
|
||||
@ -4466,6 +4500,264 @@ struct OutPtIntersect
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool Clipper::FindIntersectLoop(std::unordered_multimap<int, OutPtIntersect> & dupeRec,
|
||||
std::list<std::pair<const int, OutPtIntersect> > & iList,
|
||||
OutRec * outRec_parent,
|
||||
int idx_origin,
|
||||
int idx_prev,
|
||||
int idx_search)
|
||||
{
|
||||
auto range = dupeRec.equal_range(idx_search);
|
||||
// Check for direct connection
|
||||
for (auto it = range.first; it != range.second; ++it)
|
||||
{
|
||||
OutRec * itRec = GetOutRec(it->second.op2->Idx);
|
||||
if (itRec->Idx == idx_prev)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (itRec->Idx == idx_origin && (outRec_parent == itRec || outRec_parent == ParseFirstLeft(itRec->FirstLeft)))
|
||||
{
|
||||
iList.emplace_front(idx_search, it->second);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Check for connection through chain of other intersections
|
||||
for (auto it = range.first; it != range.second; ++it)
|
||||
{
|
||||
OutRec * itRec = GetOutRec(it->second.op2->Idx);
|
||||
if (itRec->Idx == idx_search || itRec->Idx == idx_prev ||
|
||||
(outRec_parent != itRec && outRec_parent != ParseFirstLeft(itRec->FirstLeft)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (FindIntersectLoop(dupeRec, iList, outRec_parent, idx_origin, idx_search, itRec->Idx))
|
||||
{
|
||||
iList.emplace_front(idx_search, it->second);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool Clipper::FixIntersects(std::unordered_multimap<int, OutPtIntersect> & dupeRec,
|
||||
OutPt * op_j,
|
||||
OutPt * op_k,
|
||||
OutRec * outRec_j,
|
||||
OutRec * outRec_k)
|
||||
{
|
||||
if (!outRec_j->IsHole && !outRec_k->IsHole)
|
||||
{
|
||||
// Both are not holes, return nothing to do.
|
||||
return false;
|
||||
}
|
||||
OutRec * outRec_origin;
|
||||
OutRec * outRec_search;
|
||||
OutRec * outRec_parent;
|
||||
OutPt * op_origin_1;
|
||||
OutPt * op_origin_2;
|
||||
if (!outRec_j->IsHole)
|
||||
{
|
||||
outRec_origin = outRec_j;
|
||||
outRec_parent = outRec_origin;
|
||||
outRec_search = outRec_k;
|
||||
op_origin_1 = op_j;
|
||||
op_origin_2 = op_k;
|
||||
}
|
||||
else if (!outRec_k->IsHole)
|
||||
{
|
||||
outRec_origin = outRec_k;
|
||||
outRec_parent = outRec_origin;
|
||||
outRec_search = outRec_k;
|
||||
outRec_search = outRec_j;
|
||||
op_origin_1 = op_k;
|
||||
op_origin_2 = op_j;
|
||||
|
||||
}
|
||||
else // both are holes
|
||||
{
|
||||
// Order doesn't matter
|
||||
outRec_origin = outRec_j;
|
||||
outRec_parent = ParseFirstLeft(outRec_origin->FirstLeft);
|
||||
outRec_search = outRec_k;
|
||||
outRec_search = outRec_k;
|
||||
op_origin_1 = op_j;
|
||||
op_origin_2 = op_k;
|
||||
}
|
||||
if (outRec_parent != ParseFirstLeft(outRec_search->FirstLeft))
|
||||
{
|
||||
// The two holes do not have the same parent, do not add them
|
||||
// simply return!
|
||||
return false;
|
||||
}
|
||||
bool found = false;
|
||||
std::list<std::pair<const int, OutPtIntersect> > iList;
|
||||
auto range = dupeRec.equal_range(outRec_search->Idx);
|
||||
// Check for direct connection
|
||||
for (auto it = range.first; it != range.second; ++it)
|
||||
{
|
||||
OutRec * itRec = GetOutRec(it->second.op2->Idx);
|
||||
if (itRec->Idx == outRec_origin->Idx)
|
||||
{
|
||||
found = true;
|
||||
if (op_origin_1->Pt != it->second.op2->Pt)
|
||||
{
|
||||
iList.emplace_back(outRec_search->Idx, it->second);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
// Check for connection through chain of other intersections
|
||||
for (auto it = range.first; it != range.second; ++it)
|
||||
{
|
||||
OutRec * itRec = GetOutRec(it->second.op2->Idx);
|
||||
if (itRec->IsHole && (outRec_parent == itRec || outRec_parent == ParseFirstLeft(itRec->FirstLeft)) &&
|
||||
FindIntersectLoop(dupeRec, iList, outRec_parent, outRec_origin->Idx, outRec_search->Idx, itRec->Idx))
|
||||
{
|
||||
found = true;
|
||||
iList.emplace_front(outRec_search->Idx, it->second);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
OutPtIntersect intPt_origin = { op_origin_1, op_origin_2 };
|
||||
OutPtIntersect intPt_search = { op_origin_2, op_origin_1 };
|
||||
dupeRec.emplace(outRec_origin->Idx, intPt_origin);
|
||||
dupeRec.emplace(outRec_search->Idx, intPt_search);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (iList.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Switch
|
||||
OutPt * op_origin_1_next = op_origin_1->Next;
|
||||
OutPt * op_origin_2_next = op_origin_2->Next;
|
||||
op_origin_1->Next = op_origin_2_next;
|
||||
op_origin_2->Next = op_origin_1_next;
|
||||
op_origin_1_next->Prev = op_origin_2;
|
||||
op_origin_2_next->Prev = op_origin_1;
|
||||
|
||||
for (auto iRing : iList)
|
||||
{
|
||||
OutPt * op_search_1 = iRing.second.op1;
|
||||
OutPt * op_search_2 = iRing.second.op2;
|
||||
OutPt * op_search_1_next = op_search_1->Next;
|
||||
OutPt * op_search_2_next = op_search_2->Next;
|
||||
op_search_1->Next = op_search_2_next;
|
||||
op_search_2->Next = op_search_1_next;
|
||||
op_search_1_next->Prev = op_search_2;
|
||||
op_search_2_next->Prev = op_search_1;
|
||||
}
|
||||
|
||||
OutRec * outRec_new = CreateOutRec();
|
||||
outRec_new->IsHole = false;
|
||||
if (outRec_origin->IsHole == ((Area(op_origin_1) > 0) && m_ReverseOutput))
|
||||
{
|
||||
outRec_origin->Pts = op_origin_1;
|
||||
outRec_new->Pts = op_origin_2;
|
||||
}
|
||||
else
|
||||
{
|
||||
outRec_origin->Pts = op_origin_2;
|
||||
outRec_new->Pts = op_origin_1;
|
||||
}
|
||||
|
||||
UpdateOutPtIdxs(*outRec_origin);
|
||||
UpdateOutPtIdxs(*outRec_new);
|
||||
|
||||
outRec_origin->BottomPt = 0;
|
||||
|
||||
std::list<std::pair<const int, OutPtIntersect> > move_list;
|
||||
for (auto iRing : iList)
|
||||
{
|
||||
OutRec * outRec_itr = GetOutRec(iRing.first);
|
||||
int itr_idx = outRec_itr->Idx;
|
||||
outRec_itr->Pts = 0;
|
||||
outRec_itr->BottomPt = 0;
|
||||
outRec_itr->Idx = outRec_origin->Idx;
|
||||
if (outRec_origin->IsHole)
|
||||
{
|
||||
outRec_itr->FirstLeft = ParseFirstLeft(outRec_origin->FirstLeft);
|
||||
}
|
||||
else
|
||||
{
|
||||
outRec_itr->FirstLeft = outRec_origin;
|
||||
}
|
||||
outRec_itr->IsHole = outRec_origin->IsHole;
|
||||
if (m_UsingPolyTree)
|
||||
{
|
||||
FixupFirstLefts3(outRec_itr, outRec_origin);
|
||||
}
|
||||
auto range_itr = dupeRec.equal_range(itr_idx);
|
||||
if (range_itr.first != range_itr.second)
|
||||
{
|
||||
for (auto it = range_itr.first; it != range_itr.second; ++it)
|
||||
{
|
||||
OutRec * itRec1 = GetOutRec(it->second.op1->Idx);
|
||||
OutRec * itRec2 = GetOutRec(it->second.op2->Idx);
|
||||
if (!(itRec1->Idx == outRec_new->Idx && itRec2->Idx == outRec_origin->Idx) &&
|
||||
!(itRec2->Idx == outRec_new->Idx && itRec1->Idx == outRec_origin->Idx) &&
|
||||
(itRec1->IsHole || itRec2->IsHole))
|
||||
{
|
||||
move_list.emplace_back(itRec1->Idx, it->second);
|
||||
}
|
||||
}
|
||||
dupeRec.erase(itr_idx);
|
||||
}
|
||||
}
|
||||
if (outRec_origin->IsHole)
|
||||
{
|
||||
outRec_new->FirstLeft = outRec_origin;
|
||||
}
|
||||
else
|
||||
{
|
||||
outRec_new->FirstLeft = outRec_origin->FirstLeft;
|
||||
}
|
||||
auto range_itr = dupeRec.equal_range(outRec_origin->Idx);
|
||||
for (auto it = range_itr.first; it != range_itr.second;)
|
||||
{
|
||||
OutRec * itRec1 = GetOutRec(it->second.op1->Idx);
|
||||
OutRec * itRec2 = GetOutRec(it->second.op2->Idx);
|
||||
if (!(itRec1->Idx == outRec_origin->Idx) &&
|
||||
(itRec1->IsHole || itRec2->IsHole))
|
||||
{
|
||||
move_list.emplace_back(itRec1->Idx, it->second);
|
||||
it = dupeRec.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_UsingPolyTree)
|
||||
{
|
||||
if (outRec_origin->IsHole)
|
||||
{
|
||||
FixupFirstLefts2(outRec_new, outRec_origin);
|
||||
}
|
||||
else
|
||||
{
|
||||
FixupFirstLefts1(outRec_origin, outRec_new);
|
||||
}
|
||||
}
|
||||
if (!move_list.empty())
|
||||
{
|
||||
dupeRec.insert(move_list.begin(), move_list.end());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void Clipper::DoSimplePolygons()
|
||||
{
|
||||
std::vector < OutPt*> m_OutPts;
|
||||
@ -4485,7 +4777,8 @@ void Clipper::DoSimplePolygons()
|
||||
}
|
||||
}
|
||||
std::stable_sort(m_OutPts.begin(), m_OutPts.end(), SortOutPt);
|
||||
std::list<OutPtIntersect> dupeRec;
|
||||
std::unordered_multimap<int, OutPtIntersect> dupeRec;
|
||||
dupeRec.reserve(m_PolyOuts.size());
|
||||
std::size_t count = 0;
|
||||
for (std::size_t i = 1; i < m_OutPts.size(); ++i)
|
||||
{
|
||||
@ -4501,13 +4794,11 @@ void Clipper::DoSimplePolygons()
|
||||
if (m_OutPts[j]->Idx < 0) continue;
|
||||
OutRec * outRec_j = GetOutRec(m_OutPts[j]->Idx);
|
||||
int idx_j = outRec_j->Idx;
|
||||
bool hole_j = outRec_j->IsHole;
|
||||
for (std::size_t k = j + 1; k < i; ++k)
|
||||
{
|
||||
if (m_OutPts[k]->Idx < 0) continue;
|
||||
OutRec * outRec_k = GetOutRec(m_OutPts[k]->Idx);
|
||||
int idx_k = outRec_k->Idx;
|
||||
bool hole_k = outRec_k->IsHole;
|
||||
if (idx_k == idx_j)
|
||||
{
|
||||
OutPt * op = m_OutPts[j];
|
||||
@ -4529,158 +4820,127 @@ void Clipper::DoSimplePolygons()
|
||||
UpdateOutPtIdxs(*outrec2);
|
||||
if (Poly2ContainsPoly1(outrec2->Pts, outrec->Pts))
|
||||
{
|
||||
//OutRec2 is contained by OutRec1 ...
|
||||
outrec2->IsHole = !outrec->IsHole;
|
||||
outrec2->FirstLeft = outrec;
|
||||
if (m_UsingPolyTree) FixupFirstLefts2(outrec2, outrec);
|
||||
//OutRec2 is contained by OutRec1 ...
|
||||
outrec2->IsHole = !outrec->IsHole;
|
||||
outrec2->FirstLeft = outrec;
|
||||
if (m_UsingPolyTree)
|
||||
{
|
||||
FixupFirstLefts2(outrec2, outrec);
|
||||
}
|
||||
auto range = dupeRec.equal_range(idx_k);
|
||||
std::list<std::pair<const int, OutPtIntersect> > move_list;
|
||||
for (auto it = range.first; it != range.second;)
|
||||
{
|
||||
OutRec * itRec = GetOutRec(it->second.op1->Idx);
|
||||
if (itRec->Idx != idx_k)
|
||||
{
|
||||
OutRec * itRec2 = GetOutRec(it->second.op2->Idx);
|
||||
if (itRec->IsHole || itRec2->IsHole)
|
||||
{
|
||||
move_list.emplace_back(itRec->Idx, it->second);
|
||||
}
|
||||
it = dupeRec.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
if (!move_list.empty())
|
||||
{
|
||||
dupeRec.insert(move_list.begin(), move_list.end());
|
||||
}
|
||||
OutPtIntersect intPt1 = { op, op2 };
|
||||
OutPtIntersect intPt2 = { op2, op };
|
||||
dupeRec.emplace(idx_k, intPt1);
|
||||
dupeRec.emplace(outrec2->Idx, intPt2);
|
||||
}
|
||||
else if (Poly2ContainsPoly1(outrec->Pts, outrec2->Pts))
|
||||
{
|
||||
//OutRec1 is contained by OutRec2 ...
|
||||
outrec2->IsHole = outrec->IsHole;
|
||||
outrec->IsHole = !outrec2->IsHole;
|
||||
outrec2->FirstLeft = outrec->FirstLeft;
|
||||
outrec->FirstLeft = outrec2;
|
||||
if (m_UsingPolyTree) FixupFirstLefts2(outrec, outrec2);
|
||||
//OutRec1 is contained by OutRec2 ...
|
||||
outrec2->IsHole = outrec->IsHole;
|
||||
outrec->IsHole = !outrec2->IsHole;
|
||||
outrec2->FirstLeft = outrec->FirstLeft;
|
||||
outrec->FirstLeft = outrec2;
|
||||
if (m_UsingPolyTree)
|
||||
{
|
||||
FixupFirstLefts2(outrec, outrec2);
|
||||
}
|
||||
auto range = dupeRec.equal_range(idx_k);
|
||||
std::list<std::pair<const int, OutPtIntersect> > move_list;
|
||||
for (auto it = range.first; it != range.second;)
|
||||
{
|
||||
OutRec * itRec = GetOutRec(it->second.op1->Idx);
|
||||
if (itRec->Idx != idx_k)
|
||||
{
|
||||
OutRec * itRec2 = GetOutRec(it->second.op2->Idx);
|
||||
if (itRec->IsHole || itRec2->IsHole)
|
||||
{
|
||||
move_list.emplace_back(itRec->Idx, it->second);
|
||||
}
|
||||
it = dupeRec.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
if (!move_list.empty())
|
||||
{
|
||||
dupeRec.insert(move_list.begin(), move_list.end());
|
||||
}
|
||||
OutPtIntersect intPt1 = { op, op2 };
|
||||
OutPtIntersect intPt2 = { op2, op };
|
||||
dupeRec.emplace(idx_k, intPt1);
|
||||
dupeRec.emplace(outrec2->Idx, intPt2);
|
||||
}
|
||||
else
|
||||
{
|
||||
//the 2 polygons are separate ...
|
||||
outrec2->IsHole = outrec->IsHole;
|
||||
outrec2->FirstLeft = outrec->FirstLeft;
|
||||
if (m_UsingPolyTree) FixupFirstLefts1(outrec, outrec2);
|
||||
//the 2 polygons are separate ...
|
||||
outrec2->IsHole = outrec->IsHole;
|
||||
outrec2->FirstLeft = outrec->FirstLeft;
|
||||
if (m_UsingPolyTree)
|
||||
{
|
||||
FixupFirstLefts1(outrec, outrec2);
|
||||
}
|
||||
auto range = dupeRec.equal_range(idx_k);
|
||||
std::list<std::pair<const int, OutPtIntersect> > move_list;
|
||||
for (auto it = range.first; it != range.second;)
|
||||
{
|
||||
OutRec * itRec = GetOutRec(it->second.op1->Idx);
|
||||
if (itRec->Idx != idx_k)
|
||||
{
|
||||
OutRec * itRec2 = GetOutRec(it->second.op2->Idx);
|
||||
if (itRec->IsHole || itRec2->IsHole)
|
||||
{
|
||||
move_list.emplace_back(itRec->Idx, it->second);
|
||||
}
|
||||
it = dupeRec.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
if (!move_list.empty())
|
||||
{
|
||||
dupeRec.insert(move_list.begin(), move_list.end());
|
||||
}
|
||||
if (outrec2->IsHole)
|
||||
{
|
||||
OutPtIntersect intPt1 = { op, op2 };
|
||||
OutPtIntersect intPt2 = { op2, op };
|
||||
dupeRec.emplace(idx_k, intPt1);
|
||||
dupeRec.emplace(outrec2->Idx, intPt2);
|
||||
}
|
||||
}
|
||||
OutPtIntersect intPt = { op, op2 };
|
||||
dupeRec.push_back(intPt);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
bool found = false;
|
||||
if (hole_k != hole_j)
|
||||
if (FixIntersects(dupeRec, m_OutPts[j], m_OutPts[k], outRec_j, outRec_k))
|
||||
{
|
||||
auto dupe = dupeRec.begin();
|
||||
while (dupe != dupeRec.end())
|
||||
{
|
||||
int idx1 = GetOutRec(dupe->op1->Idx)->Idx;
|
||||
int idx2 = GetOutRec(dupe->op2->Idx)->Idx;
|
||||
if ((idx1 == idx_j && idx2 == idx_k) ||
|
||||
(idx2 == idx_j && idx1 == idx_k))
|
||||
{
|
||||
found = true;
|
||||
if (dupe->op1->Pt == m_OutPts[j]->Pt)
|
||||
{
|
||||
break;
|
||||
}
|
||||
OutPt* op1 = dupe->op1;
|
||||
OutPt* op2 = dupe->op2;
|
||||
OutPt* op1_next = op1->Next;
|
||||
OutPt* op2_next = op2->Next;
|
||||
OutPt* op1b;
|
||||
OutPt* op2b;
|
||||
OutRec* outRec1;
|
||||
OutRec* outRec2;
|
||||
bool one_is_j = false;
|
||||
if (idx1 == idx_j)
|
||||
{
|
||||
one_is_j = true;
|
||||
outRec1 = outRec_j;
|
||||
outRec2 = outRec_k;
|
||||
op1b = m_OutPts[j];
|
||||
op2b = m_OutPts[k];
|
||||
}
|
||||
else
|
||||
{
|
||||
outRec1 = outRec_k;
|
||||
outRec2 = outRec_j;
|
||||
op1b = m_OutPts[k];
|
||||
op2b = m_OutPts[j];
|
||||
}
|
||||
OutPt* op1b_next = op1b->Next;
|
||||
OutPt* op2b_next = op2b->Next;
|
||||
op2b->Next= op1b_next;
|
||||
op1b->Next = op2b_next;
|
||||
op2b_next->Prev = op1b;
|
||||
op1b_next->Prev = op2b;
|
||||
op2->Next= op1_next;
|
||||
op1->Next = op2_next;
|
||||
op2_next->Prev = op1;
|
||||
op1_next->Prev = op2;
|
||||
bool holeState = (Area(op1b) > 0) && m_ReverseOutput;
|
||||
if (outRec1->IsHole == holeState) // outRec1 is "parent"
|
||||
{
|
||||
outRec1->Pts = op1b;
|
||||
outRec1->BottomPt = 0;
|
||||
outRec2->Pts = 0;
|
||||
outRec2->BottomPt = 0;
|
||||
outRec2->Idx = outRec1->Idx;
|
||||
outRec2->FirstLeft = outRec1;
|
||||
outRec2->IsHole = outRec1->IsHole;
|
||||
if (m_UsingPolyTree) FixupFirstLefts3(outRec2, outRec1);
|
||||
OutRec * outRec3 = CreateOutRec();
|
||||
outRec3->Pts = op2b;
|
||||
outRec3->IsHole = outRec1->IsHole;
|
||||
UpdateOutPtIdxs(*outRec1);
|
||||
UpdateOutPtIdxs(*outRec3);
|
||||
outRec3->FirstLeft = outRec1->FirstLeft;
|
||||
//fixup FirstLeft pointers that may need reassigning to OutRec3
|
||||
if (m_UsingPolyTree) FixupFirstLefts1(outRec1, outRec3);
|
||||
PointCount(outRec1->Pts);
|
||||
PointCount(outRec3->Pts);
|
||||
if (one_is_j)
|
||||
{
|
||||
outRec_k = outRec3;
|
||||
hole_k = outRec3->IsHole;
|
||||
}
|
||||
else
|
||||
{
|
||||
outRec_j = outRec3;
|
||||
hole_j = outRec3->IsHole;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
outRec2->Pts = op2b;
|
||||
outRec2->BottomPt = 0;
|
||||
outRec1->Pts = 0;
|
||||
outRec1->BottomPt = 0;
|
||||
outRec1->Idx = outRec2->Idx;
|
||||
outRec1->FirstLeft = outRec2;
|
||||
outRec1->IsHole = outRec2->IsHole;
|
||||
if (m_UsingPolyTree) FixupFirstLefts3(outRec1, outRec2);
|
||||
OutRec * outRec3 = CreateOutRec();
|
||||
outRec3->Pts = op1b;
|
||||
outRec3->IsHole = outRec2->IsHole;
|
||||
UpdateOutPtIdxs(*outRec2);
|
||||
UpdateOutPtIdxs(*outRec3);
|
||||
outRec3->FirstLeft = outRec2->FirstLeft;
|
||||
//fixup FirstLeft pointers that may need reassigning to OutRec3
|
||||
if (m_UsingPolyTree) FixupFirstLefts1(outRec2, outRec3);
|
||||
PointCount(outRec2->Pts);
|
||||
PointCount(outRec3->Pts);
|
||||
if (one_is_j)
|
||||
{
|
||||
outRec_j = outRec3;
|
||||
hole_j = outRec3->IsHole;
|
||||
}
|
||||
else
|
||||
{
|
||||
outRec_k = outRec3;
|
||||
hole_k = outRec3->IsHole;
|
||||
}
|
||||
}
|
||||
dupe = dupeRec.erase(dupe);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
++dupe;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
OutPtIntersect intPt = { m_OutPts[j], m_OutPts[k] };
|
||||
dupeRec.push_back(intPt);
|
||||
outRec_j = GetOutRec(m_OutPts[j]->Idx);
|
||||
idx_j = outRec_j->Idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,7 @@
|
||||
#include <ostream>
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
#if defined(CLIPPER_IMPL_INCLUDE)
|
||||
#include CLIPPER_IMPL_INCLUDE
|
||||
#endif
|
||||
@ -77,7 +78,7 @@ enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
|
||||
static cInt const loRange = 0x7FFF;
|
||||
static cInt const hiRange = 0x7FFF;
|
||||
#else
|
||||
typedef signed long long cInt;
|
||||
typedef std::int64_t cInt;
|
||||
static cInt const loRange = 0x3FFFFFFF;
|
||||
static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL;
|
||||
typedef signed long long long64; //used by Int128 class
|
||||
@ -235,6 +236,7 @@ struct LocalMinimum;
|
||||
struct OutPt;
|
||||
struct OutRec;
|
||||
struct Join;
|
||||
struct OutPtIntersect;
|
||||
|
||||
typedef std::vector < OutRec* > PolyOutList;
|
||||
typedef std::vector < TEdge* > EdgeList;
|
||||
@ -377,6 +379,17 @@ private:
|
||||
bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2);
|
||||
void JoinCommonEdges();
|
||||
void DoSimplePolygons();
|
||||
bool FindIntersectLoop(std::unordered_multimap<int, OutPtIntersect> & dupeRec,
|
||||
std::list<std::pair<const int, OutPtIntersect> > & iList,
|
||||
OutRec * outRec_parent,
|
||||
int idx_origin,
|
||||
int idx_prev,
|
||||
int idx_search);
|
||||
bool FixIntersects(std::unordered_multimap<int, OutPtIntersect> & dupeRec,
|
||||
OutPt * op_j,
|
||||
OutPt * op_k,
|
||||
OutRec * outRec_j,
|
||||
OutRec * outRec_k);
|
||||
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
|
||||
void FixupFirstLefts2(OutRec* InnerOutRec, OutRec* OuterOutRec);
|
||||
void FixupFirstLefts3(OutRec* OldOutRec, OutRec* NewOutRec);
|
||||
|
12
geometry.cc
12
geometry.cc
@ -21,10 +21,10 @@ extern "C" {
|
||||
drawvec decode_geometry(char **meta, int z, unsigned tx, unsigned ty, int detail, long long *bbox, unsigned initial_x, unsigned initial_y) {
|
||||
drawvec out;
|
||||
|
||||
bbox[0] = LONG_LONG_MAX;
|
||||
bbox[1] = LONG_LONG_MAX;
|
||||
bbox[2] = LONG_LONG_MIN;
|
||||
bbox[3] = LONG_LONG_MIN;
|
||||
bbox[0] = LLONG_MAX;
|
||||
bbox[1] = LLONG_MAX;
|
||||
bbox[2] = LLONG_MIN;
|
||||
bbox[3] = LLONG_MIN;
|
||||
|
||||
long long wx = initial_x, wy = initial_y;
|
||||
|
||||
@ -169,7 +169,7 @@ drawvec shrink_lines(drawvec &geom, int z, int detail, int basezoom, long long *
|
||||
long long d = sqrt(dx * dx + dy * dy);
|
||||
|
||||
long long n;
|
||||
long long next = LONG_LONG_MAX;
|
||||
long long next = LLONG_MAX;
|
||||
for (n = *here; n < *here + d; n = next) {
|
||||
int within;
|
||||
|
||||
@ -995,7 +995,7 @@ std::vector<drawvec> chop_polygon(std::vector<drawvec> &geoms) {
|
||||
for (unsigned i = 0; i < geoms.size(); i++) {
|
||||
if (geoms[i].size() > 700) {
|
||||
long long midx = 0, midy = 0, count = 0;
|
||||
long long maxx = LONG_LONG_MIN, maxy = LONG_LONG_MIN, minx = LONG_LONG_MAX, miny = LONG_LONG_MAX;
|
||||
long long maxx = LLONG_MIN, maxy = LLONG_MIN, minx = LLONG_MAX, miny = LLONG_MAX;
|
||||
|
||||
for (unsigned j = 0; j < geoms[i].size(); j++) {
|
||||
if (geoms[i][j].op == VT_MOVETO || geoms[i][j].op == VT_LINETO) {
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user