Skip to content

Commit

Permalink
moved comp-geom algos to new folder, added GraphSplitter2d, Line2.Whi…
Browse files Browse the repository at this point in the history
…chSide
  • Loading branch information
rms80 committed Nov 18, 2017
1 parent 772123e commit d32fdea
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 5 deletions.
File renamed without changes.
File renamed without changes.
148 changes: 148 additions & 0 deletions comp_geom/GraphSplitter2d.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace g3
{
public class GraphSplitter2d
{
public DGraph2 Graph;

public double OnVertexTol = MathUtil.Epsilonf;
public int InsertedEdgesID = 1;

public Func<Vector2d, bool> InsideTestF = null;

public GraphSplitter2d(DGraph2 graph)
{
Graph = graph;
}


DVector<int> EdgeSigns = new DVector<int>();


struct edge_hit
{
public int hit_eid;
public Index2i vtx_signs;
public int hit_vid;
public Vector2d hit_pos;
public double line_t;
}


List<edge_hit> hits = new List<edge_hit>();

public void InsertCutEdges(Line2d line)
{
if (EdgeSigns.Length < Graph.MaxVertexID)
EdgeSigns.resize(Graph.MaxVertexID);
foreach ( int vid in Graph.VertexIndices()) {
EdgeSigns[vid] = line.WhichSide(Graph.GetVertex(vid), OnVertexTol);
}


hits.Clear();
foreach ( int eid in Graph.EdgeIndices() ) {
Index2i ev = Graph.GetEdgeV(eid);
Index2i signs = new Index2i(EdgeSigns[ev.a], EdgeSigns[ev.b]);
if (signs.a * signs.b > 0)
continue; // both positive or negative, ignore

edge_hit hit = new edge_hit() { hit_eid = eid, vtx_signs = signs, hit_vid = -1 };
Vector2d a = Graph.GetVertex(ev.a);
Vector2d b = Graph.GetVertex(ev.b);

// parallel-edge case (both are zero)
if (signs.a == signs.b) {
if ( a.DistanceSquared(b) > MathUtil.Epsilon ) {
// we need to somehow not insert a new segment for this span below.
// so, insert two hit points for the ray-interval, with same eid.
// This will result in this span being skipped by the same-eid test below
// *however*, if other edges self-intersect w/ this segment, this will *not work*
// and duplicate edges will be inserted
hit.hit_vid = ev.a;
hit.line_t = line.Project(a);
hits.Add(hit);
edge_hit hit2 = hit;
hit.hit_vid = ev.b;
hit.line_t = line.Project(b);
hits.Add(hit);
} else {
// degenerate edge - fall through to a == 0 case below
signs.b = 1;
}
}

if ( signs.a == 0 ) {
hit.hit_pos = a;
hit.hit_vid = ev.a;
hit.line_t = line.Project(a);
} else if (signs.b == 0 ) {
hit.hit_pos = b;
hit.hit_vid = ev.b;
hit.line_t = line.Project(b);
} else {
IntrLine2Segment2 intr = new IntrLine2Segment2(line, new Segment2d(a, b));
if (intr.Find() == false)
throw new Exception("GraphSplitter2d.InsertCutEdges: signs are different but ray did not it?");
if ( intr.IsSimpleIntersection ) {
hit.hit_pos = intr.Point;
hit.line_t = intr.Parameter;
} else {
throw new Exception("GraphSplitter2d.InsertCutEdges: got parallel edge case!");
}
}
hits.Add(hit);
}

// sort by increasing ray-t
hits.Sort((hit0, hit1) => { return hit0.line_t.CompareTo(hit1.line_t); });

// insert segments between successive intersection points
int N = hits.Count;
for ( int i = 0; i < N-1; ++i ) {
int j = i + 1;
// note: skipping parallel segments depends on this eid == eid test (see above)
if (hits[i].line_t == hits[j].line_t || hits[i].hit_eid == hits[j].hit_eid)
continue;

int vi = hits[i].hit_vid;
if (vi == -1) {
DGraph2.EdgeSplitInfo split;
var result = Graph.SplitEdge(hits[i].hit_eid, out split);
if (result != MeshResult.Ok)
throw new Exception("GraphSplitter2d.InsertCutEdges: first edge split failed!");
vi = split.vNew;
Graph.SetVertex(vi, hits[i].hit_pos);
}

int vj = hits[j].hit_vid;
if ( vj == -1) {
DGraph2.EdgeSplitInfo split;
var result = Graph.SplitEdge(hits[j].hit_eid, out split);
if (result != MeshResult.Ok)
throw new Exception("GraphSplitter2d.InsertCutEdges: second edge split failed!");
vj = split.vNew;
Graph.SetVertex(vj, hits[j].hit_pos);
}

// check if we actually want to add this segment
if ( InsideTestF != null ) {
Vector2d midpoint = 0.5 * (Graph.GetVertex(vi) + Graph.GetVertex(vj));
if (InsideTestF(midpoint) == false)
continue;
}

Graph.AppendEdge(vi, vj, InsertedEdgesID);
}


}



}
}
5 changes: 3 additions & 2 deletions geometry3Sharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,10 @@
<Compile Include="color\ColorHSV.cs" />
<Compile Include="color\ColorMap.cs" />
<Compile Include="color\ColorMixer.cs" />
<Compile Include="comp_geom\GraphSplitter2d.cs" />
<Compile Include="containment\ContMinBox2.cs" />
<Compile Include="containment\ContMinCircle2.cs" />
<Compile Include="containment\ConvexHull2.cs" />
<Compile Include="comp_geom\ConvexHull2.cs" />
<Compile Include="core\CommandArgumentSet.cs" />
<Compile Include="core\DijkstraGraphDistance.cs" />
<Compile Include="core\DVector.cs" />
Expand All @@ -79,7 +80,7 @@
<Compile Include="curve\BSplineBasis.cs" />
<Compile Include="curve\Circle2.cs" />
<Compile Include="curve\CurveResampler.cs" />
<Compile Include="curve\Arrangement2d.cs" />
<Compile Include="comp_geom\Arrangement2d.cs" />
<Compile Include="curve\DGraph2Resampler.cs" />
<Compile Include="curve\DGraph2Util.cs" />
<Compile Include="curve\Ellipse2.cs" />
Expand Down
8 changes: 5 additions & 3 deletions intersection/IntrLine2Segment2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,11 @@ public bool IsSimpleIntersection {
get { return Result == IntersectionResult.Intersects && Type == IntersectionType.Point; }
}

// these values are on the line
public Vector2d Point; // only set if Quantity = 1
public double Parameter; // only set if Quantity = 1
/// <summary> Point on line, only set if Quantity = 1 </summary>
public Vector2d Point;

/// <summary>Parameter along line, only set if Quanityt = 1 </summary>
public double Parameter;

public IntrLine2Segment2(Line2d line, Segment2d seg)
{
Expand Down
30 changes: 30 additions & 0 deletions math/Line2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,36 @@ public double DistanceSquared(Vector2d p)
return (proj - p).LengthSquared;
}



/// <summary>
/// Returns:
/// +1, on right of line
/// -1, on left of line
/// 0, on the line
/// </summary>
public int WhichSide(Vector2d test, double tol = 0)
{
double x0 = test.x - Origin.x;
double y0 = test.y - Origin.y;
double x1 = Direction.x;
double y1 = Direction.y;
double det = x0 * y1 - x1 * y0;
return (det > tol ? +1 : (det < -tol ? -1 : 0));
}
public int WhichSide(ref Vector2d test, double tol = 0)
{
double x0 = test.x - Origin.x;
double y0 = test.y - Origin.y;
double x1 = Direction.x;
double y1 = Direction.y;
double det = x0 * y1 - x1 * y0;
return (det > tol ? +1 : (det < -tol ? -1 : 0));
}




// conversion operators
public static implicit operator Line2d(Line2f v)
{
Expand Down

0 comments on commit d32fdea

Please sign in to comment.