Skip to content

Commit d32fdea

Browse files
committed
moved comp-geom algos to new folder, added GraphSplitter2d, Line2.WhichSide
1 parent 772123e commit d32fdea

File tree

6 files changed

+186
-5
lines changed

6 files changed

+186
-5
lines changed
File renamed without changes.
File renamed without changes.

comp_geom/GraphSplitter2d.cs

+148
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace g3
7+
{
8+
public class GraphSplitter2d
9+
{
10+
public DGraph2 Graph;
11+
12+
public double OnVertexTol = MathUtil.Epsilonf;
13+
public int InsertedEdgesID = 1;
14+
15+
public Func<Vector2d, bool> InsideTestF = null;
16+
17+
public GraphSplitter2d(DGraph2 graph)
18+
{
19+
Graph = graph;
20+
}
21+
22+
23+
DVector<int> EdgeSigns = new DVector<int>();
24+
25+
26+
struct edge_hit
27+
{
28+
public int hit_eid;
29+
public Index2i vtx_signs;
30+
public int hit_vid;
31+
public Vector2d hit_pos;
32+
public double line_t;
33+
}
34+
35+
36+
List<edge_hit> hits = new List<edge_hit>();
37+
38+
public void InsertCutEdges(Line2d line)
39+
{
40+
if (EdgeSigns.Length < Graph.MaxVertexID)
41+
EdgeSigns.resize(Graph.MaxVertexID);
42+
foreach ( int vid in Graph.VertexIndices()) {
43+
EdgeSigns[vid] = line.WhichSide(Graph.GetVertex(vid), OnVertexTol);
44+
}
45+
46+
47+
hits.Clear();
48+
foreach ( int eid in Graph.EdgeIndices() ) {
49+
Index2i ev = Graph.GetEdgeV(eid);
50+
Index2i signs = new Index2i(EdgeSigns[ev.a], EdgeSigns[ev.b]);
51+
if (signs.a * signs.b > 0)
52+
continue; // both positive or negative, ignore
53+
54+
edge_hit hit = new edge_hit() { hit_eid = eid, vtx_signs = signs, hit_vid = -1 };
55+
Vector2d a = Graph.GetVertex(ev.a);
56+
Vector2d b = Graph.GetVertex(ev.b);
57+
58+
// parallel-edge case (both are zero)
59+
if (signs.a == signs.b) {
60+
if ( a.DistanceSquared(b) > MathUtil.Epsilon ) {
61+
// we need to somehow not insert a new segment for this span below.
62+
// so, insert two hit points for the ray-interval, with same eid.
63+
// This will result in this span being skipped by the same-eid test below
64+
// *however*, if other edges self-intersect w/ this segment, this will *not work*
65+
// and duplicate edges will be inserted
66+
hit.hit_vid = ev.a;
67+
hit.line_t = line.Project(a);
68+
hits.Add(hit);
69+
edge_hit hit2 = hit;
70+
hit.hit_vid = ev.b;
71+
hit.line_t = line.Project(b);
72+
hits.Add(hit);
73+
} else {
74+
// degenerate edge - fall through to a == 0 case below
75+
signs.b = 1;
76+
}
77+
}
78+
79+
if ( signs.a == 0 ) {
80+
hit.hit_pos = a;
81+
hit.hit_vid = ev.a;
82+
hit.line_t = line.Project(a);
83+
} else if (signs.b == 0 ) {
84+
hit.hit_pos = b;
85+
hit.hit_vid = ev.b;
86+
hit.line_t = line.Project(b);
87+
} else {
88+
IntrLine2Segment2 intr = new IntrLine2Segment2(line, new Segment2d(a, b));
89+
if (intr.Find() == false)
90+
throw new Exception("GraphSplitter2d.InsertCutEdges: signs are different but ray did not it?");
91+
if ( intr.IsSimpleIntersection ) {
92+
hit.hit_pos = intr.Point;
93+
hit.line_t = intr.Parameter;
94+
} else {
95+
throw new Exception("GraphSplitter2d.InsertCutEdges: got parallel edge case!");
96+
}
97+
}
98+
hits.Add(hit);
99+
}
100+
101+
// sort by increasing ray-t
102+
hits.Sort((hit0, hit1) => { return hit0.line_t.CompareTo(hit1.line_t); });
103+
104+
// insert segments between successive intersection points
105+
int N = hits.Count;
106+
for ( int i = 0; i < N-1; ++i ) {
107+
int j = i + 1;
108+
// note: skipping parallel segments depends on this eid == eid test (see above)
109+
if (hits[i].line_t == hits[j].line_t || hits[i].hit_eid == hits[j].hit_eid)
110+
continue;
111+
112+
int vi = hits[i].hit_vid;
113+
if (vi == -1) {
114+
DGraph2.EdgeSplitInfo split;
115+
var result = Graph.SplitEdge(hits[i].hit_eid, out split);
116+
if (result != MeshResult.Ok)
117+
throw new Exception("GraphSplitter2d.InsertCutEdges: first edge split failed!");
118+
vi = split.vNew;
119+
Graph.SetVertex(vi, hits[i].hit_pos);
120+
}
121+
122+
int vj = hits[j].hit_vid;
123+
if ( vj == -1) {
124+
DGraph2.EdgeSplitInfo split;
125+
var result = Graph.SplitEdge(hits[j].hit_eid, out split);
126+
if (result != MeshResult.Ok)
127+
throw new Exception("GraphSplitter2d.InsertCutEdges: second edge split failed!");
128+
vj = split.vNew;
129+
Graph.SetVertex(vj, hits[j].hit_pos);
130+
}
131+
132+
// check if we actually want to add this segment
133+
if ( InsideTestF != null ) {
134+
Vector2d midpoint = 0.5 * (Graph.GetVertex(vi) + Graph.GetVertex(vj));
135+
if (InsideTestF(midpoint) == false)
136+
continue;
137+
}
138+
139+
Graph.AppendEdge(vi, vj, InsertedEdgesID);
140+
}
141+
142+
143+
}
144+
145+
146+
147+
}
148+
}

geometry3Sharp.csproj

+3-2
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,10 @@
5151
<Compile Include="color\ColorHSV.cs" />
5252
<Compile Include="color\ColorMap.cs" />
5353
<Compile Include="color\ColorMixer.cs" />
54+
<Compile Include="comp_geom\GraphSplitter2d.cs" />
5455
<Compile Include="containment\ContMinBox2.cs" />
5556
<Compile Include="containment\ContMinCircle2.cs" />
56-
<Compile Include="containment\ConvexHull2.cs" />
57+
<Compile Include="comp_geom\ConvexHull2.cs" />
5758
<Compile Include="core\CommandArgumentSet.cs" />
5859
<Compile Include="core\DijkstraGraphDistance.cs" />
5960
<Compile Include="core\DVector.cs" />
@@ -79,7 +80,7 @@
7980
<Compile Include="curve\BSplineBasis.cs" />
8081
<Compile Include="curve\Circle2.cs" />
8182
<Compile Include="curve\CurveResampler.cs" />
82-
<Compile Include="curve\Arrangement2d.cs" />
83+
<Compile Include="comp_geom\Arrangement2d.cs" />
8384
<Compile Include="curve\DGraph2Resampler.cs" />
8485
<Compile Include="curve\DGraph2Util.cs" />
8586
<Compile Include="curve\Ellipse2.cs" />

intersection/IntrLine2Segment2.cs

+5-3
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,11 @@ public bool IsSimpleIntersection {
6767
get { return Result == IntersectionResult.Intersects && Type == IntersectionType.Point; }
6868
}
6969

70-
// these values are on the line
71-
public Vector2d Point; // only set if Quantity = 1
72-
public double Parameter; // only set if Quantity = 1
70+
/// <summary> Point on line, only set if Quantity = 1 </summary>
71+
public Vector2d Point;
72+
73+
/// <summary>Parameter along line, only set if Quanityt = 1 </summary>
74+
public double Parameter;
7375

7476
public IntrLine2Segment2(Line2d line, Segment2d seg)
7577
{

math/Line2.cs

+30
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,36 @@ public double DistanceSquared(Vector2d p)
3333
return (proj - p).LengthSquared;
3434
}
3535

36+
37+
38+
/// <summary>
39+
/// Returns:
40+
/// +1, on right of line
41+
/// -1, on left of line
42+
/// 0, on the line
43+
/// </summary>
44+
public int WhichSide(Vector2d test, double tol = 0)
45+
{
46+
double x0 = test.x - Origin.x;
47+
double y0 = test.y - Origin.y;
48+
double x1 = Direction.x;
49+
double y1 = Direction.y;
50+
double det = x0 * y1 - x1 * y0;
51+
return (det > tol ? +1 : (det < -tol ? -1 : 0));
52+
}
53+
public int WhichSide(ref Vector2d test, double tol = 0)
54+
{
55+
double x0 = test.x - Origin.x;
56+
double y0 = test.y - Origin.y;
57+
double x1 = Direction.x;
58+
double y1 = Direction.y;
59+
double det = x0 * y1 - x1 * y0;
60+
return (det > tol ? +1 : (det < -tol ? -1 : 0));
61+
}
62+
63+
64+
65+
3666
// conversion operators
3767
public static implicit operator Line2d(Line2f v)
3868
{

0 commit comments

Comments
 (0)