public bool IsValid(decimal epsilon = 0.5m) { return(!GetCoplanarFaces().Any() && // Check coplanar faces !GetBackwardsFaces(epsilon).Any() && // Check faces are pointing outwards !Faces.Any(x => x.GetNonPlanarVertices(epsilon).Any()) && // Check face vertices are all on the plane Faces.All(x => x.IsConvex())); // Check all faces are convex }
protected override object GetFieldValue(Item cognitiveIndexable) { if (Faces == null || Faces.Length == 0) { return(null); } if (Faces.Any(x => x.FaceAttributes.Gender.Equals("male")) && Faces.Any(x => x.FaceAttributes.Gender.Equals("female"))) { return(2); } if (Faces.Any(x => x.FaceAttributes.Gender.Equals("male"))) { return(3); } if (Faces.Any(x => x.FaceAttributes.Gender.Equals("female"))) { return(4); } return(1); }
private bool _containsOnInside(Point passedPoint) { if (Faces.Any(face => face.Contains(passedPoint))) { return(false); } Line testLine = new Line(Point.Origin, passedPoint); Line intersectionLine; int counter = 0; Point intersectionPoint; foreach (Polygon face in this.Faces) { intersectionPoint = face.IntersectWithLine(testLine).As <Point>(); if (intersectionPoint != null) { intersectionLine = new Line(passedPoint, intersectionPoint); if (intersectionLine.Direction.Equals(testLine.Direction)) { counter++; } } } if (counter % 2 == 0) { return(false); } else { return(true); } }
public Face AddFace(Face face) { if (Faces.Any(f => f.IsMatchFor(face))) { throw new InvalidOperationException("There is allready such a face in the shape!"); } Faces.Add(face); return(face); }
public Face2D AddFace(Face2D face) { if (Faces.Any(f => f.IsMatchFor(face))) { //throw new InvalidOperationException("There is already such a face in the shape!"); Debug.Log("There is already such a face in the shape!"); return(face); } Faces.Add(face); face.Shape = this; _lazyExitedEdges.isValeChanged = true; _lazyAllEdges.isValeChanged = true; _lazyAllPoints.isValeChanged = true; return(face); }
/// <summary> /// Gets neighbours that do not have any uncovered neighbours and are not contained in any face. /// </summary> /// <param name="node"></param> /// <param name="nodeInFaces">Whether we found a node that is contained in a face.</param> /// <returns></returns> private List <TNode> GetSoloNeighbours(TNode node, out bool nodeInFaces) { var soloNeighbours = new List <TNode>(); nodeInFaces = false; foreach (var neighbour in Graph.GetNeighbours(node).Where(x => !IsCovered(x))) { if (UncoveredNeighboursCount(neighbour) == 0) { if (Faces.Any(x => x.Contains(neighbour))) { nodeInFaces = true; continue; } soloNeighbours.Add(neighbour); } } return(soloNeighbours); }
public bool Contains(Point point) { if (Faces.Any(face => face.Contains(point))) { return(true); } if (this.IsConvex) { foreach (Plane face in this.Faces) { if (face.PointIsOnNormalSide(point)) { return(false); } } } else { return(_containsOnInside(point)); } return(true); }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> Validates this mesh. </summary> /// /// <remarks> TODO: Think about this /// How much do we really want to do at this top level? Without making certain assumptions /// it's really difficult to do anything useful but we want to be as flexible as possible. /// Since we currently only create elements by adding faces, it's pretty safe, I think, to /// insist that all faces have at least three edges. /// /// Darrell Plank, 12/8/2017. </remarks> /// /// <returns> True if it succeeds, false if it fails. </returns> //////////////////////////////////////////////////////////////////////////////////////////////////// public virtual bool Validate() { if (VerticesInternal.Count == 0) { if (HalfEdgesInternal.Count != 0 && FacesInternal.Count != 0) { throw new MeshNavException("No vertices but we have other elements"); } } if (Faces.Any(face => face.Edges().Take(3).Count() != 3 && !face.IsBoundary)) { throw new MeshNavException("Faces with less than three sides not allowed"); } if (Faces.Where(f => f.IsAlive).Any(f => !f.HalfEdge.IsAlive)) { throw new MeshNavException("Live faces point to dead halfedges"); } if (Vertices.Where(v => v.IsAlive).Any(v => v.Mesh != this || !v.Edge.IsAlive)) { throw new MeshNavException("Live vertices point at dead half edges or don't belong to this mesh"); } if (HalfEdges.Where(he => he.IsAlive).Any(he => !he.InitVertex.IsAlive || he.Face != null && !he.Face.IsAlive)) { throw new MeshNavException("Live halfedge points at dead component"); } if (HalfEdges.Where(he => he.IsAlive).Any(he => he.InitVertex == he.Opposite.InitVertex)) { throw new MeshNavException("Edge and opposite oriented identically"); } return(true); }
/// <summary> /// Gets a path that is conencted to already discovered vertices. /// </summary> /// <remarks> /// It tries to minimize the number of chains with only a single node. /// </remarks> /// <returns></returns> private List <TNode> GetNextPath() { var firstVertex = default(TNode); var firstDepth = int.MaxValue; var foundFirst = false; // Save a node that is the covered neighbour of the firstVertex var hasOrigin = false; var origin = default(TNode); // Check if there is at least one covered node if (Graph.Vertices.Any(IsCovered)) { foreach (var node in Graph.Vertices.Where(x => !IsCovered(x))) { var coveredNeighbours = Graph.GetNeighbours(node).Where(IsCovered).ToList(); if (coveredNeighbours.Count == 0) { continue; } var minDepthIndex = coveredNeighbours.MinBy(GetDepth); var minDepth = GetDepth(coveredNeighbours[minDepthIndex]); if (minDepth < firstDepth) { firstVertex = node; firstDepth = minDepthIndex; foundFirst = true; hasOrigin = true; origin = coveredNeighbours[minDepthIndex]; } } } else { // If there are no covered nodes, find a one that is a leaf firstVertex = Graph.Vertices.First(x => Graph.GetNeighbours(x).Count() == 1); foundFirst = true; } // Must not happen if (!foundFirst) { throw new InvalidOperationException(); } var chain = new List <TNode>(); chain.Add(firstVertex); SetDepth(firstVertex, ChainsCounter); var nodeInFaces = false; // Check if we have an origin vertex and if the first vertex has any uncovered neighbour. // If it does not have any uncovered neighbour, it will normally form a chain of the lenght 1. // We want to prevent it and check if the origin node has any neighbour with the same characteristics. if (groupSoloVertices && hasOrigin && UncoveredNeighboursCount(firstVertex) == 0) { var soloNeighbours = GetSoloNeighbours(origin, out nodeInFaces); foreach (var neighbour in soloNeighbours) { chain.Add(neighbour); SetDepth(neighbour, ChainsCounter); } } while (true) { var lastNode = chain[chain.Count - 1]; var neighbours = Graph.GetNeighbours(lastNode).Where(x => !IsCovered(x)).ToList(); // Break if there are not neigbours if (neighbours.Count == 0) { break; } if (groupSoloVertices) { var soloNeighbours = GetSoloNeighbours(lastNode, out var nodeInFacesLocal); if (nodeInFacesLocal) { nodeInFaces = true; } // Add solo neighbours as above. // Break if we found at least one. if (soloNeighbours.Count != 0) { foreach (var neighbour in soloNeighbours) { chain.Add(neighbour); SetDepth(neighbour, ChainsCounter); } break; } } var nextNode = neighbours[0]; if (Faces.Any(x => x.Contains(nextNode))) { nodeInFaces = true; } chain.Add(nextNode); SetDepth(nextNode, ChainsCounter); // Break if we found a node that is contained in a face. // We do not want this path to continue with that face. if (nodeInFaces) { break; } } ChainsCounter++; return(chain); }