예제 #1
0
        private void BuildCurveVertexKdTree(IEnumerable <ObjectId> allIds, Transaction transaction,
                                            out Dictionary <ObjectId, CurveVertex[]> curveVertices, out CurveVertexKdTree <CurveVertex> kdTree)
        {
            kdTree        = null;
            curveVertices = new Dictionary <ObjectId, CurveVertex[]>();
            var allVertices = new List <CurveVertex>();

            foreach (var id in allIds)
            {
                var points = CurveUtils.GetCurveEndPoints(id, transaction);
                if (points.Length <= 0)
                {
                    continue;
                }

                var distinctPoints = GetDistinctPoints(points);
                // If distinctPoints.Length == 1, means it's self-loop
                if (distinctPoints.Length <= 1)
                {
                    continue;
                }

                var vertices = distinctPoints.Select(it => new CurveVertex(it, id));
                curveVertices[id] = vertices.ToArray();
                allVertices.AddRange(vertices);
            }
            kdTree = new CurveVertexKdTree <CurveVertex>(allVertices, it => it.Point.ToArray(), ignoreZ: true);
        }
예제 #2
0
 public UnclosedPolygonCheckResult(ObjectId sourceId)
     : base(ActionType.UnclosedPolygon, new ObjectId[] { sourceId })
 {
     using (var transaction = sourceId.Database.TransactionManager.StartTransaction())
     {
         _markPoints = CurveUtils.GetCurveEndPoints(sourceId, transaction);
         transaction.Commit();
     }
 }
예제 #3
0
        private IEnumerable <CurveCrossingInfo> FilterCrossInfos(IEnumerable <CurveCrossingInfo> crossInfos, out IEnumerable <CurveCrossingInfo> duplicateEntities)
        {
            duplicateEntities = new List <CurveCrossingInfo>();
            var result = new List <CurveCrossingInfo>();

            foreach (var curveCrossingInfo in crossInfos)
            {
                // Filter out duplicate entities
                if (AreDuplicateEntities(curveCrossingInfo))
                {
                    ((List <CurveCrossingInfo>)duplicateEntities).Add(curveCrossingInfo);
                    continue;
                }

                var sourcePoints = CurveUtils.GetCurveEndPoints(curveCrossingInfo.SourceId, _transaction);
                var targetPoints = new Point3d[0];
                if (curveCrossingInfo.TargetId != curveCrossingInfo.SourceId)
                {
                    targetPoints = CurveUtils.GetCurveEndPoints(curveCrossingInfo.TargetId, _transaction);
                }
                sourcePoints = DistinctEndPoints(sourcePoints);
                targetPoints = DistinctEndPoints(targetPoints);

                var points = new List <Point3d>();
                foreach (var point3D in curveCrossingInfo.IntersectPoints)
                {
                    // Whether point3D is end point of each cuve

                    //// If sourcePoints.Length is 1 or 0, means it's a loop, loop need to be splitted.
                    //if (sourcePoints.Length >= 2 && sourcePoints.Contains(point3D) &&
                    //    targetPoints.Length >= 2 && targetPoints.Contains(point3D))
                    //    continue;

                    // If curveCrossingInfo.SourceId == curveCrossingInfo.TargetId, it's a self intersection.
                    if (sourcePoints.Contains(point3D) && targetPoints.Contains(point3D) &&
                        curveCrossingInfo.SourceId != curveCrossingInfo.TargetId)
                    {
                        continue;
                    }

                    points.Add(point3D);
                }
                if (points.Count > 0)
                {
                    var newCrossingInfo = new CurveCrossingInfo(curveCrossingInfo.SourceId, curveCrossingInfo.TargetId,
                                                                points.ToArray());
                    result.Add(newCrossingInfo);
                }
            }
            return(result);
        }
예제 #4
0
        private IEnumerable <CurveVertex> GetCurveVertices(ObjectId id, HashSet <ObjectId> visitedIds)
        {
            var points = CurveUtils.GetCurveEndPoints(id, _transaction);

            if (points.Length <= 0)
            {
                return(new CurveVertex[0]);
            }

            // Remove the duplicate point
            // Note: if a curve has 2 same end points, means its a self-loop.
            var     distinctPoints = new List <Point3d>();
            Point3d current        = points[0];

            distinctPoints.Add(current);
            for (int i = 1; i < points.Length; i++)
            {
                if (points[i] != current)
                {
                    current = points[i];
                    distinctPoints.Add(current);
                }
            }
            if (distinctPoints.Count <= 1)
            {
                return(new CurveVertex[0]);
            }

            // Create vertices for the curve
            var vertices = new CurveVertex[distinctPoints.Count];

            for (int i = 0; i < distinctPoints.Count; i++)
            {
                vertices[i] = new CurveVertex(distinctPoints[i], id);
            }
            return(vertices);
        }
예제 #5
0
        private IEnumerable <SEdge <CurveVertex> > VisitCurve(CurveVertex?sourceVertex, ObjectId id, IEnumerable <ObjectId> allIds,
                                                              HashSet <ObjectId> visitedIds, Stack <KeyValuePair <ObjectId, CurveVertex> > candidates, Transaction transaction)
        {
            var points = CurveUtils.GetCurveEndPoints(id, transaction);

            // If none of the curve's end points is equal to the point, just return.
            // It means this curve is not a qualified one because it's not connected to sourceVertex.
            // Then it will be handled later because it belongs to another loop.
            if (sourceVertex != null && points.Length > 0 && !points.Contains(sourceVertex.Value.Point))
            {
                bool contains = false;
                foreach (var point in points)
                {
                    if (point.IsEqualTo(sourceVertex.Value.Point))
                    {
                        contains = true;
                    }
                }

                if (!contains)
                {
                    return(new SEdge <CurveVertex> [0]);
                }
            }

            // Mark it as visited.
            visitedIds.Add(id);
            // If there is no end points on the entity, just return.
            if (points.Length <= 0)
            {
                return(new SEdge <CurveVertex> [0]);
            }

            // Remove the duplicate point
            // Note: if a curve has 2 same end points, means its a self-loop.
            var     distinctPoints = new List <Point3d>();
            Point3d current        = points[0];

            distinctPoints.Add(current);
            for (int i = 1; i < points.Length; i++)
            {
                if (points[i] != current)
                {
                    current = points[i];
                    distinctPoints.Add(current);
                }
            }

            // Create vertices for the curve
            var vertices = new CurveVertex[distinctPoints.Count];

            for (int i = 0; i < distinctPoints.Count; i++)
            {
                vertices[i] = new CurveVertex(distinctPoints[i], id);
            }

            var result = new List <SEdge <CurveVertex> >();

            // Push vertex and adjacent curve into candidates
            foreach (var vertex in vertices)
            {
                if (sourceVertex != null && sourceVertex.Value.Point.IsEqualTo(vertex.Point))
                {
                    continue;
                }

                var adjacentIds = SelectCurves(vertex.Point);
                foreach (ObjectId adjacentId in adjacentIds)
                {
                    // If it has been visited.
                    if (visitedIds.Contains(adjacentId))
                    {
                        var originVertex = new CurveVertex(vertex.Point, adjacentId);
                        // If this curve has been pushed into the candidates stack before, there must exist a loop.
                        // So we create a back edge to the original vertex.
                        // NOTE: Use candidates.Contains(new KeyValuePair<ObjectId, CurveVertex>(id, originVertex))
                        // will cause a problem if two point are very close to each other
                        // such as (10.5987284839403,10.2186528623464,0) and (10.5987284839408,10.2186528623464,0)
                        var existing = candidates.FirstOrDefault(it => it.Key == id && it.Value == originVertex);
                        if (!existing.Equals(default(KeyValuePair <ObjectId, CurveVertex>)))
                        {
                            // Create edge back to the old vertex.
                            result.Add(new SEdge <CurveVertex>(vertex, existing.Value));
                        }
                        //if (candidates.Contains(new KeyValuePair<ObjectId, CurveVertex>(id, originVertex)))
                        //{
                        //    // Create edge back to the old vertex.
                        //    result.Add(new SEdge<CurveVertex>(vertex, originVertex));
                        //}
                        continue;
                    }

                    // If it's not in the collection of selected ids.
                    if (!allIds.Contains(adjacentId))
                    {
                        continue;
                    }

                    candidates.Push(new KeyValuePair <ObjectId, CurveVertex>(adjacentId, vertex));
                }
            }

            // Create edges
            int start = 0;

            if (sourceVertex != null)
            {
                for (int i = 0; i < vertices.Length; i++)
                {
                    if (vertices[i].Point.IsEqualTo(sourceVertex.Value.Point))
                    {
                        start = i;
                        // Add edge from sourceVertex to nearest point.
                        result.Add(new SEdge <CurveVertex>(sourceVertex.Value, vertices[start]));
                        break;
                    }
                }
            }

            if (vertices.Length == 1)
            {
                // Allan 2015/05/06: Self loop won't be handled - to improve performance.

                //// Self loop, create dummy vertex to let it to be a real loop
                //var dummy = new CurveVertex(vertices[0].Point + new Vector3d(1, 1, 1), id);
                //result.Add(new SEdge<CurveVertex>(vertices[0], dummy));
                //result.Add(new SEdge<CurveVertex>(dummy, vertices[0]));
            }
            else
            {
                // Must start from the vertex whose poitn is equal to source vertex's point.
                // Up
                var previousVertex = vertices[start];
                for (int i = start + 1; i < vertices.Length; i++)
                {
                    // Create a middle point to fix a bug - to avoid a line's two vertices are both in loop,
                    // but actually the line is not in a loop, for example
                    //        /\             /\
                    //       /  \           /  \
                    //      /____\A_______B/____\
                    // Point A and point B are both in a loop, but line AB is not in a loop.
                    // If I add a dummy point C in the middle of AB, then our graph could easily
                    // to determine C is not in a loop.
                    var middlePoint  = previousVertex.Point + (vertices[i].Point - previousVertex.Point) / 2.0;
                    var middleVertex = new CurveVertex(middlePoint, id);
                    result.Add(new SEdge <CurveVertex>(previousVertex, middleVertex));
                    result.Add(new SEdge <CurveVertex>(middleVertex, vertices[i]));
                    previousVertex = vertices[i];
                }
                // Down
                previousVertex = vertices[start];
                for (int i = start - 1; i >= 0; i--)
                {
                    var middlePoint  = previousVertex.Point + (vertices[i].Point - previousVertex.Point) / 2.0;
                    var middleVertex = new CurveVertex(middlePoint, id);
                    result.Add(new SEdge <CurveVertex>(previousVertex, middleVertex));
                    result.Add(new SEdge <CurveVertex>(middleVertex, vertices[i]));

                    previousVertex = vertices[i];
                }
            }

            return(result);
        }