/// <summary> 判断半边道路的挖填情况 </summary>
        /// <param name="center"></param>
        /// <param name="leftSide">左侧还是右侧</param>
        /// <param name="slopeFill">此侧边坡的填挖情况</param>
        /// <param name="treatmentDepth">浅挖路基的翻挖压实处理的最底部距离路面顶的深度,一般为1.5m左右</param>
        /// <param name="ground">自然地面</param>
        /// <returns>此侧路基中,需要进行翻挖压实处理的路基宽度。
        ///     当边坡为填方时(且道路中线处为挖方),此时自然地面线一般会与路面线相交,返回相交后靠近道路中线侧的挖方宽度;
        ///     如果自然地面线与路面线不相交(),则将此侧道路按全挖方考虑,且为全浅挖</returns>
        private static double HalfRoadShallowCut(SectionInfo center, bool leftSide, bool?slopeFill,
                                                 double treatmentDepth, Polyline ground)
        {
            var centerCutWidth = 0.0;

            var halfRoadWidth = leftSide
                ? center.CenterX - center.LeftRoadEdge.X
                : center.RightRoadEdge.X - center.CenterX; // 路面+路肩

            if (slopeFill == null || !slopeFill.Value)
            {
                // 说明不是填方
                centerCutWidth = halfRoadWidth;
            }
            else
            {
                // 说明中心为挖方,而边坡为填方
                var bottomPt = new Point2d(center.CenterX, center.CenterY - treatmentDepth);
                var inters   = new CurveCurveIntersector2d(ground.Get2dLinearCurve(),
                                                           new Ray2d(bottomPt, new Vector2d(leftSide ? -1 : 1, 0)));
                if (inters.NumberOfIntersectionPoints == 0)
                {
                    centerCutWidth = halfRoadWidth;
                }
                else
                {
                    centerCutWidth = Math.Abs(inters.GetIntersectionPoint(0).X - center.CenterX);
                    if (centerCutWidth > halfRoadWidth)
                    {
                        centerCutWidth = halfRoadWidth;
                    }
                }
            }
            return(centerCutWidth);
        }
Exemple #2
0
        private static List <Point2d> CalcGeologPtsByDepth(Point2d p0, Point2d p1, int[] interval,
                                                           List <Point2d> groundSurfPoly, double depthMultipier)
        {
            List <Point2d> polygonPts = new List <Point2d>();

            LineSegment2d geologSegment = new LineSegment2d(p0, p1);

            //начало отрезка
            LineSegment2d           surfSegment0 = new LineSegment2d(groundSurfPoly[interval[0]], groundSurfPoly[interval[0] + 1]);
            Line2d                  vert0        = new Line2d(p0, Vector2d.YAxis);
            CurveCurveIntersector2d intersector0 = new CurveCurveIntersector2d(vert0, surfSegment0);

            if (intersector0.NumberOfIntersectionPoints > 0)
            {
                Point2d surfPt0            = intersector0.GetPointOnCurve2(0).Point;
                double  depth0             = (surfPt0.Y - p0.Y) * depthMultipier;
                Point2d convertedGeologPt0 = surfPt0 - Vector2d.YAxis * depth0;
                polygonPts.Add(convertedGeologPt0);
            }

            //все точки поверхности между началом и концом отрезка
            if (!geologSegment.Direction.IsParallelTo(Vector2d.YAxis))
            {
                for (int i = interval[0]; i <= interval[1]; i++)
                {
                    Point2d surfPt = groundSurfPoly[i];
                    Line2d  vert   = new Line2d(surfPt, Vector2d.YAxis);
                    CurveCurveIntersector2d intersector = new CurveCurveIntersector2d(vert, geologSegment);
                    if (intersector.NumberOfIntersectionPoints > 0)
                    {
                        Point2d geologPt          = intersector.GetPointOnCurve2(0).Point;
                        double  depth             = (surfPt.Y - geologPt.Y) * depthMultipier;
                        Point2d convertedGeologPt = surfPt - Vector2d.YAxis * depth;
                        polygonPts.Add(convertedGeologPt);
                    }
                }
            }


            //конец отрезка
            LineSegment2d           surfSegment1 = new LineSegment2d(groundSurfPoly[interval[1] - 1], groundSurfPoly[interval[1]]);
            Line2d                  vert1        = new Line2d(p1, Vector2d.YAxis);
            CurveCurveIntersector2d intersector1 = new CurveCurveIntersector2d(vert1, surfSegment1);

            if (intersector1.NumberOfIntersectionPoints > 0)
            {
                Point2d surfPt1            = intersector1.GetPointOnCurve2(0).Point;
                double  depth1             = (surfPt1.Y - p1.Y) * depthMultipier;
                Point2d convertedGeologPt1 = surfPt1 - Vector2d.YAxis * depth1;
                polygonPts.Add(convertedGeologPt1);
            }

            return(polygonPts);
        }
Exemple #3
0
        /// <summary>
        /// Расчет пересечений двух линий
        /// С учетом допусков автокада
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="p3"></param>
        /// <param name="p4"></param>
        /// <returns></returns>
        public static Point2d?GetLinesIntersectionAcad(Point2d p1, Point2d p2, Point2d p3, Point2d p4)
        {
            Point2d?                pt          = null;
            LineSegment2d           line1       = new LineSegment2d(p1, p2);
            LineSegment2d           line2       = new LineSegment2d(p3, p4);
            CurveCurveIntersector2d intersector = new CurveCurveIntersector2d(line1, line2);

            if (intersector.NumberOfIntersectionPoints > 0)
            {
                pt = intersector.GetIntersectionPoint(0);
            }
            return(pt);
        }
        /// <summary> 构造函数 </summary>
        /// <param name="docMdf"></param>
        /// <param name="roadCurve"></param>
        /// <param name="groundCurve"></param>
        public LongitudinalSection(DocumentModifier docMdf, CompositeCurve3d roadCurve, CompositeCurve3d groundCurve)
        {
            _docMdf       = docMdf;
            RoadCurve2d   = roadCurve.Get2dLinearCurve();
            GroundCurve2d = groundCurve.Get2dLinearCurve();
            //
            StartStation = RoadCurve2d.StartPoint.X;
            EndStation   = RoadCurve2d.EndPoint.X;

            // 求交点
            Intersects = new CurveCurveIntersector2d(RoadCurve2d, GroundCurve2d);
            GetIntersects();
            //_road = Curve.CreateFromGeCurve(roadCurve) as Polyline;
            //_ground = Curve.CreateFromGeCurve(groundCurve) as Polyline;
        }
Exemple #5
0
            private PointOnCurve2d GetSplitPt(CivilDB.Structure str, bool start)
            {
                Curve2d strPosCurve = StructurePosCurve(str);
                CurveCurveIntersector2d intersector = new CurveCurveIntersector2d(PositionCurve, strPosCurve);

                if (intersector.NumberOfIntersectionPoints > 0)
                {
                    intersector.OrderWithRegardsTo1();
                    //взять точку пересечения, которая имеет имеет наибольший параметр PositionCurve для начальной точки
                    //и наименьший для конечной точки
                    return(start ? intersector.GetPointOnCurve1(intersector.NumberOfIntersectionPoints - 1)
                        : intersector.GetPointOnCurve1(0));
                }
                return(null);
            }
        private double?[,] GetZArray(Point2dCollection[] collections, double sizeX)
        {
            var distance    = TechProcess.Tool.Diameter / 2;
            var countX      = (int)(sizeX / StepX2) + 1;
            var zArray      = new double?[collections.Length, countX];
            var intersector = new CurveCurveIntersector2d();

            Acad.SetLimitProgressor(collections.Length);

            var rays = Enumerable.Range(0, countX).Select(p => new Ray2d(new Point2d(p * StepX2, 0), Vector2d.YAxis)).ToList();

            for (int i = 0; i < collections.Length; i++)
            {
                Acad.ReportProgressor();

                if (collections[i] == null)
                {
                    continue;
                }

                var polylene    = new PolylineCurve2d(collections[i]);
                var offsetCurve = polylene.GetTrimmedOffset(distance, OffsetCurveExtensionType.Fillet)[0];

                for (int j = 0; j < countX; j++)
                {
                    intersector.Set(offsetCurve, rays[j]);
                    if (intersector.NumberOfIntersectionPoints == 1)
                    {
                        zArray[i, j] = intersector.GetIntersectionPoint(0).Y - distance;
                    }
                }
                //if (i < 50)
                //{
                //    Draw.Pline(polylene.GetSamplePoints(10).Select(p => new Point3d(p.X + i * 100, p.Y + 1000, 0)));
                //    Draw.Pline(offsetCurve.GetSamplePoints(10).Select(p => new Point3d(p.X + i * 100, p.Y + 1000, 0)));
                //}
                //else
                //{
                polylene.Dispose();
                offsetCurve.Dispose();
                //}
            }
            rays.ForEach(p => p.Dispose());
            intersector.Dispose();

            return(zArray);
        }
        /// <summary> 纵断面中某个桩号所对应的填方高度,如果为负值,则代表挖方高度 </summary>
        /// <param name="station"></param>
        /// <returns></returns>
        public double GetFillHeight(double station)
        {
            var intersVerticalRoad = new CurveCurveIntersector2d(RoadCurve2d,
                                                                 new Line2d(new Point2d(station, 0), new Vector2d(0, 1)));
            var intersVerticalGround = new CurveCurveIntersector2d(GroundCurve2d,
                                                                   new Line2d(new Point2d(station, 0), new Vector2d(0, 1)));

            if (intersVerticalRoad.NumberOfIntersectionPoints == 0 ||
                intersVerticalGround.NumberOfIntersectionPoints == 0)
            {
                // 这种情况一般不会出现
            }
            else
            {
                var yRoad   = intersVerticalRoad.GetIntersectionPoint(0).Y;
                var yGround = intersVerticalGround.GetIntersectionPoint(0).Y;
                return(yRoad - yGround);
            }
            return(0.0);
        }
            private bool AddIntersection(LineSegment2d intersectionSeg, LinearEntity2d vert, HatchNestingNode hatchNode, SortedSet <Node> vertSorted)
            {
                bool result = false;
                CurveCurveIntersector2d intersector = new CurveCurveIntersector2d(intersectionSeg, vert);

                if (intersector.NumberOfIntersectionPoints > 0)
                {
                    Point2d intersectionPt = intersector.GetPointOnCurve1(0).Point;
                    //если точка пересечения контура и вертикали имеет ту же координату X,
                    //что и начало или конец контура, то это пересечение не учитывается!
                    if (!Utils.LengthIsEquals(intersectionPt.X, hatchNode.Extents.MinPoint.X) &&
                        !Utils.LengthIsEquals(intersectionPt.X, hatchNode.Extents.MaxPoint.X))   //допуск
                    {
                        double param = hatchNode.Boundary.GetParameterOf(intersectionPt);

                        Node newIntersectionNode = new Node(hatchNode, param, intersectionPt);
                        if (!vertSorted.Contains(newIntersectionNode))//TODO: Нужен учет допуска???
                        {
                            result = true;
                            notVisited.Add(newIntersectionNode);

                            vertSorted.Add(newIntersectionNode);
                            SortedSet <Node> boundarySorted = null;
                            boundariesSorted.TryGetValue(hatchNode, out boundarySorted);
                            if (boundarySorted == null)
                            {
                                boundarySorted = new SortedSet <Node>(new NodeParamComparer());//сортировка по параметру!!!
                                boundariesSorted.Add(hatchNode, boundarySorted);
                            }

                            if (boundarySorted.Contains(newIntersectionNode))
                            {
                                throw new Exception("Ошибка логики обхода полигона. Получены 2 точки с одинаковым параметром на одной кривой");
                            }

                            boundarySorted.Add(newIntersectionNode);
                        }
                    }
                }
                return(result);
            }
Exemple #9
0
        public static List <Point2d> GetProcessPoints1(Curve profile, int index, double step, double shift, bool isMinToolCoord, double?begin, double?end, bool isProfileStep = false)  //, bool isExactlyBegin, bool isExactlyEnd)
        {
            var result    = new List <Point2d>();
            var start     = 10000D;
            var rayVector = index == 0 ? -Vector2d.YAxis : -Vector2d.XAxis;

            var p0  = begin ?? Math.Max(profile.StartPoint[index], profile.EndPoint[index]);
            var p1  = end ?? Math.Min(profile.StartPoint[index], profile.EndPoint[index]);
            var dir = Math.Sign(p1 - p0);

            using (var curve = profile.ToCompositeCurve2d())
                using (var ray = new Ray2d())
                    using (var intersector = new CurveCurveIntersector2d())
                    {
                        var     pos       = p0;
                        Point2d?point0    = null;
                        var     length    = profile.Length();
                        int     curveSign = dir * Math.Sign(curve.EndPoint[index] - curve.StartPoint[index]);
                        double? dist      = null;

                        while (dir > 0 ? pos <p1 : pos> p1)
                        {
                            double?max = null;
                            for (int i = 0; i <= 10; i++)
                            {
                                var rayPoint = GetPoint(pos + i * (shift / 10) * dir, start, index);
                                ray.Set(rayPoint, rayVector);
                                intersector.Set(curve, ray);
                                if (intersector.NumberOfIntersectionPoints > 0)
                                {
                                    var intersect = intersector.GetIntersectionPoint(0);
                                    max = Math.Max(max ?? double.MinValue, intersect[1 - index]);
                                    if (!point0.HasValue && i == 0)
                                    {
                                        point0 = intersect;
                                    }
                                }
                            }
                            if (max.HasValue)
                            {
                                var toolCoord = pos + shift * dir * (isMinToolCoord ^ dir < 0 ? 0 : 1);
                                result.Add(GetPoint(toolCoord, max.Value, index));
                            }
                            if (isProfileStep && point0.HasValue)
                            {
                                if (!dist.HasValue)
                                {
                                    dist = curve.GetLength(0, curve.GetParameterOf(point0.Value));
                                }
                                dist += step * curveSign;
                                if (dist < 0 || dist > length)
                                {
                                    break;
                                }
                                var point = curve.EvaluatePoint(curve.GetParameterAtLength(0, dist.Value, true));
                                pos = point[index];
                            }
                            else
                            {
                                pos += step * dir;
                            }
                        }
                    }
            return(result);
        }
        /// <summary> 低填路堤 </summary>
        /// <param name="centerAxis"></param>
        /// <param name="width"> 左右路堤坡底之间的宽度</param>
        /// <param name="height"> 自然地面以下地基加固的高度</param>
        /// <returns></returns>
        public static bool IsThinFill(Database db, SubgradeSection centerAxis, out double width, out double height)
        {
            var center = centerAxis.XData;

            height = 0.0;
            width  = 0.0;
            // 1. 基本判断标准
            var depth = center.CenterElevation_Road - center.CenterElevation_Ground;

            double leftWidth1  = 0.0;
            double rightWidth1 = 0.0;

            // 道路中心为填方,而且左右至少有一侧为填方边坡
            if (depth >= 0 && depth <= _criterion.低填最大高度 &&
                ((center.LeftSlopeFill == null || center.LeftSlopeFill.Value) ||
                 (center.RightSlopeFill == null || center.RightSlopeFill.Value)))
            {
                // 道路中心线 与 自然地面线的交点
                var centerGroundPt = new Point3d(center.CenterX, center.GetYFromElev(center.CenterElevation_Ground), 0);

                // 左侧低填处理的宽度
                var leftRoadWidth = center.CenterX - center.LeftRoadEdge.X;
                if (center.LeftSlopeFill == null || !center.LeftSlopeFill.Value)
                {
                    // 无边坡线或者是挖方
                    leftWidth1 = leftRoadWidth;
                }
                else
                {
                    var leftSlope = center.LeftSlopeHandle.GetDBObject <Polyline>(db);
                    if (leftSlope == null)
                    {
                        leftWidth1 = leftRoadWidth;
                    }
                    else
                    {
                        // 先计算填方边坡线与
                        var leftInters = new CurveCurveIntersector2d(leftSlope.Get2dLinearCurve(),
                                                                     new Ray2d(centerGroundPt.ToXYPlane(), new Vector2d(-1, 0)));
                        if (leftInters.NumberOfIntersectionPoints == 0)
                        {
                            leftWidth1 = leftRoadWidth;
                        }
                        else
                        {
                            leftWidth1 = Math.Abs(leftInters.GetIntersectionPoint(0).X - center.CenterX);
                        }
                    }
                }

                // 右侧低填处理的宽度
                var rightRoadWidth = center.RightRoadEdge.X - center.CenterX;
                if (center.RightSlopeFill == null || !center.RightSlopeFill.Value)
                {
                    // 无边坡线或者是挖方
                    rightWidth1 = rightRoadWidth;
                }
                else
                {
                    var rightSlope = center.RightSlopeHandle.GetDBObject <Polyline>(db);
                    if (rightSlope == null)
                    {
                        rightWidth1 = rightRoadWidth;
                    }
                    else
                    {
                        // 先计算填方边坡线与
                        var rightInters = new CurveCurveIntersector2d(rightSlope.Get2dLinearCurve(),
                                                                      new Ray2d(centerGroundPt.ToXYPlane(), new Vector2d(1, 0)));
                        if (rightInters.NumberOfIntersectionPoints == 0)
                        {
                            rightWidth1 = rightRoadWidth;
                        }
                        else
                        {
                            rightWidth1 = Math.Abs(rightInters.GetIntersectionPoint(0).X - center.CenterX);
                        }
                    }
                }

                width = leftWidth1 + rightWidth1;
                //
                if (width > 0)
                {
                    // 低填路堤的自然地面下部地基处理的高度
                    height = _criterion.低填处理高度 - (center.CenterElevation_Road - center.CenterElevation_Ground);
                    if (height < 0)
                    {
                        height = 0;
                    }
                    return(true);
                }
            }
            return(false);
        }
Exemple #11
0
        /// <summary>
        /// 判断某一侧边坡是否为陡坡路堤
        /// </summary>
        /// <param name="slp">某一侧边坡,其值可能为null,表示此侧没有边坡线 </param>
        /// <param name="ground">边坡所对应的自然地面线</param>
        /// <param name="treatedWidth"></param>
        /// <param name="setReinforcement">是否要设置加筋结构,比如铺设三层土工格栅</param>
        /// <returns></returns>
        private bool IsSteepFill(SectionInfo sec, bool left, SlopeLine slp, Polyline ground, out double treatedWidth,
                                 out double stairArea, out bool setReinforcement)
        {
            treatedWidth     = 0;
            stairArea        = 0;
            setReinforcement = false;
            var slopeFill = (slp == null) || slp.XData.FillCut;

            // ----------------------------------------------------------------------------------------
            // 确定进行搜索的左右边界:路基边缘(或边坡脚) 到 道路中线
            var    cGround = ground.Get2dLinearCurve();
            double edgeXleft;
            double edgeXright;
            var    succ = sec.GetFillSlopeXRange(left, slp, cGround, _docMdf.acDataBase, out edgeXleft, out edgeXright);

            if (!succ)
            {
                return(false);
            }
            // ----------------------------------------------------------------------------------------
            // ---------此时 [edgeXleft ~ edgeXright] 区间内应该都是填方区域 --------------------------

            //
            var segCounts = (int)Math.Ceiling((edgeXright - edgeXleft) / _criterion.最小迭代宽度); // 其值最小为1
            var xInterval = (edgeXright - edgeXleft) / segCounts;
            var xYs       = new List <double[]>();
            var cSlope    = slp?.Pline.Get2dLinearCurve();

            for (int i = 0; i <= segCounts; i++)
            {
                var    x = edgeXleft + i * xInterval;
                double yGround;
                var    inters = new CurveCurveIntersector2d(cGround, new Line2d(new Point2d(x, 0), new Vector2d(0, 1)));
                // 没有交点的情况一般不会出现,因为自然地面线的范围很广
                yGround = inters.NumberOfIntersectionPoints == 0 ? 0 : inters.GetIntersectionPoint(0).Y;

                double ySlope;
                if (cSlope == null) // 表示没有边坡线
                {
                    ySlope = 0;
                }
                else
                {
                    inters = new CurveCurveIntersector2d(cSlope, new Line2d(new Point2d(x, 0), new Vector2d(0, 1)));

                    // 没有交点的情况必然会出现,即x对应路基位置,而不是对应边坡位置,比如当路基下的自然地面线是向路基中心倾斜时。
                    ySlope = inters.NumberOfIntersectionPoints == 0 ? sec.CenterY : inters.GetIntersectionPoint(0).Y;
                }
                //
                xYs.Add(new double[3] {
                    x, yGround, ySlope
                });
            }

            // 每隔x间距时,自然地面的Y值
            var xyGround = xYs.Select(r => new double[] { r[0], r[1] }).ToList();

            // 开始求斜率(集合中至少有两个元素)。每个元素为三分量向量,分别为 X 坐标、X对应的自然地面的Y坐标,X对应的边坡的Y坐标
            double maxRatio = 0;
            double maxYFill;

            var lastX = xYs[0];

            maxYFill = lastX[2] - lastX[1];
            for (int i = 1; i < xYs.Count; i++)
            {
                var thisX = xYs[i];
                maxRatio = Math.Max(maxRatio, Math.Abs((thisX[1] - lastX[1]) / (thisX[0] - lastX[0])));
                maxYFill = Math.Max(maxYFill, Math.Abs(thisX[2] - thisX[1]));
                //
                lastX = thisX;
            }
            // 判断是否为陡坡路堤
            if (maxRatio >= (1 / _criterion.陡坡坡比))
            {
                // 道路中心与边坡均为填方
                treatedWidth = edgeXright - edgeXleft;
                stairArea    = CalculateStairArea(xyGround, edgeXleft, edgeXright);

                if (slopeFill && treatedWidth > 0 && maxYFill >= _criterion.加筋体对应填方段最小高度)
                {
                    setReinforcement = true;
                }
                return(true);
            }
            //
            return(false);
        }
Exemple #12
0
        /// <summary> 初始化每一个填挖交界点所占据的几何区间 </summary>
        /// <param name="longitudinalSection"></param>
        /// <returns></returns>
        private void ConstructIntersectRange(LongitudinalSection longitudinalSection)
        {
            var inters = longitudinalSection.Intersects;

            //

            // 将结果整理为二维数组,用来进行表格输出
            var rows   = new List <object[]>();
            var header = new object[] { "交界点坐标", "交界方式", "10m填方段最大高度", "10m挖方段最大高度", "处理方式" };

            rows.Add(header);

            int interval        = 2;
            var fillLargerThan  = 5.0;
            int fillCheckLength = 10;
            var arrCutToFill    = ArrayConstructor.FromRangeAri(0, fillCheckLength, interval);
            var arrFillToCut    = ArrayConstructor.FromRangeAri(0, -fillCheckLength, -interval);

            var blocks = Options_Collections.RangeBlocks;

            for (int i = 0; i < inters.NumberOfIntersectionPoints; i++)
            {
                var ptRoad   = inters.GetPointOnCurve1(i);
                var ptGround = inters.GetPointOnCurve2(i);

                // 排除桥梁等结构区域
                if (blocks.Any(r => r.ContainsStation(ptRoad.Point.X)))
                {
                    continue;
                }
                //
                var fillToCut = longitudinalSection.FilltoCut(ptRoad, ptGround);
                var arrDx     = fillToCut ? arrFillToCut : arrCutToFill;
                var intersX   = ptRoad.Point.X;

                // 填挖交界处的路基,在填方段10m范围内高度H<5m时,按断面A实施,H>5m时,按断面B实施。
                var maxVerticalDiff_Fill = 0.0;
                foreach (var dx in arrDx)
                {
                    var x = intersX + dx;
                    var intersVerticalRoad = new CurveCurveIntersector2d(longitudinalSection.RoadCurve2d,
                                                                         new Line2d(new Point2d(x, 0), new Vector2d(0, 1)));
                    var intersVerticalGround = new CurveCurveIntersector2d(longitudinalSection.GroundCurve2d,
                                                                           new Line2d(new Point2d(x, 0), new Vector2d(0, 1)));
                    if (intersVerticalRoad.NumberOfIntersectionPoints == 0 ||
                        intersVerticalGround.NumberOfIntersectionPoints == 0)
                    {
                        break;
                    }
                    else
                    {
                        var verticalDiff = intersVerticalRoad.GetIntersectionPoint(0).Y -
                                           intersVerticalGround.GetIntersectionPoint(0).Y;
                        if (verticalDiff > maxVerticalDiff_Fill)
                        {
                            maxVerticalDiff_Fill = verticalDiff;
                        }
                    }
                }

                var maxVerticalDiff_Cut = 0.0;
                foreach (var dx in arrDx)
                {
                    var x = intersX - dx;
                    var intersVerticalRoad = new CurveCurveIntersector2d(longitudinalSection.RoadCurve2d,
                                                                         new Line2d(new Point2d(x, 0), new Vector2d(0, 1)));
                    var intersVerticalGround = new CurveCurveIntersector2d(longitudinalSection.GroundCurve2d,
                                                                           new Line2d(new Point2d(x, 0), new Vector2d(0, 1)));
                    if (intersVerticalRoad.NumberOfIntersectionPoints == 0 ||
                        intersVerticalGround.NumberOfIntersectionPoints == 0)
                    {
                        break;
                    }
                    else
                    {
                        var verticalDiff = intersVerticalGround.GetIntersectionPoint(0).Y -
                                           intersVerticalRoad.GetIntersectionPoint(0).Y;

                        if (verticalDiff > maxVerticalDiff_Cut)
                        {
                            maxVerticalDiff_Cut = verticalDiff;
                        }
                    }
                }

                string fill      = fillToCut ? "填 - 挖" : "挖 - 填";
                var    reinforce = (maxVerticalDiff_Fill > fillLargerThan) ? "超挖换填 + 土工格栅" : "超挖换填";
                //
                rows.Add(new object[]
                {
                    ptRoad.Point.X, fill, maxVerticalDiff_Fill, maxVerticalDiff_Cut, reinforce
                });
            }

            var sheetArr = ArrayConstructor.FromList2D(listOfRows: rows);
            // sheetArr = sheetArr.InsertVector<object, string, object>(true, new[] { header }, new[] { -1.5f, });

            // 输出到表格
            var sheet_Infos = new List <WorkSheetData>
            {
                new WorkSheetData(WorkSheetDataType.SteepSlope, "纵向填挖交界", sheetArr)
            };

            ExportWorkSheetDatas(sheet_Infos);
            //
        }
Exemple #13
0
        /// <summary>
        /// 判断某一侧边坡的填方边坡类型
        /// </summary>
        /// <param name="slp">某一侧边坡,其值可能为null,表示此侧没有边坡线 </param>
        /// <param name="ground">边坡所对应的自然地面线</param>
        /// <param name="treatedWidth"></param>
        /// <param name="stairArea">某一侧边坡所挖台阶面积</param>
        /// <returns></returns>
        private FillSlopeType GetFillSlopeType(SectionInfo sec, bool left, SlopeLine slp, Polyline ground,
                                               out double treatedWidth, out double stairArea)
        {
            treatedWidth = 0;
            stairArea    = 0.0;
            double edgeXleft;
            double edgeXright;
            var    cGround = ground.Get2dLinearCurve();
            var    succ    = sec.GetFillSlopeXRange(left, slp, cGround, _docMdf.acDataBase, out edgeXleft, out edgeXright);

            if (!succ)
            {
                return(FillSlopeType.Other);
            }

            // 必须是填方边坡
            if ((left && (sec.LeftSlopeFill == null || !sec.LeftSlopeFill.Value)) ||
                (!left && (sec.RightSlopeFill == null || !sec.RightSlopeFill.Value)))
            {
                return(FillSlopeType.Other);
            }

            // 有路肩墙
            if ((left && sec.LeftRetainingWallType == RetainingWallType.路肩墙) || (!left && sec.RightRetainingWallType == RetainingWallType.路肩墙))
            {
                return(FillSlopeType.Other);
            }

            //
            var segCounts = (int)Math.Ceiling((edgeXright - edgeXleft) / _criterion.最小迭代宽度); // 其值最小为1
            var xInterval = (edgeXright - edgeXleft) / segCounts;
            var xYs       = new List <double[]>();

            for (int i = 0; i <= segCounts; i++)
            {
                var    x = edgeXleft + i * xInterval;
                double yGround;
                var    inters = new CurveCurveIntersector2d(cGround, new Line2d(new Point2d(x, 0), new Vector2d(0, 1)));
                // 没有交点的情况一般不会出现,因为自然地面线的范围很广
                yGround = inters.NumberOfIntersectionPoints == 0 ? 0 : inters.GetIntersectionPoint(0).Y;
                //
                xYs.Add(new double[] { x, yGround });
            }
            // 开始求斜率(集合中至少有两个元素)。每个元素为三分量向量,分别为 X 坐标、X对应的自然地面的Y坐标,X对应的边坡的Y坐标
            double maxRatio      = 0;
            bool   hasStairExcav = false;
            var    lastX         = xYs[0];

            for (int i = 1; i < xYs.Count; i++)
            {
                var thisX    = xYs[i];
                var segRatio = Math.Abs((thisX[1] - lastX[1]) / (thisX[0] - lastX[0]));
                if ((segRatio > 1 / _criterion.填方坡比下限) && (segRatio > 1 / _criterion.填方坡比下限))
                {
                    hasStairExcav = true;
                }
                maxRatio = Math.Max(maxRatio, segRatio);
                //
                lastX = thisX;
            }
            if (!hasStairExcav)
            {
                return(FillSlopeType.Other);
            }
            else
            {
                //  判断是否为陡坡路堤,如果是,则不计入挖台阶工程量表中(因为在陡坡路堤工程量表中已经计入)
                if (maxRatio >= (1 / _criterion.陡坡坡比))
                {
                    treatedWidth = 0;
                    return(FillSlopeType.SteepSlope);
                }
                else
                {
                    //
                    treatedWidth = edgeXright - edgeXleft;
                    stairArea    = Exporter_SteepSlope.CalculateStairArea(xYs, edgeXleft, edgeXright);
                    return(FillSlopeType.StairExcav);
                }
            }
        }
Exemple #14
0
        /// <summary>
        /// 计算道路横断面的某一侧中,从路面中心到边坡外边缘的范围内,属于填方的区域在 AutoCAD 几何中的 X 范围
        /// </summary>
        /// <param name="sec"></param>
        /// <param name="left"></param>
        /// <param name="slp"> 某一侧边坡,其值可能为null,表示此侧没有边坡线 </param>
        /// <param name="cGround"></param>
        /// <param name="db"></param>
        /// <param name="edgeXleft">此侧边坡的填方左边界</param>
        /// <param name="edgeXright">此侧边坡的填方右边界</param>
        /// <returns>如果没有填方区域,则返回 false </returns>
        public bool GetFillSlopeXRange(bool left, SlopeLine slp, CompositeCurve2d cGround, Database db,
                                       out double edgeXleft, out double edgeXright)
        {
            edgeXleft  = 0.0;
            edgeXright = 0.0;
            var centerFill = IsCenterFill();
            var slopeFill  = slp == null || slp.XData.FillCut;

            if (!centerFill && (slp == null || !slopeFill))
            {
                return(false);
            }

            // 确定进行搜索的左右边界:路基边缘(或边坡脚) 到 道路中线
            double roadEdge = left ? LeftRoadEdge.X : RightRoadEdge.X;

            double slopeEdge = roadEdge; // 边坡的坡脚的 X 值

            if (slp != null && slp.XData.Slopes.Count > 0)
            {
                var data = slp.XData;
                slopeEdge = data.Slopes[data.Slopes.Count - 1].OuterPoint.X;
            }
            if (centerFill && slopeFill)
            {
                // 道路中心与边坡均为填方
                double edgeX1 = CenterX;

                edgeXleft  = Math.Min(edgeX1, slopeEdge);
                edgeXright = Math.Max(edgeX1, slopeEdge);
            }
            else
            {
                // 说明 坡脚与道路中心这二者中有一个为挖方,另一个为填方
                var    roadSurfHandle = left ? LeftRoadSurfaceHandle : RightRoadSurfaceHandle;
                var    roadSurf       = roadSurfHandle.GetDBObject <Polyline>(db);
                var    cRoad          = roadSurf.Get2dLinearCurve();
                var    inters         = new CurveCurveIntersector2d(cRoad, cGround);
                double iX;
                if (inters.NumberOfIntersectionPoints > 0)
                {
                    iX = inters.GetIntersectionPoint(0).X;
                }
                else
                {
                    // 这种情况极少会出现,但测试中确实会有,即自然地面线与挖方坡底边沟相交,而不与路面相交
                    iX = roadEdge;
                }
                // 自然地面与路面的交点
                var roadWidth  = Math.Abs((roadEdge - CenterX));
                var innerRatio = Math.Abs((iX - CenterX) / roadWidth);
                if ((centerFill && innerRatio > 0.5))
                {
                    // 靠道路中心为填方,边坡为挖方
                    if (left)
                    {
                        edgeXleft  = iX;
                        edgeXright = CenterX;
                    }
                    else
                    {
                        edgeXleft  = CenterX;
                        edgeXright = iX;
                    }
                }
                else if (!centerFill && innerRatio <= 0.5)
                {
                    // 靠道路中心为挖方,边坡为填方
                    if (left)
                    {
                        edgeXleft  = slopeEdge;
                        edgeXright = iX;
                    }
                    else
                    {
                        edgeXleft  = iX;
                        edgeXright = slopeEdge;
                    }
                }
                else
                {
                    // 填方区域太小
                    return(false);
                }
            }
            return(true);
        }
        private void Create3dProfile(object arg)
        {
            try
            {
                if (doc != null)
                {
                    List <ObjectId> toHighlight = new List <ObjectId>();

                    using (doc.LockDocument())
                    {
                        Editor   ed = doc.Editor;
                        Database db = doc.Database;

                        using (Transaction tr = db.TransactionManager.StartTransaction())
                        {
                            //найти координату X начала профиля (крайнюю левую)
                            double          minx        = double.PositiveInfinity;
                            List <ObjectId> allSelected = new List <ObjectId>(soilHatchIds);
                            foreach (ObjectId id in allSelected)
                            {
                                Entity ent = null;
                                try
                                {
                                    ent = (Entity)tr.GetObject(id, OpenMode.ForRead);
                                }
                                catch (Autodesk.AutoCAD.Runtime.Exception) { continue; }
                                Extents3d?ext = ent.Bounds;
                                if (ext != null)
                                {
                                    Point3d minPt = ext.Value.MinPoint;
                                    if (minx > minPt.X)
                                    {
                                        minx = minPt.X;
                                    }
                                }
                            }


                            //Штриховки должны быть заранее раскиданы по слоям в соответствии с ИГЭ!

                            //пересчет всех точек штриховок в координаты:
                            //X - положение отностиельно начала профиля с учетом горизонтального масштаба профиля,
                            //Y - отметка расчитанная согласно базовой отметке с учетом вертикального масштаба профиля
                            Matrix2d transform =
                                new Matrix2d(new double[]
                            {
                                HorScaling, 0, 0,
                                0, VertScaling, 0,
                                0, 0, 1
                            })
                                * Matrix2d.Displacement(new Vector2d(-minx, -ElevBasePoint.Value.Y + ElevationInput / VertScaling));

                            C5.IntervalHeap <HatchEvent> eventQueue            = new C5.IntervalHeap <HatchEvent>();
                            List <HatchData>             allHatchData          = new List <HatchData>();
                            List <Point2dCollection>     selfintersectingLoops = new List <Point2dCollection>();
                            foreach (ObjectId id in soilHatchIds)
                            {
                                //получить все точки штриховок с учетом возможных дуг, сплайнов и проч
                                //Для каждой штриховки создается набор композитных кривых, состоящих из линейных сегментов
                                Hatch hatch = null;
                                try
                                {
                                    hatch = (Hatch)tr.GetObject(id, OpenMode.ForRead);
                                }
                                catch (Autodesk.AutoCAD.Runtime.Exception) { continue; }
                                List <CompositeCurve2d>  boundaries   = new List <CompositeCurve2d>();
                                List <Extents2d>         extends      = new List <Extents2d>();
                                List <Point2dCollection> ptsCollList  = new List <Point2dCollection>();
                                List <List <double> >    ptParamsList = new List <List <double> >();
                                for (int i = 0; i < hatch.NumberOfLoops; i++)
                                {
                                    HatchLoop hl = hatch.GetLoopAt(i);
                                    if (!hl.LoopType.HasFlag(HatchLoopTypes.SelfIntersecting) &&
                                        !hl.LoopType.HasFlag(HatchLoopTypes.Textbox) &&
                                        !hl.LoopType.HasFlag(HatchLoopTypes.TextIsland) &&
                                        !hl.LoopType.HasFlag(HatchLoopTypes.NotClosed))
                                    {
                                        List <Curve2d>   curves = Utils.GetHatchLoopCurves(hl);
                                        List <Curve2d>   compositeCurveElems = new List <Curve2d>();
                                        double           _minx         = double.PositiveInfinity;
                                        double           _miny         = double.PositiveInfinity;
                                        double           _maxx         = double.NegativeInfinity;
                                        double           _maxy         = double.NegativeInfinity;
                                        Action <Point2d> updateExtends = new Action <Point2d>(p =>
                                        {
                                            _minx = p.X < _minx ? p.X : _minx;
                                            _miny = p.Y < _miny ? p.Y : _miny;
                                            _maxx = p.X > _maxx ? p.X : _maxx;
                                            _maxy = p.Y > _maxy ? p.Y : _maxy;
                                        });

                                        Point2dCollection ptsColl   = new Point2dCollection();
                                        List <double>     ptParams  = new List <double>();
                                        double            currParam = 0;
                                        foreach (Curve2d c in curves)
                                        {
                                            if (!(c is LineSegment2d))
                                            {
                                                Interval         interval  = c.GetInterval();
                                                PointOnCurve2d[] samplePts = c.GetSamplePoints(interval.LowerBound, interval.UpperBound, 0.02);

                                                Point2d[] pts = samplePts.Select(p => transform * p.Point).ToArray();
                                                for (int n = 0; n < pts.Length - 1; n++)
                                                {
                                                    LineSegment2d lineSeg = new LineSegment2d(pts[n], pts[n + 1]);
                                                    compositeCurveElems.Add(lineSeg);

                                                    ptsColl.Add(pts[n]);
                                                    ptParams.Add(currParam);
                                                    updateExtends(pts[n]);
                                                    currParam += lineSeg.Length;
                                                }
                                            }
                                            else
                                            {
                                                LineSegment2d lineSeg = (LineSegment2d)c;
                                                lineSeg.TransformBy(transform);
                                                compositeCurveElems.Add(lineSeg);

                                                ptsColl.Add(lineSeg.StartPoint);
                                                ptParams.Add(currParam);
                                                updateExtends(lineSeg.StartPoint);
                                                currParam += lineSeg.Length;
                                            }
                                        }


                                        CompositeCurve2d boundary = new CompositeCurve2d(compositeCurveElems.ToArray());
                                        Extents2d        ext      = new Extents2d(_minx, _miny, _maxx, _maxy);
                                        boundaries.Add(boundary);
                                        ptsCollList.Add(ptsColl);
                                        ptParamsList.Add(ptParams);
                                        extends.Add(ext);
                                    }
                                }

                                //контуры штриховок не могут иметь самопересечений!
                                #region Проверка на пересечения
                                //проверка на самопересечения
                                //bool badBoundaries = false;
                                HashSet <int> badBoundaries   = new HashSet <int>();
                                HashSet <int> splitBoundaries = new HashSet <int>();//Если 2 контура в одной штриховке пересекаются, то разносить их по разным штриховкам
                                //List<HatchData> decomposeHatchData = new List<HatchData>();//TODO: самопересекающиеся полигоны нужно разбить на отдельные по количеству самопересечний.

                                for (int i = 0; i < boundaries.Count; i++)
                                {
                                    CompositeCurve2d        b           = boundaries[i];
                                    CurveCurveIntersector2d intersector = new CurveCurveIntersector2d(b, b);
                                    if (intersector.NumberOfIntersectionPoints > 0)
                                    {
                                        //если происходит только наложение???
                                        badBoundaries.Add(i);
                                        selfintersectingLoops.Add(ptsCollList[i]);
                                    }
                                }

                                if (boundaries.Count > 1)
                                {
                                    //проверка на взаимные пересечения.
                                    //Исп RBush для того чтобы избежать проверки на пересечение каждого с каждым и квадратичной сложности
                                    //(работает только если контуры разнесены)
                                    //Не брать в расчет пересечения по касательной
                                    RBush <Spatial> boundariesRBush = new RBush <Spatial>();
                                    List <Spatial>  spatialData     = new List <Spatial>();
                                    for (int i = 0; i < extends.Count; i++)
                                    {
                                        spatialData.Add(new Spatial(extends[i], i));
                                    }
                                    boundariesRBush.BulkLoad(spatialData);
                                    foreach (Spatial s in spatialData)
                                    {
                                        IReadOnlyList <Spatial> nearestNeighbors = boundariesRBush.Search(s.Envelope);
                                        if (nearestNeighbors.Count > 1)
                                        {
                                            CompositeCurve2d thisCurve = boundaries[(int)s.Obj];
                                            foreach (Spatial n in nearestNeighbors)
                                            {
                                                if (!s.Equals(n))
                                                {
                                                    CompositeCurve2d        otherCurve = boundaries[(int)n.Obj];
                                                    CurveCurveIntersector2d intersector
                                                        = new CurveCurveIntersector2d(thisCurve, otherCurve);
                                                    if (intersector.NumberOfIntersectionPoints > 0 ||
                                                        intersector.OverlapCount > 0)
                                                    {
                                                        bool matches = false;
                                                        //Проверить, что кривые не накладываются друг на друга по всей длине (то есть полностью совпадают)
                                                        if (intersector.OverlapCount > 0)
                                                        {
                                                            //сумма длин всех интервалов перекрытия равна общей длине кривой
                                                            double thisCurveOverlapLength  = 0;
                                                            double otherCurveOverlapLength = 0;
                                                            for (int i = 0; i < intersector.OverlapCount; i++)
                                                            {
                                                                Interval[] intervals           = intersector.GetOverlapRanges(i);
                                                                Interval   thisOverlapInterval = intervals[0];
                                                                thisCurveOverlapLength += thisOverlapInterval.Length;
                                                                Interval otherOverlapInterval = intervals[1];
                                                                otherCurveOverlapLength += otherOverlapInterval.Length;
                                                            }

                                                            Interval thisCurveInterval  = thisCurve.GetInterval();
                                                            Interval otherCurveInterval = otherCurve.GetInterval();

                                                            if (Utils.LengthIsEquals(thisCurveOverlapLength, thisCurveInterval.Length) &&
                                                                Utils.LengthIsEquals(otherCurveOverlapLength, otherCurveInterval.Length))
                                                            {
                                                                matches = true;
                                                            }
                                                        }

                                                        if (!matches)
                                                        {
                                                            splitBoundaries.Add((int)s.Obj);
                                                            splitBoundaries.Add((int)n.Obj);
                                                        }
                                                        else
                                                        {
                                                            badBoundaries.Add((int)s.Obj);
                                                            badBoundaries.Add((int)n.Obj);
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }

                                splitBoundaries.ExceptWith(badBoundaries);
                                List <HatchData> splitHatchData = new List <HatchData>();
                                if (badBoundaries.Count > 0 || splitBoundaries.Count > 0)
                                {
                                    List <CompositeCurve2d>  boundariesClear   = new List <CompositeCurve2d>();
                                    List <Extents2d>         extendsClear      = new List <Extents2d>();
                                    List <Point2dCollection> ptsCollListClear  = new List <Point2dCollection>();
                                    List <List <double> >    ptParamsListClear = new List <List <double> >();

                                    for (int i = 0; i < boundaries.Count; i++)
                                    {
                                        if (!badBoundaries.Contains(i) && !splitBoundaries.Contains(i))
                                        {
                                            boundariesClear.Add(boundaries[i]);
                                            extendsClear.Add(extends[i]);
                                            ptsCollListClear.Add(ptsCollList[i]);
                                            ptParamsListClear.Add(ptParamsList[i]);
                                        }
                                    }

                                    foreach (int index in splitBoundaries)
                                    {
                                        splitHatchData.Add(new HatchData(
                                                               new HatchNestingNode(
                                                                   boundaries[index],
                                                                   extends[index],
                                                                   ptsCollList[index],
                                                                   ptParamsList[index], hatch)));
                                    }


                                    boundaries   = boundariesClear;
                                    extends      = extendsClear;
                                    ptsCollList  = ptsCollListClear;
                                    ptParamsList = ptParamsListClear;
                                }
                                #endregion

                                //определяется вложенность контуров штриховки
                                //ЕСЛИ ШТРИХОВКА СОСТОИТ ИЗ 2 И БОЛЕЕ КОНТУРОВ, КОТОРЫЕ НЕ ВЛОЖЕНЫ ДРУГ В ДРУГА,
                                //ТО ЭТИ КОНТУРЫ ДОЛЖНЫ РАССМАТРИВАТЬСЯ КАК ОТДЕЛЬНЫЕ ШТРИХОВКИ!!!
                                HatchNestingTree hatchNestingTree
                                    = new HatchNestingTree(boundaries, extends, ptsCollList, ptParamsList, hatch);
                                List <HatchData> currHatchData = hatchNestingTree.GetHatchData();
                                currHatchData.AddRange(splitHatchData);//добавить контуры, полученные из взаимно пересекающихся контуров
                                //currHatchData.AddRange(decomposeHatchData);

                                allHatchData.AddRange(currHatchData);

                                //Каждая штриховка имеет диапазон по X от начала до конца по оси.
                                //В общую очередь событий сохраняются события начала и конца штриховки
                                foreach (HatchData hd in currHatchData)
                                {
                                    hd.AddEventsToQueue(eventQueue);
                                }
                            }



                            //Трассу разбить на отрезки, на которых будут вставлены прямолинейные сегменты штриховок
                            Polyline alignmentPoly = null;
                            try
                            {
                                alignmentPoly = (Polyline)tr.GetObject(AlignmentPolyId, OpenMode.ForRead);
                            }
                            catch (Autodesk.AutoCAD.Runtime.Exception)
                            {
                                return;
                            }
                            int segments = alignmentPoly.NumberOfVertices - 1;
                            List <AlignmentSegment>   alignmentSegments   = new List <AlignmentSegment>();
                            Action <Point2d, Point2d> addAlignmentSegment = new Action <Point2d, Point2d>((p0, p1) =>
                            {
                                double start = alignmentPoly.GetDistAtPoint(new Point3d(p0.X, p0.Y, 0));
                                double end   = alignmentPoly.GetDistAtPoint(new Point3d(p1.X, p1.Y, 0));
                                if (Math.Abs(start - end) > Tolerance.Global.EqualPoint)//TODO: Это спорный момент - ведь может быть большое множество очень коротких участков подряд!
                                {
                                    Vector2d startDir = p1 - p0;
                                    alignmentSegments.Add(new AlignmentSegment(start, end, p0, startDir));
                                }
                            });
                            for (int i = 0; i < segments; i++)
                            {
                                SegmentType segmentType = alignmentPoly.GetSegmentType(i);
                                Point2d     startLoc    = alignmentPoly.GetPoint2dAt(i);
                                Point2d     endLoc      = alignmentPoly.GetPoint2dAt(i + 1);
                                switch (segmentType)
                                {
                                case SegmentType.Line:
                                    addAlignmentSegment(startLoc, endLoc);
                                    break;

                                case SegmentType.Arc:
                                    CircularArc2d    arc       = new CircularArc2d(startLoc, endLoc, alignmentPoly.GetBulgeAt(i), false);
                                    Interval         interval  = arc.GetInterval();
                                    PointOnCurve2d[] samplePts = arc.GetSamplePoints(interval.LowerBound, interval.UpperBound, 0.1);
                                    for (int n = 0; n < samplePts.Length - 1; n++)
                                    {
                                        addAlignmentSegment(samplePts[n].Point, samplePts[n + 1].Point);
                                    }
                                    break;
                                }
                            }


                            //проход по каждому отрезку трассы (диапазон отрезка - диапазон длины полилинии)
                            HashSet <HatchData> currentHatchData = new HashSet <HatchData>();
                            foreach (AlignmentSegment alignmentSegment in alignmentSegments)
                            {
                                if (eventQueue.Count == 0)
                                {
                                    break;                       //штриховки закончились
                                }
                                //Получить те штриховки, диапазон по X которых пересекается с диапазоном текущего отрезка
                                //(СКАНИРУЮЩАЯ ЛИНИЯ: события - начало, конец штриховки)
                                HashSet <HatchData> intervalHatchData = new HashSet <HatchData>(currentHatchData);//штриховки пришедшие из предыдущего участка остаются все

                                //Собрать все события до конца сегмента
                                //Если при проходе от начала до конца сегмента какая-то штриховка проходится полностью от начала до конца, то
                                //все ее контуры без изменений должны быть переданы для создания М-полигона!!! (для них обход графа не нужен!)
                                HashSet <HatchData> startedInsideInterval           = new HashSet <HatchData>();
                                List <HatchData>    hatchesCompletelyInsideInterval = new List <HatchData>();
                                while (eventQueue.Count > 0)
                                {
                                    HatchEvent nextEvent = eventQueue.FindMin();
                                    if (nextEvent.Position > alignmentSegment.End)
                                    {
                                        break;
                                    }
                                    else if (nextEvent.Start)
                                    {
                                        //добавить штриховку в текущий набор
                                        HatchData hd = eventQueue.DeleteMin().HatchData;
                                        currentHatchData.Add(hd);
                                        //добавлять в набор текущего интервла только в том случае,
                                        //если сканирующая линия еще не дошла до конца интервала
                                        if (nextEvent.Position < alignmentSegment.End &&
                                            !Utils.LengthIsEquals(nextEvent.Position, alignmentSegment.End))   //Допуск нужен
                                        {
                                            startedInsideInterval.Add(hd);
                                            intervalHatchData.Add(hd);
                                        }
                                    }
                                    else
                                    {
                                        //убрать штриховку из текущего набора
                                        HatchData hd = eventQueue.DeleteMin().HatchData;
                                        currentHatchData.Remove(hd);

                                        if (startedInsideInterval.Contains(hd))
                                        {
                                            hatchesCompletelyInsideInterval.Add(hd);
                                        }
                                    }
                                }

                                foreach (HatchData hd in hatchesCompletelyInsideInterval)
                                {
                                    HatchSegmentData hsd = new HatchSegmentData(hd);
                                    alignmentSegment.HatchSegmentData.Add(hsd);

                                    hsd.Polygons = hd.GetAllBoundaries();
                                }


                                intervalHatchData.ExceptWith(hatchesCompletelyInsideInterval);
                                foreach (HatchData hd in intervalHatchData)
                                {
                                    HatchSegmentData hsd = new HatchSegmentData(hd);
                                    alignmentSegment.HatchSegmentData.Add(hsd);
                                    //для каждой штриховки выполнить построение и обход графа сегмента штриховки
                                    HatchSegmentGraph graph = new HatchSegmentGraph(alignmentSegment.Start, alignmentSegment.End, hd, doc.Editor);

                                    //сохранить наборы полигонов для текущего диапазона
                                    hsd.Polygons = graph.Result;
                                }
                            }



                            //для каждого диапазона создать полученные полигоны в 3d
                            BlockTable       bt = tr.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable;
                            BlockTableRecord ms
                                = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

                            BlockTableRecord btr = new BlockTableRecord();//Каждый профиль в отдельный блок
                            btr.Name = Guid.NewGuid().ToString();
                            ObjectId btrId = bt.Add(btr);
                            tr.AddNewlyCreatedDBObject(btr, true);

                            foreach (AlignmentSegment alignmentSegment in alignmentSegments)
                            {
                                List <Entity> flatObjs = new List <Entity>();

                                foreach (HatchSegmentData hsd in alignmentSegment.HatchSegmentData)
                                {
                                    //PlaneSurface
                                    hsd.GetNesting();
                                    Dictionary <Point2dCollection, List <Point2dCollection> > bwhs = hsd.GetBoundariesWithHoles();
                                    foreach (KeyValuePair <Point2dCollection, List <Point2dCollection> > bwh in bwhs)
                                    {
                                        //создать Region
                                        Region region = null;
                                        using (Polyline poly = new Polyline())
                                        {
                                            for (int i = 0; i < bwh.Key.Count; i++)
                                            {
                                                poly.AddVertexAt(i, bwh.Key[i], 0, 0, 0);
                                            }
                                            poly.Closed = true;
                                            DBObjectCollection coll = new DBObjectCollection();
                                            coll.Add(poly);
                                            try
                                            {
                                                DBObjectCollection regionColl = Region.CreateFromCurves(coll);
                                                foreach (DBObject dbo in regionColl)
                                                {
                                                    region = (Region)dbo;
                                                    break;
                                                }
                                            }
                                            catch { }
                                        }

                                        //из Region создать PlaneSurface
                                        if (region != null)
                                        {
                                            using (PlaneSurface planeSurface = new PlaneSurface())
                                            {
                                                planeSurface.CreateFromRegion(region);
                                                planeSurface.LayerId    = hsd.Hatch.LayerId;
                                                planeSurface.ColorIndex = 256;



                                                ObjectId planeSurfaceId = ms.AppendEntity(planeSurface);
                                                tr.AddNewlyCreatedDBObject(planeSurface, true);


                                                //вырезать отверстия в PlaneSurface

                                                foreach (Point2dCollection holePts2d in bwh.Value)
                                                {
                                                    if (holePts2d.Count < 3)
                                                    {
                                                        continue;
                                                    }

                                                    using (Polyline poly = new Polyline())
                                                    {
                                                        for (int i = 0; i < holePts2d.Count; i++)
                                                        {
                                                            poly.AddVertexAt(i, holePts2d[i], 0, 0, 0);
                                                        }
                                                        poly.Closed = true;

                                                        ObjectIdCollection trimPolyColl = new ObjectIdCollection();
                                                        trimPolyColl.Add(ms.AppendEntity(poly));
                                                        tr.AddNewlyCreatedDBObject(poly, true);

                                                        List <Point2d> ptsList  = new List <Point2d>(holePts2d.ToArray());
                                                        Point2d        pickPt2d = Utils.GetAnyPointInsidePoligon(ptsList,
                                                                                                                 Utils.DirectionIsClockwise(ptsList));

                                                        try
                                                        {
                                                            AcadDB.Surface.TrimSurface(planeSurfaceId, new ObjectIdCollection(), trimPolyColl,
                                                                                       new Vector3dCollection()
                                                            {
                                                                Vector3d.ZAxis
                                                            }, new Point3d(pickPt2d.X, pickPt2d.Y, 0),
                                                                                       -Vector3d.ZAxis, false, false);
                                                        }
                                                        catch /*(Exception ex)*/
                                                        {
                                                            //Вывод в командную строку
                                                            Utils.ErrorToCommandLine(doc.Editor,
                                                                                     "Ошибка при попытке вырезания отверстия в поверхности" /*, ex*/);
                                                        }

                                                        //Удалить все объекты, добавленные в чертеж!
                                                        poly.Erase();
                                                    }
                                                }


                                                flatObjs.Add((Entity)planeSurface.Clone());

                                                //Удалить все объекты, добавленные в чертеж!
                                                planeSurface.Erase();
                                            }
                                            region.Dispose();
                                        }
                                    }
                                }



                                foreach (Entity ent in flatObjs)
                                {
                                    ent.TransformBy(alignmentSegment.Transform);
                                    /*ms*/
                                    btr.AppendEntity(ent);
                                    tr.AddNewlyCreatedDBObject(ent, true);
                                    ent.Dispose();
                                }
                            }

                            BlockReference br = new BlockReference(Point3d.Origin, btrId);
                            ms.AppendEntity(br);
                            tr.AddNewlyCreatedDBObject(br, true);


                            if (selfintersectingLoops.Count > 0)
                            {
                                Utils.ErrorToCommandLine(doc.Editor,
                                                         "Отбраковано самопересекающихся контуров штриховок - " + selfintersectingLoops.Count + " (отмечены на профиле)");

                                ObjectId layerId = Utils.CreateLayerIfNotExists("САМОПЕРЕСЕКАЮЩИЙСЯ КОНТУР ШТРИХОВКИ", db, tr,
                                                                                color: Color.FromColorIndex(ColorMethod.ByAci, 1), lineWeight: LineWeight.LineWeight200);
                                Matrix2d returnTransform = transform.Inverse();
                                foreach (Point2dCollection pts in selfintersectingLoops)
                                {
                                    using (Polyline selfIntersectingPoly = new Polyline())
                                    {
                                        selfIntersectingPoly.LayerId    = layerId;
                                        selfIntersectingPoly.ColorIndex = 256;
                                        for (int i = 0; i < pts.Count; i++)
                                        {
                                            Point2d pt = pts[i].TransformBy(returnTransform);
                                            selfIntersectingPoly.AddVertexAt(i, pt, 0, 0, 0);
                                        }

                                        toHighlight.Add(ms.AppendEntity(selfIntersectingPoly));
                                        tr.AddNewlyCreatedDBObject(selfIntersectingPoly, true);

                                        //selfIntersectingPoly.Highlight();
                                    }
                                }
                            }


                            tr.Commit();
                        }
                    }
                    ps.Visible = false;

                    if (toHighlight.Count > 0)
                    {
                        using (Transaction tr = doc.Database.TransactionManager.StartTransaction())
                        {
                            foreach (ObjectId id in toHighlight)
                            {
                                Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead);
                                ent.Highlight();
                            }
                            tr.Commit();
                        }
                    }
                }
            }
            catch (System.Exception ex)
            {
                GeologyConvertationCommand.ClosePalette(null, null);
                CommonException(ex, "Ошибка при создании 3d профиля геологии");
            }
        }
Exemple #16
0
        /// <summary>
        /// 计算一段填方区间(填方段的两个边界交点之间的区间)的挖台阶量
        /// </summary>
        /// <param name="startStation"></param>
        /// <param name="endStation"></param>
        private List <LongitudinalStairExcav> CalculateFillRange(double startStation, double endStation)
        {
            if (endStation - startStation < _criterion.最小区间宽度)
            {
                return(null);
            }

            // 求分段交点(集合中至少有两个值)
            var xy = new List <double[]>();

            for (double x = startStation; x < endStation; x += _criterion.台阶宽度)
            {
                var intersVerticalGround = new CurveCurveIntersector2d(_longitudinalSection.GroundCurve2d,
                                                                       new Line2d(new Point2d(x, 0), new Vector2d(0, 1)));
                xy.Add(new double[] { x, intersVerticalGround.GetIntersectionPoint(0).Y });
            }

            var stairsInFillZone = new List <LongitudinalStairExcav>();

            // 计算此区间内所有坡度较陡的台阶
            for (int i = 0; i < xy.Count - 1; i++)
            {
                var ratio = Math.Abs((xy[i + 1][1] - xy[i][1]) / ((xy[i + 1][0] - xy[i][0])));
                if (ratio > _criterion.临界纵坡)
                {
                    // 挖台阶的三角形面积
                    var area = Math.Abs((xy[i + 1][0] - xy[i][0]) * (xy[i + 1][1] - xy[i][1])) / 2;
                    stairsInFillZone.Add(new LongitudinalStairExcav(xy[i][0], xy[i + 1][0], stairArea: area));
                }
            }

            // 这里为了避免区间太密,作出一个强制处理:对同一个填方桩号区间内的所有满足条件的台阶区间进行合并,保证合并后的每一个区间的长度不小于设定的最小宽度
            // 但是处理之后,总的挖台阶面积还是此区间内有效的台阶的三角形面积之和
            int count = stairsInFillZone.Count;

            if (count == 0 ||
                stairsInFillZone[count - 1].EndStation - stairsInFillZone[0].StartStation < _criterion.最小区间宽度)
            {
                // 表示此填方区间内,所有的台阶(算上分离的)之间的距离都小于 10 m,此时认为不作挖台阶处理
                return(null);
            }
            else
            {
                var stairsInFillZone1 = new List <LongitudinalStairExcav>();
                // 将一些分离的台阶进行合并,确保其距离不小于10m;但是处理之后,总的挖台阶面积还是此区间内有效的台阶的三角形面积之和
                // 1. 将直接相连的台阶进行合并
                var lastStair = stairsInFillZone[0];
                LongitudinalStairExcav thisStair;
                stairsInFillZone1.Add(lastStair);
                for (int i = 1; i < count; i++)
                {
                    thisStair = stairsInFillZone[i];
                    if (lastStair.IsMergeable(thisStair))
                    {
                        lastStair.Merge(thisStair);
                    }
                    else
                    {
                        lastStair = thisStair;
                        stairsInFillZone1.Add(thisStair);
                    }
                }
                // 合并后,整个填方区间内,剩下相互分离的多个台阶子区间
                // 2. 对于初步合并后自身宽度不足10m,左右10m内又没有其他台阶的项,直接删除
                count = stairsInFillZone1.Count;
                if (count == 1)
                {
                    // 如果合并后只剩一段,则直接返回
                    return(stairsInFillZone1);
                }
                else
                {
                    // 从小桩号往大桩号前进式合并
                    stairsInFillZone = new List <LongitudinalStairExcav>();
                    LongitudinalStairExcav validatedStair;
                    LongitudinalStairExcav backStair  = stairsInFillZone1[0];
                    LongitudinalStairExcav frontStair = stairsInFillZone1[1];
                    // 整个填方段起码有三段分离的台阶子区间
                    for (int i = 0; i < count - 1; i++)
                    {
                        frontStair     = stairsInFillZone1[i + 1];
                        validatedStair = MergeSeperatedStair(backStair, ref frontStair);
                        if (validatedStair != null)
                        {
                            stairsInFillZone.Add(validatedStair);
                        }
                        backStair = frontStair;
                    }
                    // 最后一个子区间
                    if (frontStair.GetLength() >= _criterion.最小区间宽度)
                    {
                        stairsInFillZone.Add(frontStair);
                    }
                    return(stairsInFillZone);
                }
            }
        }
        protected override void BuildProcessing(MillingCommandGenerator generator)
        {
            var toolThickness = Tool.Thickness.Value;
            var profile       = ProcessingArea[0].GetCurve();

            if (Delta != 0)
            {
                profile = (Curve)profile.GetOffsetCurves(Delta)[0];
            }

            var zMax = profile.GetStartEndPoints().Max(p => p.Y);

            generator.SetZSafety(ZSafety, zMax);
            var xMax = 0D;

            using (var curve = profile.ToCompositeCurve2d())
                using (var ray = new Ray2d())
                    using (var intersector = new CurveCurveIntersector2d())
                    {
                        var angleC = 360;
                        var gCode  = 2;

                        for (var z = StartZ; z > 0; z -= StepZ)
                        {
                            var xMin = RadiusMin;
                            for (int i = 0; i < 3; i++)
                            {
                                ray.Set(new Point2d(0, z + i * toolThickness / 2), Vector2d.XAxis);
                                intersector.Set(curve, ray);
                                if (intersector.NumberOfIntersectionPoints == 1)
                                {
                                    xMin = Math.Max(xMin, intersector.GetIntersectionPoint(0).X);
                                }
                            }
                            if (xMin == 0)
                            {
                                throw new Exception("Нет точек пересечения с профилем");
                            }

                            var x         = Math.Max(xMin, RadiusMax - Penetration);
                            var s         = x - xMin;
                            int passCount = (int)Math.Ceiling(s / Penetration);
                            var dx        = s > Consts.Epsilon ? s / passCount : 1;

                            if (generator.IsUpperTool)
                            {
                                generator.Move(0, -x - ZSafety, angleC: 0, angleA: 90);
                            }
                            else
                            {
                                generator.Transition(y: -x - ZSafety, feed: CuttingFeed);
                            }
                            generator.Transition(z: z);
                            do
                            {
                                var arc = new Arc(new Point3d(0, 0, z), x, Math.PI * 1.5, Math.PI * 1.5 - Consts.Epsilon);
                                generator.Cutting(0, -x, z, PenetrationFeed);
                                generator.GCommand(CommandNames.Cutting, gCode, angleC: angleC, curve: arc, center: arc.Center.To2d(), feed: CuttingFeed);
                                angleC = 360 - angleC;
                                gCode  = 5 - gCode;
                                x     -= dx;
                            }while (x >= xMin - Consts.Epsilon);

                            xMax = Math.Max(xMin, RadiusMax);
                        }
                        generator.Transition(y: -xMax - ZSafety, feed: PenetrationFeed);
                        generator.Uplifting();
                    }
        }