/// <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); }
private void GetIntersects() { IntersPoints = new Dictionary <double, Point2d>(); for (int i = 0; i < Intersects.NumberOfIntersectionPoints; i++) { var pt = Intersects.GetIntersectionPoint(i); IntersPoints.Add(pt.X, pt); } }
/// <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); }
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); }
/// <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); }
/// <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); }
/// <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); // }
/// <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); }
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="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(); } }
/// <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); } } }