//Vertices need to be reduced to 2D //see Akenine-Möller, Tomas; Haines, Eric; Hoffman, Naty (2016): Real-Time Rendering, p. 754 /// <summary> /// Tests if a point/vertex lies inside or outside a face - Only use this if you know the face AND vertex lie in the same plane and this plane is parallel to xy or xz or yz! /// </summary> /// <param name="geometry">The geometry the polygon (here: face) belongs to.</param> /// <param name="face">The faces to be tested. It will not be Reduced2D!</param> /// <param name="v">The vertex to be tested.</param> /// <returns></returns> public static bool IsPointInPolygon(this Geometry geometry, Face face, float3 v) { var inside = false; var faceVerts = geometry.GetFaceVertices(face.Handle).ToList(); var v1 = geometry.GetVertexByHandle(faceVerts.Last().Handle); var v1Pos = geometry.Get2DVertPos(face, v1.Handle); var y0 = v1Pos.y >= v.y; foreach (var vert in faceVerts) { var e1Pos = geometry.Get2DVertPos(face, vert.Handle); var y1 = e1Pos.y >= v.y; if (y0 != y1) { if ((e1Pos.y - v.y) * (v1Pos.x - e1Pos.x) >= (e1Pos.x - v.x) * (v1Pos.y - e1Pos.y) == y1) { inside = !inside; } } y0 = y1; v1Pos = e1Pos; } return(inside); }
private static bool IsPolygonRightOfVert(Geometry geometry, Face face, IList <HalfEdge> faceHalfEdges, Vertex vert) { var prevV = GetPrevVertex(face, faceHalfEdges, vert); var nextV = GetNextVertex(face, faceHalfEdges, vert); var redPrevPos = geometry.Get2DVertPos(face, prevV.Handle); var redNextPos = geometry.Get2DVertPos(face, nextV.Handle); return(redPrevPos.y > redNextPos.y); }
//Vertices need to be reduced to 2D. /// <summary> /// Determines if the angle between two vectors, formed by three vertices, is greater or equal 180°. /// The first vector will be created from v1 and v2, the second from v2 and v3. /// </summary> /// <param name="geom">The geometry the vertices belong to.</param> /// <param name="face">The face the vertices belong to.</param> /// <param name="v1">Vertex one</param> /// <param name="v2">Vertex two</param> /// <param name="v3">Vertex three</param> /// <returns></returns> public static bool IsAngleGreaterOrEqualPi(this Geometry geom, Face face, Vertex v1, Vertex v2, Vertex v3) { var v1Pos = geom.Get2DVertPos(face, v1.Handle); var v2Pos = geom.Get2DVertPos(face, v2.Handle); var v3Pos = geom.Get2DVertPos(face, v3.Handle); var firstVec = v1Pos - v2Pos; var secondVec = v3Pos - v2Pos; var cross = firstVec.x * secondVec.y - firstVec.y * secondVec.x; //Z component of the cross product. var dot = float3.Dot(firstVec, secondVec); var angle = (float)System.Math.Atan2(cross, dot); return(angle <= 0); }
//Vertices need to be reduced to 2D. /// <summary> /// Determines whether the angle between two vectors formed by three vertices is greater than 180 °. /// The first vector will be created from v1 and v2, the second from v2 and v3. /// </summary> /// <param name="geom">The geometry the vertices belong to.</param> /// <param name="face">The face the vertices belong to.</param> /// <param name="v1">Vertex one</param> /// <param name="v2">Vertex two</param> /// <param name="v3">Vertex three</param> /// <returns></returns> public static bool IsAngleGreaterPi(this Geometry geom, Face face, Vertex v1, Vertex v2, Vertex v3) { var v1Pos = geom.Get2DVertPos(face, v1.Handle); var v2Pos = geom.Get2DVertPos(face, v2.Handle); var v3Pos = geom.Get2DVertPos(face, v3.Handle); var firstVec = v1Pos - v2Pos; var secondVec = v3Pos - v2Pos; var det = firstVec.x * secondVec.y - firstVec.y * secondVec.x; //determinant / Z component of the cross product / sine / y var dot = float3.Dot(firstVec, secondVec); // cosine / x var angle = (float)System.Math.Atan2(det, dot); if ((angle * -1).Equals(M.Pi)) { return(false); } return(angle < 0); }
//Vertices need to be reduced to 2D. private static IList <Vertex> GetSortedVertices(Geometry geometry, Face face, IEnumerable <Vertex> unsortedVerts) { var sorted = new List <Vertex>(); sorted.AddRange(unsortedVerts); sorted.Sort(delegate(Vertex a, Vertex b) { var redA = geometry.Get2DVertPos(face, a.Handle); var redB = geometry.Get2DVertPos(face, b.Handle); var ydiff = -1 * redA.y.CompareTo(redB.y); if (ydiff != 0) { return(ydiff); } return(redA.x.CompareTo(redB.x)); }); return(sorted); }
//Vertices need to be reduced to 2D. private static bool IsUnderVert(Face face, Vertex middle, Vertex neighbour) { var redMiddle = _geometry.Get2DVertPos(face, middle.Handle); var redNeighbour = _geometry.Get2DVertPos(face, neighbour.Handle); if (redMiddle.y > redNeighbour.y) { return(true); } if (redMiddle.y.Equals(redNeighbour.y) && redMiddle.x < redNeighbour.x) { return(true); } return(false); }