Skip to content

Commit

Permalink
added Line2d, ported 2D Line/Line and Segment/Segment intersection te…
Browse files Browse the repository at this point in the history
…sts (required Intersector1 interval-overlap, so also added Interval1d struct)

added Polygon2d Signed Area, IsCW, and IsInside(pt) tests
all untested!
  • Loading branch information
rms80 committed Dec 18, 2016
1 parent 8c97da1 commit 489e648
Show file tree
Hide file tree
Showing 10 changed files with 610 additions and 1 deletion.
54 changes: 54 additions & 0 deletions curve/Polygon2d.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ public void AppendVertex(Vector2d v)
Timestamp++;
}

public void Reverse()
{
vertices.Reverse();
Timestamp++;
}


public Vector2d GetTangent(int i)
{
Expand Down Expand Up @@ -89,6 +95,54 @@ public IEnumerable<Segment2d> SegmentItr() {




public bool IsClockwise() {
return SignedArea < 0;
}
public double SignedArea {
get {
double fArea = 0;
int N = vertices.Count;
for (int i = 0; i < N; ++i) {
Vector2d v1 = vertices[i];
Vector2d v2 = vertices[(i+1) % N];
fArea += v1.x * v2.y - v1.y * v2.x;
}
return fArea;
}
}


public bool IsInside( Vector2d vTest )
{
int nWindingNumber = 0; // winding number counter

int N = vertices.Count;
for (int i = 0; i < N; ++i) {

int iNext = (i+1) % N;

if (vertices[i].y <= vTest.y) {
// start y <= P.y
if (vertices[iNext].y > vTest.y) { // an upward crossing
if (MathUtil.IsLeft( vertices[i], vertices[iNext], vTest) > 0) // P left of edge
++nWindingNumber; // have a valid up intersect
}
} else {
// start y > P.y (no test needed)
if (vertices[iNext].y <= vTest.y) { // a downward crossing
if (MathUtil.IsLeft( vertices[i], vertices[iNext], vTest) < 0) // P right of edge
--nWindingNumber; // have a valid down intersect
}
}
}

return nWindingNumber != 0;
}




static public Polygon2d MakeCircle(float fRadius, int nSteps)
{
VectorArray2d vertices = new VectorArray2d(nSteps);
Expand Down
13 changes: 13 additions & 0 deletions geometry3Sharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,19 @@
<Compile Include="curve\CurveSampler2.cs" />
<Compile Include="math\AxisAlignedBox2d.cs" />
<Compile Include="curve\CurveSequence2.cs" />
<Compile Include="queries\DistLine3Segment3.cs" />
<Compile Include="queries\DistLine3Triangle3.cs" />
<Compile Include="queries\DistPoint3Triangle3.cs" />
<Compile Include="queries\DistSegment3Triangle3.cs" />
<Compile Include="queries\DistTriangle3Triangle3.cs" />
<Compile Include="queries\Intersection.cs" />
<Compile Include="queries\IntrRay3Triangle3.cs" />
<Compile Include="math\Triangle3.cs" />
<Compile Include="queries\IntrSegment2Segment2.cs" />
<Compile Include="queries\IntrLine2Line2.cs" />
<Compile Include="math\Line2.cs" />
<Compile Include="queries\Intersector1.cs" />
<Compile Include="math\Interval1d.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="interfaces\" />
Expand Down
102 changes: 102 additions & 0 deletions math/Interval1d.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using System;

namespace g3
{
// interval [a,b] on Real line.
// TODO: should check that a <= b !!
public struct Interval1d
{
public double a;
public double b;

public Interval1d(double f) { a = b = f; }
public Interval1d(double x, double y) { this.a = x; this.b = y; }
public Interval1d(double[] v2) { a = v2[0]; b = v2[1]; }
public Interval1d(float f) { a = b = f; }
public Interval1d(float x, float y) { this.a = x; this.b = y; }
public Interval1d(float[] v2) { a = v2[0]; b = v2[1]; }
public Interval1d(Interval1d copy) { a = copy.a; b = copy.b; }


static public readonly Interval1d Zero = new Interval1d(0.0f, 0.0f);
static public readonly Interval1d Empty = new Interval1d(double.MaxValue, -double.MaxValue);
static public readonly Interval1d Infinite = new Interval1d(-double.MaxValue, double.MaxValue);


public double this[int key]
{
get { return (key == 0) ? a : b; }
set { if (key == 0) a = value; else b = value; }
}


public double LengthSquared
{
get { return (a-b)*(a-b); }
}
public double Length
{
get { return b-a; }
}


public bool Contains(double d) {
return d >= a && d <= b;
}


public bool Overlaps(Interval1d o) {
return ! ( o.a > b || o.b < a );
}

public double SquaredDist(Interval1d o) {
if ( b < o.a )
return (o.a - b)*(o.a - b);
else if ( a > o.b )
return (a - o.b)*(a - o.b);
else
return 0;
}
public double Dist(Interval1d o) {
if ( b < o.a )
return o.a - b;
else if ( a > o.b )
return a - o.b;
else
return 0;
}


public void Set(Interval1d o) {
a = o.a; b = o.b;
}
public void Set(double fA, double fB) {
a = fA; b = fB;
}



public static Interval1d operator -(Interval1d v) {
return new Interval1d(-v.a, -v.b);
}


public static Interval1d operator +(Interval1d a, double f) {
return new Interval1d(a.a + f, a.b + f);
}
public static Interval1d operator -(Interval1d a, double f) {
return new Interval1d(a.a - f, a.b - f);
}

public static Interval1d operator *(Interval1d a, double f) {
return new Interval1d(a.a * f, a.b * f);
}


public override string ToString() {
return string.Format("[{0:F8},{1:F8}]", a, b);
}


}
}
79 changes: 79 additions & 0 deletions math/Line2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace g3
{
public struct Line2d
{
public Vector2d Origin;
public Vector2d Direction;

public Line2d(Vector2d origin, Vector2d direction)
{
this.Origin = origin;
this.Direction = direction;
}

// parameter is distance along Line
public Vector2d PointAt(double d) {
return Origin + d * Direction;
}

public double Project(Vector2d p)
{
return (p - Origin).Dot(Direction);
}

public double DistanceSquared(Vector2d p)
{
double t = (p - Origin).Dot(Direction);
Vector2d proj = Origin + t * Direction;
return (proj - p).LengthSquared;
}

// conversion operators
public static implicit operator Line2d(Line2f v)
{
return new Line2d(v.Origin, v.Direction);
}
public static explicit operator Line2f(Line2d v)
{
return new Line2f((Vector2f)v.Origin, (Vector2f)v.Direction);
}


}


public struct Line2f
{
public Vector2f Origin;
public Vector2f Direction;

public Line2f(Vector2f origin, Vector2f direction)
{
this.Origin = origin;
this.Direction = direction;
}

// parameter is distance along Line
public Vector2f PointAt(float d)
{
return Origin + d * Direction;
}

public float Project(Vector2f p)
{
return (p - Origin).Dot(Direction);
}

public float DistanceSquared(Vector2f p)
{
float t = (p - Origin).Dot(Direction);
Vector2f proj = Origin + t * Direction;
return (proj - p).LengthSquared;
}
}
}
11 changes: 11 additions & 0 deletions math/MathUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -218,5 +218,16 @@ public static bool IsObtuse(Vector3d v1, Vector3d v2, Vector3d v3) {
}


// code adapted from http://softsurfer.com/Archive/algorithm_0103/algorithm_0103.htm
// Return: >0 for P2 left of the line through P0 and P1
// =0 for P2 on the line
// <0 for P2 right of the line
public static double IsLeft( Vector2d P0, Vector2d P1, Vector2d P2 )
{
return ( (P1.x - P0.x) * (P2.y - P0.y) - (P2.x - P0.x) * (P1.y - P0.y) );
}



}
}
10 changes: 10 additions & 0 deletions math/Vector2d.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,16 @@ public double Cross(Vector2d v2) {
}


public Vector2d Perp {
get { return new Vector2d(y, -x); }
}
public Vector2d UnitPerp {
get { return new Vector2d(y, -x).Normalized; }
}
public double DotPerp(Vector2d v2) {
return x*v2.y - y*v2.x;
}


public double SquaredDist(Vector2d o) {
return ((x - o.x) * (x - o.x) + (y - o.y) * (y - o.y));
Expand Down
2 changes: 1 addition & 1 deletion queries/Intersection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public enum IntersectionResult

public enum IntersectionType
{
Point, Line
Empty, Point, Segment, Line
}


Expand Down
72 changes: 72 additions & 0 deletions queries/Intersector1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;

namespace g3
{
// ported from WildMagic5
//
// A class for intersection of intervals [u0,u1] and [v0,v1]. The end
// points must be ordered: u0 <= u1 and v0 <= v1. Values of MAX_REAL
// and -MAX_REAL are allowed, and degenerate intervals are allowed:
// u0 = u1 or v0 = v1.
//
public class Intersector1
{
// intervals to intersect
public Interval1d U;
public Interval1d V;


// Information about the intersection set. The number of intersections
// is 0 (intervals do not overlap), 1 (intervals are just touching), or
// 2 (intervals intersect in an inteval).
public int NumIntersections = 0;

// intersection point/interval, access via GetIntersection
private Interval1d Intersections = Interval1d.Zero;

public Intersector1(double u0, double u1, double v0, double v1) {
// [TODO] validate 0 < 1
U = new Interval1d(u0,u1);
V = new Interval1d(v0,v1);
}
public Intersector1(Interval1d u, Interval1d v) {
U = u;
V = v;
}

public bool Test {
get { return U.a <= V.b && U.b >= V.a; }
}


public double GetIntersection(int i) {
return Intersections[i];
}

public bool Find()
{
if (U.b < V.a || U.a > V.b) {
NumIntersections = 0;
} else if (U.b > V.a) {
if (U.a < V.b) {
NumIntersections = 2;
Intersections.a = (U.a < V.a ? V.a : U.a);
Intersections.b = (U.b > V.b ? V.b : U.b);
if (Intersections.a == Intersections.b) {
NumIntersections = 1;
}
} else {
// U.a == V.b
NumIntersections = 1;
Intersections.a = U.a;
}
} else {
// U.b == V.a
NumIntersections = 1;
Intersections.a = U.b;
}

return NumIntersections > 0;
}
}
}
Loading

0 comments on commit 489e648

Please sign in to comment.