private bool IsCutElement(XContinuumElement2D element) { var polygon = ConvexPolygon2D.CreateUnsafe(element.Nodes); // Look at each segment foreach (var crackSegment in Segments) { var segment = new LineSegment2D(crackSegment.Start, crackSegment.End); CartesianPoint intersectionPoint; foreach (var edge in polygon.Edges) { LineSegment2D.SegmentSegmentPosition position = segment.IntersectionWith(edge, out intersectionPoint); if (position == LineSegment2D.SegmentSegmentPosition.Intersecting) { // TODO: Perhaps the element should not be flagged as a Heaviside element, if the segment passes // through 1 node only. To detect this, check if the intersection point coincides with an element // node. If it does store it and go to the next edge. If a second intersection point (that does // not coincide with the stored one) is found then it is a Heaviside element. return(true); } else if (position == LineSegment2D.SegmentSegmentPosition.Overlapping) { return(true); } } } // Look at the vertices // (if a segment is entirely inside an element, it will not be caught by checking the segment itself) bool previousVertexOnEdge = false; LinkedListNode <CartesianPoint> currentNode = Vertices.First.Next; LinkedListNode <CartesianPoint> lastNode = Vertices.Last; while (currentNode != lastNode) { PolygonPointPosition position = polygon.FindRelativePositionOfPoint(currentNode.Value); if (position == PolygonPointPosition.Inside) { return(true); } else if (position == PolygonPointPosition.OnEdge || position == PolygonPointPosition.OnVertex) { if (previousVertexOnEdge) { return(true); } else { previousVertexOnEdge = true; } } else { previousVertexOnEdge = false; } currentNode = currentNode.Next; } return(false); }
public SortedSet <CartesianPoint> FindTriangleVertices(XContinuumElement2D element) { var polygon = ConvexPolygon2D.CreateUnsafe(element.Nodes); var triangleVertices = new SortedSet <CartesianPoint>(element.Nodes, pointComparer); int nodesCount = element.Nodes.Count; foreach (var vertex in Vertices) { PolygonPointPosition position = polygon.FindRelativePositionOfPoint(vertex); if (position == PolygonPointPosition.Inside || position == PolygonPointPosition.OnEdge || position == PolygonPointPosition.OnVertex) { triangleVertices.Add(vertex); } } foreach (var crackSegment in Segments) { var segment = new LineSegment2D(crackSegment.Start, crackSegment.End); IReadOnlyList <CartesianPoint> intersections = segment.IntersectionWith(polygon); foreach (var point in intersections) { triangleVertices.Add(point); } } return(triangleVertices); }
public NodePosition FindRelativePosition(XNode node) { PolygonPointPosition pos = polygon.FindRelativePositionOfPoint(node); if (pos == PolygonPointPosition.Outside) { return(NodePosition.External); } else if ((pos == PolygonPointPosition.OnEdge) || (pos == PolygonPointPosition.OnVertex)) { // On the inter-subdomain part of the polygon's outline foreach (var boundary in boundaries) { if (boundary.FindRelativePositionOfPoint(node) == LineSegment2D.SegmentPointPosition.PointOnSegment) { return(NodePosition.Boundary); } } // otherwise return(NodePosition.Internal); } else if (pos == PolygonPointPosition.Inside) { return(NodePosition.Internal); } else { throw new Exception("This code should not have been reached"); } }
public List <XContinuumElement2D> FindElementsThatContains(IEnumerable <XContinuumElement2D> elements, CartesianPoint point) { var result = new List <XContinuumElement2D>(); foreach (var element in elements) { var outline = ConvexPolygon2D.CreateUnsafe(element.Nodes); PolygonPointPosition position = outline.FindRelativePositionOfPoint(point); if (position == PolygonPointPosition.Inside) { result.Add(element); break; } else if ((position == PolygonPointPosition.OnEdge) || (position == PolygonPointPosition.OnVertex)) { result.Add(element); } } if (result.Count == 0) { throw new KeyNotFoundException("No element containing the point " + point + "was found"); } return(result); }
// TODO: handle cases where more the point lies on an element edge or node. public IReadOnlyList <TElement> FindElementsContainingPoint(CartesianPoint point, TElement startingElement = null) { var containingElements = new List <TElement>(); foreach (TElement element in Elements) // O(elementsCount) { var outline = ConvexPolygon2D.CreateUnsafe(element.Nodes.ToCartesianPoints()); PolygonPointPosition pos = outline.FindRelativePositionOfPoint(point); if ((pos == PolygonPointPosition.Inside) || (pos == PolygonPointPosition.OnEdge) || (pos == PolygonPointPosition.OnVertex)) { containingElements.Add(element); } } return(containingElements); }
private bool IsTipElement(XContinuumElement2D element, CrackTipPosition tipPosition) { CartesianPoint crackTip, adjacentVertex; if (tipPosition == CrackTipPosition.Start) { crackTip = Vertices.First.Value; adjacentVertex = Vertices.First.Next.Value; } else if (tipPosition == CrackTipPosition.End) { crackTip = Vertices.Last.Value; adjacentVertex = Vertices.Last.Previous.Value; } else { throw new ArgumentException("Tip position can be either start or end"); } var polygon = ConvexPolygon2D.CreateUnsafe(element.Nodes); PolygonPointPosition relativeTipPos = polygon.FindRelativePositionOfPoint(crackTip); if (relativeTipPos == PolygonPointPosition.Inside || relativeTipPos == PolygonPointPosition.OnEdge || relativeTipPos == PolygonPointPosition.OnVertex) { PolygonPointPosition previousVertexPos = polygon.FindRelativePositionOfPoint(adjacentVertex); if (previousVertexPos == PolygonPointPosition.Inside) { throw new NotImplementedException("Problem with blending elements, if the tip element is also " + "enriched with Heaviside. What happens after the crack tip? Based on the LSM, the signed " + "distance of the blending element after the crack tip should have a positive and negative " + "region, however that element is not split by the crack and thus should not have " + "discontinuity in the displacement field"); //return ElementEnrichmentType.Both; } return(true); } return(false); }
private ElementEnrichmentType CharacterizeElementEnrichment(XContinuumElement2D element) { var polygon = ConvexPolygon2D.CreateUnsafe(element.Nodes); int tipIndex = Vertices.Count - 1; // Check tip element PolygonPointPosition tipPosition = polygon.FindRelativePositionOfPoint(Vertices[tipIndex]); if (tipPosition == PolygonPointPosition.Inside || tipPosition == PolygonPointPosition.OnEdge || tipPosition == PolygonPointPosition.OnVertex) { PolygonPointPosition previousVertexPos = polygon.FindRelativePositionOfPoint(Vertices[tipIndex - 1]); if (previousVertexPos == PolygonPointPosition.Inside) { // Problem with blending elements, if the tip element is also enriched with Heaviside. What happens // after the crack tip? Based on the LSM, the signed distance of the blending element after the // crack tip should have a positive and negative region, however that element is not split by the // crack and thus should not have discontinuity in the displacement field. var builder = new StringBuilder(); builder.Append("Crack tip "); builder.Append(Vertices[Vertices.Count - 1].ToString()); builder.Append(" and kink point "); builder.Append(Vertices[Vertices.Count - 2].ToString()); builder.Append(" inside the same element with nodes: "); foreach (var node in element.Nodes) { builder.Append(node.ToString()); builder.Append(' '); } throw new ArgumentException(builder.ToString()); //return ElementEnrichmentType.Both; } else { return(ElementEnrichmentType.Tip); } } // Look at the other vertices // (if a segment is inside an element, it will not be caught by checking the segment itself) bool previousVertexOnEdge = false; for (int v = 0; v < tipIndex; ++v) { PolygonPointPosition position = polygon.FindRelativePositionOfPoint(Vertices[v]); if (position == PolygonPointPosition.Inside) { return(ElementEnrichmentType.Heaviside); } else if (position == PolygonPointPosition.OnEdge || position == PolygonPointPosition.OnVertex) { if (previousVertexOnEdge) { return(ElementEnrichmentType.Heaviside); } else { previousVertexOnEdge = true; } } else { previousVertexOnEdge = false; } } // Look at each segment foreach (var crackSegment in Segments) { var segment = new LineSegment2D(crackSegment.Start, crackSegment.End); CartesianPoint intersectionPoint; foreach (var edge in polygon.Edges) { LineSegment2D.SegmentSegmentPosition position = segment.IntersectionWith(edge, out intersectionPoint); if (position == LineSegment2D.SegmentSegmentPosition.Intersecting) { // TODO: Perhaps the element should not be flagged as a Heaviside element, if the segment passes // through 1 node only. To detect this, check if the intersection point coincides with an element // node. If it does store it and go to the next edge. If a second intersection point (that does // not coincide with the stored one) is found then it is a Heaviside element. return(ElementEnrichmentType.Heaviside); } else if (position == LineSegment2D.SegmentSegmentPosition.Overlapping) { return(ElementEnrichmentType.Heaviside); } } } // Then it must be a standard element return(ElementEnrichmentType.Standard); }