From 19ebc915c8dbb0780e1f74770eaaa561da59dc33 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Wed, 14 Oct 2020 18:40:23 +0200 Subject: [PATCH] CSG2d - faster AddIntersections (search tree per loop) --- libsrc/geom2d/csg2d.cpp | 146 +++++++++++++++++++++++----------------- 1 file changed, 85 insertions(+), 61 deletions(-) diff --git a/libsrc/geom2d/csg2d.cpp b/libsrc/geom2d/csg2d.cpp index e1168d53..f46a813d 100644 --- a/libsrc/geom2d/csg2d.cpp +++ b/libsrc/geom2d/csg2d.cpp @@ -670,55 +670,49 @@ void AddIntersectionPoint(Edge edgeP, Edge edgeQ, IntersectionType i, double alp } } -void ComputeIntersections(Solid2d & s1, Solid2d & s2) +void ComputeIntersections(Loop & l1, Loop & l2) { - static Timer tall("ComputeIntersections"); RegionTimer rtall(tall); - static Timer t_tree("build search trees"); static Timer t_intersect("find intersections"); static Timer t_split("split splines"); - auto & PP = s1.polys; - auto & QQ = s2.polys; t_intersect.Start(); - for (Loop& P : PP) - for (Edge edgeP : P.Edges(SOURCE)) - for (Loop& Q : QQ) - for (Edge edgeQ : Q.Edges(SOURCE)) + for (Edge edgeP : l1.Edges(SOURCE)) + for (Edge edgeQ : l2.Edges(SOURCE)) + { + double alpha = 0.0; + double beta = 0.0; + IntersectionType i = intersect(edgeP, edgeQ, alpha, beta); + AddIntersectionPoint(edgeP, edgeQ, i, alpha, beta); + if(i==X_INTERSECTION && (edgeP.v0->spline || edgeQ.v0->spline)) + { + double alpha1 = alpha+1e2*EPSILON; + double beta1 = 0.0; //beta+1e2*EPSILON; + + // search for possible second intersection + i = intersect(edgeP, edgeQ, alpha1, beta1); + // cout << "second intersection " << i << ',' << alpha1 << ',' << beta1 << ',' << alpha1-alpha << ',' << beta1-beta << endl; + if(i!=NO_INTERSECTION && alpha+EPSILONspline || edgeQ.v0->spline)) + // Add midpoint of two intersection points to avoid false overlap detection of splines + // TODO: Check if this is really necessary + auto alpha_mid = 0.5*(alpha+alpha1); + auto beta_mid = 0.5*(beta+beta1); + Point<2> MP; + if(edgeP.v0->spline) { - double alpha1 = alpha+1e2*EPSILON; - double beta1 = 0.0; //beta+1e2*EPSILON; - - // search for possible second intersection - i = intersect(edgeP, edgeQ, alpha1, beta1); - // cout << "second intersection " << i << ',' << alpha1 << ',' << beta1 << ',' << alpha1-alpha << ',' << beta1-beta << endl; - if(i!=NO_INTERSECTION && alpha+EPSILON MP; - if(edgeP.v0->spline) - { - MP = edgeP.v0->spline->GetPoint(alpha_mid); - edgeP.v0->Insert(MP, alpha_mid); - } - else - MP = edgeQ.v0->spline->GetPoint(beta_mid); - - if(edgeQ.v0->spline) - edgeQ.v0->Insert(MP, beta_mid); - - AddIntersectionPoint(edgeP, edgeQ, i, alpha1, beta1); - } + MP = edgeP.v0->spline->GetPoint(alpha_mid); + edgeP.v0->Insert(MP, alpha_mid); } + else + MP = edgeQ.v0->spline->GetPoint(beta_mid); + + if(edgeQ.v0->spline) + edgeQ.v0->Insert(MP, beta_mid); + + AddIntersectionPoint(edgeP, edgeQ, i, alpha1, beta1); } + } + } t_intersect.Stop(); RegionTimer rt_split(t_split); @@ -743,12 +737,19 @@ void ComputeIntersections(Solid2d & s1, Solid2d & s2) } while(!curr->is_source); }; - for (Loop& P : PP) - for (Vertex* v : P.Vertices(SOURCE)) - split_spline_at_vertex(v); - for (Loop& Q : QQ) - for (Vertex* v : Q.Vertices(SOURCE)) - split_spline_at_vertex(v); + for (Vertex* v : l1.Vertices(SOURCE)) + split_spline_at_vertex(v); + for (Vertex* v : l2.Vertices(SOURCE)) + split_spline_at_vertex(v); +} + +void ComputeIntersections(Solid2d & s1, Solid2d & s2) +{ + static Timer tall("ComputeIntersections"); RegionTimer rtall(tall); + + for (Loop& l1 : s1.polys) + for (Loop& l2 : s2.polys) + ComputeIntersections(l1, l2); } enum RelativePositionType @@ -1251,20 +1252,25 @@ void CleanUpResult(Solid2d & sr) RR.RemoveElement(i); } +void RemoveDuplicates(Loop & poly) +{ + if(poly.first==nullptr) + return; + + Vertex * last = poly.first->prev; + for(auto v : poly.Vertices(ALL)) + { + if(Dist2(*v, *last)prev; - for(auto v : poly.Vertices(ALL)) - { - if(Dist2(*v, *last) CSG2d :: GenerateSplineGeometry() static Timer t_is_inside("is inside check"); static Timer t_segments("add segments"); static Timer t_intersections("add intersections"); + static Timer t_segtree("seg trees"); RegionTimer rt(tall); struct Seg @@ -1756,18 +1771,27 @@ shared_ptr CSG2d :: GenerateSplineGeometry() box.Add(sbox.PMax()); } - netgen::BoxTree <2, int> solid_tree(box); + netgen::BoxTree <2> solid_tree(box); + Array> loop_list; for(auto i : Range(solids)) - solid_tree.Insert(solids[i].GetBoundingBox(), i); + for(auto li : Range(solids[i].polys)) + { + solid_tree.Insert(solids[i].polys[li].GetBoundingBox(), loop_list.Size()); + loop_list.Append(INT<2>(i, li)); + } for(auto i1 : Range(solids)) + for(auto li1 : Range(solids[i1].polys)) { - auto sbox = solids[i1].GetBoundingBox(); - solid_tree.GetFirstIntersecting(sbox.PMin(), sbox.PMax(), [&] (int i2) + auto & poly1 = solids[i1].polys[li1]; + auto box = poly1.GetBoundingBox(); + solid_tree.GetFirstIntersecting(box.PMin(), box.PMax(), [&] (int ii) { + auto i2 = loop_list[ii][0]; + auto li2 = loop_list[ii][1]; if(i1