public bool ContainsVertex(gVertex vertex) { gVertex maxVertex = vertices.OrderByDescending(v => v.DistanceTo(vertex)).First(); double maxDistance = vertex.DistanceTo(maxVertex) * 1.5; gVertex v2 = gVertex.ByCoordinates(vertex.X + maxDistance, vertex.Y, vertex.Z); gEdge ray = gEdge.ByStartVertexEndVertex(vertex, v2); gVertex coincident = null; int windNumber = 0; foreach (gEdge edge in edges) { gBase intersection = ray.Intersection(edge); if (edge.StartVertex.Y <= vertex.Y) { if (edge.EndVertex.Y > vertex.Y && intersection != null && intersection.GetType() == typeof(gVertex)) { ++windNumber; } } else { if (edge.EndVertex.Y <= vertex.Y && intersection != null && intersection.GetType() == typeof(gVertex)) { --windNumber; } } } //If intersections is odd, returns true, false otherwise //return (intersections % 2 == 0) ? false : true; return(windNumber != 0); }
internal gPolygon AddVertex(gVertex v, gEdge intersectingEdge) { //Assumes that vertex v intersects one of polygons edges. gPolygon newPolygon = (gPolygon)this.Clone(); // Assign the polygon Id to the new vertex. v.polygonId = this.id; // Getting the index of the intersecting edge's start vertex and // inserting the new vertex at the following index. int index = newPolygon.vertices.IndexOf(intersectingEdge.StartVertex); newPolygon.vertices.Insert(index + 1, v); // Rebuilding edges. newPolygon.edges.Clear(); int verticesCount = newPolygon.vertices.Count; for (var i = 0; i < verticesCount; i++) { int nextIndex = (i + 1) % verticesCount; newPolygon.edges.Add(new gEdge(newPolygon.vertices[i], newPolygon.vertices[nextIndex])); } return(newPolygon); }
public bool IsCoplanarTo(gEdge edge) { // http://mathworld.wolfram.com/Coplanar.html gVector a = this.Direction; gVector b = edge.Direction; gVector c = gVector.ByTwoVertices(this.StartVertex, edge.StartVertex); return(c.Dot(a.Cross(b)) == 0); }
public double DistanceTo(gEdge edge) { // http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html gVector v1 = gVector.ByTwoVertices(this, edge.StartVertex); gVector v2 = gVector.ByTwoVertices(this, edge.EndVertex); gVector numerator = v1.Cross(v2); gVector denominator = gVector.ByTwoVertices(edge.EndVertex, edge.StartVertex); return(numerator.Length / denominator.Length); }
public bool Intersects(gEdge edge) { if (this.StartVertex.OnEdge(edge) || this.EndVertex.OnEdge(edge)) { if (this.Direction.IsParallelTo(edge.Direction)) { return(true); } } return(this.Intersection(edge) != null); }
//public Line AsLine() //{ // return Line.ByStartPointEndPoint(StartVertex.AsPoint(), EndVertex.AsPoint()); //} #region override methods //TODO: Improve overriding equality methods as per http://www.loganfranken.com/blog/687/overriding-equals-in-c-part-1/ /// <summary> /// Override of Equal Method /// </summary> /// <param name="obj"></param> /// <returns></returns> public override bool Equals(object obj) { if (obj == null || GetType() != obj.GetType()) { return(false); } gEdge e = (gEdge)obj; if (StartVertex.Equals(e.StartVertex) && EndVertex.Equals(e.EndVertex)) { return(true); } if (StartVertex.Equals(e.EndVertex) && EndVertex.Equals(e.StartVertex)) { return(true); } return(false); }
public double DistanceTo(gEdge edge) { // http://mathworld.wolfram.com/Line-LineDistance.html if (this.IsCoplanarTo(edge)) { var distances = new double[4] { StartVertex.DistanceTo(edge), EndVertex.DistanceTo(edge), edge.StartVertex.DistanceTo(this), edge.EndVertex.DistanceTo(this) }; return(distances.Min()); } else { var a = this.Direction; var b = edge.Direction; var c = gVector.ByTwoVertices(this.StartVertex, edge.StartVertex); gVector cross = a.Cross(b); double numerator = c.Dot(cross); double denominator = cross.Length; return(Math.Abs(numerator) / Math.Abs(denominator)); } }
public gBase Intersection(gEdge edge) { // http://mathworld.wolfram.com/Line-LineIntersection.html if (!this.IsCoplanarTo(edge)) { return(null); } if (edge.Contains(this.StartVertex)) { return(StartVertex); } if (edge.Contains(this.EndVertex)) { return(EndVertex); } var a = this.Direction; var b = edge.Direction; var c = gVector.ByTwoVertices(this.StartVertex, edge.StartVertex); var cxb = c.Cross(b); var axb = a.Cross(b); var dot = cxb.Dot(axb); // if dot == 0 it means that they are parallels if (Threshold(dot, 0)) { //Fully contains the test edge if (edge.StartVertex.OnEdge(this) && edge.EndVertex.OnEdge(this)) { return(edge); } else if (this.StartVertex.OnEdge(edge) || this.EndVertex.OnEdge(edge)) { gVertex[] vertices = new gVertex[4] { this.StartVertex, this.EndVertex, edge.StartVertex, edge.EndVertex }; var sorted = vertices.OrderBy(v => v.Y).ThenBy(v => v.X).ThenBy(v => v.Z).ToList(); return(gEdge.ByStartVertexEndVertex(sorted[1], sorted[2])); } else { return(null); } } double s = (dot) / Math.Pow(axb.Length, 2); // s > 1, means that "intersection" vertex is not on either edge // s == NaN means they are parallels so never intersect if (s < 0 || s > 1 || Double.IsNaN(s)) { return(null); } gVertex intersection = this.StartVertex.Translate(a.Scale(s)); if (intersection.Equals(edge.StartVertex)) { return(edge.StartVertex); } if (intersection.Equals(edge.EndVertex)) { return(edge.EndVertex); } if (!intersection.OnEdge(edge)) { return(null); } return(intersection); }
public bool OnEdge(gEdge edge) { return(this.OnEdge(edge.StartVertex, edge.EndVertex)); }