Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        /// <summary>
        /// If a fixed enrichment area is applied, all nodes inside a circle around the tip are enriched with tip
        /// functions. They can still be enriched with Heaviside functions, if they do not belong to the tip
        /// element(s).
        /// </summary>
        /// <param name="tipNodes"></param>
        /// <param name="tipElement"></param>
        private void ApplyFixedEnrichmentArea(CartesianPoint crackTip, XContinuumElement2D tipElement,
                                              HashSet <XNode> tipNodes, IEnrichmentItem2D tipEnrichments)
        {
            if (enrichmentRadiusOverElementSize > 0)
            {
                var    outline        = ConvexPolygon2D.CreateUnsafe(tipElement.Nodes);
                double elementArea    = outline.ComputeArea();
                double radius         = enrichmentRadiusOverElementSize * Math.Sqrt(elementArea);
                var    enrichmentArea = new Circle2D(crackTip, radius);

                foreach (var element in Mesh.FindElementsInsideCircle(enrichmentArea, tipElement))
                {
                    bool completelyInside = true;
                    foreach (var node in element.Nodes)
                    {
                        CirclePointPosition position = enrichmentArea.FindRelativePositionOfPoint(node);
                        if ((position == CirclePointPosition.Inside) || (position == CirclePointPosition.On))
                        {
                            tipNodes.Add(node);
                        }
                        else
                        {
                            completelyInside = false;
                        }
                    }

                    if (completelyInside)
                    {
                        element.EnrichmentItems.Add(tipEnrichments);
                    }
                }
            }
        }
Beispiel #4
0
        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);
        }
        public IReadOnlyList <GaussPoint> GenerateIntegrationPoints(XContinuumElement2D element)
        {
            SortedSet <CartesianPoint>   cartesianDelaunyPoints = crack.FindTriangleVertices(element);
            IReadOnlyList <NaturalPoint> naturalDelaunyPoints   =
                FindNaturalPointsForTriangulation(element, cartesianDelaunyPoints);
            IReadOnlyList <Triangle2D <NaturalPoint> > subtriangles;

            if (double.IsPositiveInfinity(triangleOverElementArea))
            {
                subtriangles = triangulator.CreateMesh(naturalDelaunyPoints);
            }
            else
            {
                double elementArea = (ConvexPolygon2D.CreateUnsafe(element.Nodes)).ComputeArea();
                subtriangles = triangulator.CreateMesh(naturalDelaunyPoints, triangleOverElementArea * elementArea);
            }

            var integrationPoints = new List <GaussPoint>();

            foreach (Triangle2D <NaturalPoint> triangle in subtriangles)
            {
                integrationPoints.AddRange(GenerateIntegrationPointsOfTriangle(triangle));
            }
            return(integrationPoints);
        }
Beispiel #6
0
        /// <summary>
        /// 生成外轮廓多边形
        /// </summary>
        /// <param name="grid"></param>
        /// <param name="me"></param>
        /// <param name="startSearchPoint"></param>
        /// <param name="limitDistance"></param>
        /// <param name="isBlockOutPoly">是否为挡格的轮廓多边形,是的时候需要倒序处理</param>
        /// <returns></returns>
        private static ContourPoly GeneralOutPoly(RLEGridMap grid, MapElement me, Float2 startSearchPoint, float limitDistance, bool isBlockOutPoly)
        {
            ContourPoly    poly   = new ContourPoly();
            List <Double2> points = me.GetContourPoints(grid, startSearchPoint);

            if (isBlockOutPoly == true)
            {
                points.Reverse();
            }
            List <int>     listIndex = ConvexPolygon2D.GenerateConvexPolygonIndex(points.ToArray());
            List <Double2> polys     = new List <Double2>();

            for (int i = 0; i < listIndex.Count; i++)
            {
                if (i < listIndex.Count - 1)
                {
                    OptimizationContourConvexLine(listIndex[i], listIndex[i + 1], false, limitDistance, points, ref polys);
                }
                else
                {
                    OptimizationContourConvexLine(listIndex[i], listIndex[0], true, limitDistance, points, ref polys);
                }
            }
            poly.InitData(polys);
            return(poly);
        }
Beispiel #7
0
        public CrackElementPosition FindRelativePositionOf(XContinuumElement2D element)
        {
            CartesianPoint crackTip        = lsm.GetCrackTip(CrackTipPosition.Single);
            double         minBodyLevelSet = double.MaxValue;
            double         maxBodyLevelSet = double.MinValue;
            double         minTipLevelSet  = double.MaxValue;
            double         maxTipLevelSet  = double.MinValue;

            foreach (XNode node in element.Nodes)
            {
                double bodyLevelSet = lsm.LevelSetsBody[node];
                double tipLevelSet  = lsm.LevelSetsTip[node];
                if (bodyLevelSet < minBodyLevelSet)
                {
                    minBodyLevelSet = bodyLevelSet;
                }
                if (bodyLevelSet > maxBodyLevelSet)
                {
                    maxBodyLevelSet = bodyLevelSet;
                }
                if (tipLevelSet < minTipLevelSet)
                {
                    minTipLevelSet = tipLevelSet;
                }
                if (tipLevelSet > maxTipLevelSet)
                {
                    maxTipLevelSet = tipLevelSet;
                }
            }

            //Warning: this might actually be worse than Stolarska's criterion. At least that one enriched the dubious
            //intersected elements with tip enrichments. This one just ignores them.
            if (minBodyLevelSet * maxBodyLevelSet <= 0.0)
            {
                if (minTipLevelSet * maxTipLevelSet <= 0)
                {
                    var outline = ConvexPolygon2D.CreateUnsafe(element.Nodes);
                    if (outline.IsPointInsidePolygon(crackTip))
                    {
                        return(CrackElementPosition.ContainsTip);
                    }
                }
                else if (maxTipLevelSet < 0)
                {
                    return(CrackElementPosition.Intersected);
                }
            }
            return(CrackElementPosition.Irrelevant);
        }
        public IReadOnlyList <TElement> FindElementsIntersectedByCircle(Circle2D circle, TElement startingElement = null)
        {
            var intersectedElements = new List <TElement>();

            foreach (TElement element in Elements)
            {
                var outline = ConvexPolygon2D.CreateUnsafe(element.Nodes.ToCartesianPoints());
                CirclePolygonPosition relativePosition = outline.FindRelativePositionOfCircle(circle);
                if (relativePosition == CirclePolygonPosition.Intersecting)
                {
                    intersectedElements.Add(element);
                }
            }
            return(intersectedElements);
        }
        // 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);
        }
Beispiel #10
0
        // TODO: This method should directly return the elements and take care of cases near the domain boundaries (see Ahmed)
        // TODO: The J-integral radius should not exceed the last crack segment's length
        public double ComputeRadiusOfJintegralOuterContour(TipCoordinateSystem tipSystem,
                                                           IReadOnlyList <XContinuumElement2D> tipElements)
        {
            double maxTipElementArea = -1.0;

            foreach (var element in tipElements)
            {
                var    outline     = ConvexPolygon2D.CreateUnsafe(element.Nodes.Select(node => (CartesianPoint)node).ToArray());
                double elementArea = outline.ComputeArea();
                if (elementArea > maxTipElementArea)
                {
                    maxTipElementArea = elementArea;
                }
            }
            return(magnificationOfJintegralRadius * Math.Sqrt(maxTipElementArea));
        }
Beispiel #11
0
        //TODO: replace this with the Faster~() version
        public CrackElementPosition FindRelativePositionOf(XContinuumElement2D element)
        {
            CartesianPoint crackTip        = lsm.GetCrackTip(CrackTipPosition.Single);
            double         minBodyLevelSet = double.MaxValue;
            double         maxBodyLevelSet = double.MinValue;
            double         minTipLevelSet  = double.MaxValue;
            double         maxTipLevelSet  = double.MinValue;

            foreach (XNode node in element.Nodes)
            {
                double bodyLevelSet = lsm.LevelSetsBody[node];
                double tipLevelSet  = lsm.LevelSetsTip[node];
                if (bodyLevelSet < minBodyLevelSet)
                {
                    minBodyLevelSet = bodyLevelSet;
                }
                if (bodyLevelSet > maxBodyLevelSet)
                {
                    maxBodyLevelSet = bodyLevelSet;
                }
                if (tipLevelSet < minTipLevelSet)
                {
                    minTipLevelSet = tipLevelSet;
                }
                if (tipLevelSet > maxTipLevelSet)
                {
                    maxTipLevelSet = tipLevelSet;
                }
            }

            // Warning: This criterion might give false positives for tip elements (see Serafeim's thesis for details)
            if (minBodyLevelSet * maxBodyLevelSet <= 0.0)
            {
                var outline = ConvexPolygon2D.CreateUnsafe(element.Nodes);
                if (outline.IsPointInsidePolygon(crackTip))
                {
                    return(CrackElementPosition.ContainsTip);
                }
                else if (maxTipLevelSet < 0)
                {
                    return(CrackElementPosition.Intersected);
                }
            }
            return(CrackElementPosition.Irrelevant);
        }
Beispiel #12
0
        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);
        }
 /// <summary>
 ///
 /// </summary>
 /// <param name="allVertices"></param>
 /// <param name="boundaryVertices">If the all vertices are boundary, then this list needs to start and end with the same
 ///     vertex.</param>
 public PolygonalRegion(IReadOnlyList <CartesianPoint> allVertices, HashSet <LineSegment2D> boundaries)
 {
     this.polygon    = ConvexPolygon2D.CreateUnsafe(allVertices);
     this.boundaries = boundaries;
 }
Beispiel #14
0
 public Polygonal2DBoundary(IReadOnlyList <CartesianPoint> vertices)
 {
     polygon = ConvexPolygon2D.CreateUnsafe(vertices);
 }
Beispiel #15
0
        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);
        }