mirror of
https://github.com/NGSolve/netgen.git
synced 2024-12-25 05:20:34 +05:00
CSG2d - faster AddIntersections (search tree per loop)
This commit is contained in:
parent
7b8b3b03ca
commit
307c2a3bbb
@ -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_intersect("find intersections");
|
||||||
static Timer t_split("split splines");
|
static Timer t_split("split splines");
|
||||||
auto & PP = s1.polys;
|
|
||||||
auto & QQ = s2.polys;
|
|
||||||
|
|
||||||
t_intersect.Start();
|
t_intersect.Start();
|
||||||
for (Loop& P : PP)
|
for (Edge edgeP : l1.Edges(SOURCE))
|
||||||
for (Edge edgeP : P.Edges(SOURCE))
|
for (Edge edgeQ : l2.Edges(SOURCE))
|
||||||
for (Loop& Q : QQ)
|
{
|
||||||
for (Edge edgeQ : Q.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+EPSILON<alpha1)
|
||||||
{
|
{
|
||||||
double alpha = 0.0;
|
// Add midpoint of two intersection points to avoid false overlap detection of splines
|
||||||
double beta = 0.0;
|
// TODO: Check if this is really necessary
|
||||||
IntersectionType i = intersect(edgeP, edgeQ, alpha, beta);
|
auto alpha_mid = 0.5*(alpha+alpha1);
|
||||||
AddIntersectionPoint(edgeP, edgeQ, i, alpha, beta);
|
auto beta_mid = 0.5*(beta+beta1);
|
||||||
if(i==X_INTERSECTION && (edgeP.v0->spline || edgeQ.v0->spline))
|
Point<2> MP;
|
||||||
|
if(edgeP.v0->spline)
|
||||||
{
|
{
|
||||||
double alpha1 = alpha+1e2*EPSILON;
|
MP = edgeP.v0->spline->GetPoint(alpha_mid);
|
||||||
double beta1 = 0.0; //beta+1e2*EPSILON;
|
edgeP.v0->Insert(MP, alpha_mid);
|
||||||
|
|
||||||
// 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<alpha1)
|
|
||||||
{
|
|
||||||
// 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)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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();
|
t_intersect.Stop();
|
||||||
|
|
||||||
RegionTimer rt_split(t_split);
|
RegionTimer rt_split(t_split);
|
||||||
@ -743,12 +737,19 @@ void ComputeIntersections(Solid2d & s1, Solid2d & s2)
|
|||||||
} while(!curr->is_source);
|
} while(!curr->is_source);
|
||||||
};
|
};
|
||||||
|
|
||||||
for (Loop& P : PP)
|
for (Vertex* v : l1.Vertices(SOURCE))
|
||||||
for (Vertex* v : P.Vertices(SOURCE))
|
split_spline_at_vertex(v);
|
||||||
split_spline_at_vertex(v);
|
for (Vertex* v : l2.Vertices(SOURCE))
|
||||||
for (Loop& Q : QQ)
|
split_spline_at_vertex(v);
|
||||||
for (Vertex* v : Q.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
|
enum RelativePositionType
|
||||||
@ -1251,20 +1252,25 @@ void CleanUpResult(Solid2d & sr)
|
|||||||
RR.RemoveElement(i);
|
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)<EPSILON*EPSILON)
|
||||||
|
poly.Remove(last);
|
||||||
|
last = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RemoveDuplicates(Solid2d & sr)
|
void RemoveDuplicates(Solid2d & sr)
|
||||||
{
|
{
|
||||||
static Timer tall("RemoveDuplicates"); RegionTimer rtall(tall);
|
static Timer tall("RemoveDuplicates"); RegionTimer rtall(tall);
|
||||||
for(auto & poly : sr.polys)
|
for(auto & poly : sr.polys)
|
||||||
{
|
RemoveDuplicates(poly);
|
||||||
if(poly.first==nullptr) continue;
|
|
||||||
Vertex * last = poly.first->prev;
|
|
||||||
for(auto v : poly.Vertices(ALL))
|
|
||||||
{
|
|
||||||
if(Dist2(*v, *last)<EPSILON*EPSILON)
|
|
||||||
poly.Remove(last);
|
|
||||||
last = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Loop RectanglePoly(double x0, double x1, double y0, double y1, string bc)
|
Loop RectanglePoly(double x0, double x1, double y0, double y1, string bc)
|
||||||
@ -1316,6 +1322,14 @@ void AddIntersectionPoints ( Solid2d & s1, Solid2d & s2 )
|
|||||||
RemoveDuplicates(s2);
|
RemoveDuplicates(s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddIntersectionPoints ( Loop & l1, Loop & l2 )
|
||||||
|
{
|
||||||
|
ComputeIntersections(l1, l2);
|
||||||
|
RemoveDuplicates(l1);
|
||||||
|
RemoveDuplicates(l2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Solid2d ClipSolids ( const Solid2d & s1, const Solid2d & s2, char op)
|
Solid2d ClipSolids ( const Solid2d & s1, const Solid2d & s2, char op)
|
||||||
{
|
{
|
||||||
return ClipSolids(Solid2d{s1}, Solid2d{s2}, op);
|
return ClipSolids(Solid2d{s1}, Solid2d{s2}, op);
|
||||||
@ -1725,6 +1739,7 @@ shared_ptr<netgen::SplineGeometry2d> CSG2d :: GenerateSplineGeometry()
|
|||||||
static Timer t_is_inside("is inside check");
|
static Timer t_is_inside("is inside check");
|
||||||
static Timer t_segments("add segments");
|
static Timer t_segments("add segments");
|
||||||
static Timer t_intersections("add intersections");
|
static Timer t_intersections("add intersections");
|
||||||
|
static Timer t_segtree("seg trees");
|
||||||
RegionTimer rt(tall);
|
RegionTimer rt(tall);
|
||||||
|
|
||||||
struct Seg
|
struct Seg
|
||||||
@ -1756,18 +1771,27 @@ shared_ptr<netgen::SplineGeometry2d> CSG2d :: GenerateSplineGeometry()
|
|||||||
box.Add(sbox.PMax());
|
box.Add(sbox.PMax());
|
||||||
}
|
}
|
||||||
|
|
||||||
netgen::BoxTree <2, int> solid_tree(box);
|
netgen::BoxTree <2> solid_tree(box);
|
||||||
|
Array<INT<2>> loop_list;
|
||||||
|
|
||||||
for(auto i : Range(solids))
|
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 i1 : Range(solids))
|
||||||
|
for(auto li1 : Range(solids[i1].polys))
|
||||||
{
|
{
|
||||||
auto sbox = solids[i1].GetBoundingBox();
|
auto & poly1 = solids[i1].polys[li1];
|
||||||
solid_tree.GetFirstIntersecting(sbox.PMin(), sbox.PMax(), [&] (int i2)
|
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<i2)
|
if(i1<i2)
|
||||||
AddIntersectionPoints(solids[i1], solids[i2]);
|
AddIntersectionPoints(poly1, solids[i2].polys[li2]);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user