private int Fillet(Polyline pline, double radius, int index1, int index2) { if (pline.GetSegmentType(index1) != SegmentType.Line || pline.GetSegmentType(index2) != SegmentType.Line) { return(0); } LineSegment2d seg1 = pline.GetLineSegment2dAt(index1); LineSegment2d seg2 = pline.GetLineSegment2dAt(index2); Vector2d vec1 = seg1.StartPoint - seg1.EndPoint; Vector2d vec2 = seg2.EndPoint - seg2.StartPoint; double angle = vec1.GetAngleTo(vec2) / 2.0; double dist = radius / Math.Tan(angle); if (dist > seg1.Length || dist > seg2.Length) { return(0); } Point2d pt1 = seg1.EndPoint.TransformBy(Matrix2d.Displacement(vec1.GetNormal() * dist)); Point2d pt2 = seg2.StartPoint.TransformBy(Matrix2d.Displacement(vec2.GetNormal() * dist)); double bulge = Math.Tan((Math.PI / 2.0 - angle) / 2.0); if (Clockwise(seg1.StartPoint, seg1.EndPoint, seg2.EndPoint)) { bulge = -bulge; } pline.AddVertexAt(index2, pt1, bulge, 0.0, 0.0); pline.SetPointAt(index2 + 1, pt2); return(1); }
/// <summary> /// Перенос группы домов в точку 0,0 (в 4 четверть) /// </summary> private void MoveToZero(List <HouseTransform> houses) { // Граница группы var extGroup = GetExtents(houses); // вектор переноса (левый верхний угол границы в 0,0) var vecMove = Point2d.Origin - new Point2d(extGroup.MinPoint.X, extGroup.MaxPoint.Y); var matMove = Matrix2d.Displacement(vecMove); foreach (var house in houses) { house.Trans(matMove); } }
private const double ARROW_FULL_LENGTH = 2; // Hack to move position based on a known length public static void GenerateBlock(Database database, LevelBlockDetails x, LevelBlockDetails y) { if (!x.IsValid || !y.IsValid) { return; } if (x.Level.Equals(y.Level)) { HousingExtensionApplication.Current.Logger.Entry(Resources.Message_Levels_Are_Equal); return; } Point2d startPoint; Point2d endPoint; double startLevel; double endLevel; //Always point downhill if (x.Level > y.Level) { startPoint = x.Point2d; startLevel = x.Level; endPoint = y.Point2d; endLevel = y.Level; } else { startPoint = y.Point2d; startLevel = y.Level; endPoint = x.Point2d; endLevel = x.Level; } var vector = endPoint.GetAsVector() - startPoint.GetAsVector(); var gradient = 1 / ((startLevel - endLevel) / vector.Length); var midPoint = startPoint + vector * 0.5; // Hack to move position based on a known length var shiftVector = vector.GetNormal() * ARROW_FULL_LENGTH; var matrix = Matrix2d.Displacement(shiftVector); midPoint.TransformBy(matrix); var rotation = vector.Angle; NewGradientBlockAtPoint(database, new Point3d(midPoint.X, midPoint.Y, 0), gradient, rotation); HousingExtensionApplication.Current.Logger.Entry(string.Format(Resources.Command_Output_GradientLineLength, Math.Round(vector.Length, 3))); }
public static Point2d MoveDistance(this Point2d theP2d, Vector2d theVec, double dist) { Vector2d newVec = new Vector2d(dist * Math.Cos(theVec.Angle), dist * Math.Sin(theVec.Angle)); return(theP2d.TransformBy(Matrix2d.Displacement(newVec))); }
public void DragIt() { IsDrag = false; PromptEntityOptions entOpts = new PromptEntityOptions("请选择Polyline"); entOpts.SetRejectMessage("请选择多段线"); entOpts.AddAllowedClass(typeof(Polyline), true); var pEntRes = ed.GetEntity(entOpts); if (pEntRes.Status != PromptStatus.OK) { return; } Polyline plCo = null; using (var trans = db.TransactionManager.StartTransaction()) { pl = trans.GetObject(pEntRes.ObjectId, OpenMode.ForWrite) as Polyline; //这里如果不复制,直接操作pl,虽然是以写的方式打开的实体,但是会报错说NotOpenForWrite plCo = pl.Clone() as Polyline; pl.Erase(); trans.Commit(); } List <LineSegment2d> listL2d = new List <LineSegment2d>(); for (int i = 0; i < pl.NumberOfVertices - 1; i++) { listL2d.Add(pl.GetLineSegment2dAt(i)); } var pointRes = ed.GetPoint(new PromptPointOptions("请输入一地个点:\n")); if (pointRes.Status != PromptStatus.OK) { return; } Vector2d v2d = new Vector2d(0, 0); JigPromptPointOptions jigOpts = new JigPromptPointOptions(); MyJig myJig = new MyJig(); myJig.PromptInput(jigOpts, "拖动鼠标"); myJig.JigEnts.Add(plCo); int dir = -1; myJig.SetJigUpdate((jig) => { if (jig.JigEnts == null || jig.JigEnts.Count == 0) { return; } Polyline p = jig.JigEnts[0] as Polyline; var pt1 = pointRes.Value; var pt2 = jig.Point; var vec = pt2 - pt1; /*获取鼠标拖动方向,主要思路 * 当拖动的距离拖动前按下的那个点的 * 距离>1的时候,计算是X轴方向还是Y轴方向 * 因为第一次判断,如果距离过下方向不准确。 * 并且这个方向一确定,就不在更改。 */ if (!IsDrag) { if (vec.Length > 1) { IsDrag = true; if (Math.Abs(vec.X) > Math.Abs(vec.Y)) { dir = 0; } else { dir = 1; } } } //向右或者向左 if (dir == 0) { v2d = new Vector2d(vec.X, 0); } else//向上或者向下 { v2d = new Vector2d(0, vec.Y); } /* * 确定要拖动的边是选择距离鼠标按下的那个点最近的边 */ double minLength = double.MaxValue; int index = -1; foreach (var i in Enumerable.Range(0, listL2d.Count)) { var l = listL2d[i]; double dis = l.GetDistanceTo(new Point2d(pointRes.Value.X, pointRes.Value.Y)); if (dis < minLength) { minLength = dis; index = i; } } var l2d = listL2d[index]; Matrix2d mtx2d = Matrix2d.Displacement(v2d); var ptGet1 = l2d.StartPoint; var ptGet2 = l2d.EndPoint; //实时得到变化的点 var ptStart = ptGet1.TransformBy(mtx2d); var ptEnd = ptGet2.TransformBy(mtx2d); var vecGet = ptGet2 - ptGet1; //判断鼠标移动的方向和被拖动的边是否是在大致的同一方向 //如果不是,就允许拖动 if (dir == 0 && (Math.Abs(vecGet.X) < Math.Abs(vecGet.Y)) || dir == 1 && (Math.Abs(vecGet.X) > Math.Abs(vecGet.Y))) { p.SetPointAt(index, ptStart); p.SetPointAt(index + 1, ptEnd); //如果polyline是封闭的,要判断被拖动的点是否是闭合位置上的点, //如果是,要一致更改起点和封闭点 if (p.Closed) { if (index == 0) { p.SetPointAt(p.NumberOfVertices - 1, ptStart); } if (index + 1 == 0) { p.SetPointAt(p.NumberOfVertices - 1, ptEnd); } if (index == p.NumberOfVertices - 1) { p.SetPointAt(0, ptStart); } if (index + 1 == p.NumberOfVertices - 1) { p.SetPointAt(0, ptEnd); } } } }); if (myJig.Drag() != PromptStatus.OK) { return; } IsDrag = false; //加入到模型空间 myJig.JigEnts.ToSpace(); myJig.JigEnts.ForEach(a => a.Dispose()); }
private void CreateProfile(object arg) { try { if (doc != null) { using (doc.LockDocument()) { Editor ed = doc.Editor; Database db = doc.Database; using (Transaction tr = db.TransactionManager.StartTransaction()) { //выбрать базовую точку снизу слева double minx = double.PositiveInfinity; double miny = double.PositiveInfinity; List <ObjectId> allSelected = new List <ObjectId>(soilHatchIds); allSelected.Add(groundSurfPolyId); 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; } if (miny > minPt.Y) { miny = minPt.Y; } } } Point2d basePt = new Point2d(minx, miny); //для трансформации координат //Vector2d baseVector = new Vector2d(minx, miny); Matrix2d transform = new Matrix2d(new double[] { StartHorScaling, 0, 0, 0, StartVertScaling, 0, 0, 0, 1 }) * Matrix2d.Displacement(new Vector2d(-minx, -miny)); //полилиния поверхности земли //???????координаты точек полилинии расчитываются относительно базовой точки (и пересчитываются в метры согласно введенным коэффициентам?) //отсортировать список сточек по координате X. //ПОИСК ПО ДИАПАЗОНУ: //Использовать бинарный поиск (https://www.baeldung.com/java-binary-search) для нахождения хотябы одной точки в заданном диапазоне //затем проверять соседние точки на нахождение в диапазоне Polyline poly = null; try { poly = (Polyline)tr.GetObject(groundSurfPolyId, OpenMode.ForRead); } catch (Autodesk.AutoCAD.Runtime.Exception) { return; } ObjectId groundSurfLayerId = poly.LayerId; List <Point2d> polyPts = new List <Point2d>(); for (int i = 0; i < poly.NumberOfVertices; i++) { Point2d pt = poly.GetPoint2dAt(i); pt = transform * pt; //pt = pt - baseVector; //pt = new Point2d(pt.X * StartHorScaling, pt.Y * StartVertScaling); polyPts.Add(pt); } polyPts.Sort((a, b) => { return(a.X.CompareTo(b.X)); }); double depthMultipier = StartVertSoilScaling / StartVertScaling; //для каждой штриховки получить все контуры //любые контуры должны быть переведены в полигоны без кривизны //???????координаты точек полигонов расчитываются относительно базовой точки (и пересчитываются в метры согласно введенным коэффициентам?) //для каждой точки полигона должно быть расчитано заглубление относительно поверхности земли //если между двумя точками полигона по гоизонтали есть точки перелома поверхности земли, //то для этих точек должны быть добавлены соответствующие точки полигона List <HatchData> hatchData = new List <HatchData>(); foreach (ObjectId id in soilHatchIds) { Hatch hatch = null; try { hatch = (Hatch)tr.GetObject(id, OpenMode.ForRead); } catch (Autodesk.AutoCAD.Runtime.Exception) { continue; } HatchData hd = new HatchData(hatch); hatchData.Add(hd); 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 <Point2d> polygon = new List <Point2d>(); hd.Polygons.Add(polygon); List <Curve2d> curves = Utils.GetHatchLoopCurves(hl); foreach (Curve2d c in curves) { if (!(c is LineSegment2d)) { Interval interval = c.GetInterval(); PointOnCurve2d[] samplePts = c.GetSamplePoints(interval.LowerBound, interval.UpperBound, 0.02); for (int n = 0; n < samplePts.Length - 1; n++) { ProcessLineSegmentOfHatch(samplePts[n].Point, samplePts[n + 1].Point, polygon, polyPts, transform, /*baseVector, StartHorScaling, StartVertScaling,*/ depthMultipier); } } else { ProcessLineSegmentOfHatch(c.StartPoint, c.EndPoint, polygon, polyPts, transform, /*baseVector, StartHorScaling, StartVertScaling,*/ depthMultipier); } } } } } //указание пользователем точки вставки нового профиля //создание полилиний //координаты точек пересчитываются заданным масштабным коэффициентам // PromptPointOptions pPtOpts = new PromptPointOptions("\nУкажите точку вставки"); PromptPointResult pPtRes = doc.Editor.GetPoint(pPtOpts); if (pPtRes.Status == PromptStatus.OK) { BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable; BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); DrawOrderTable drawOrder = tr.GetObject(ms.DrawOrderTableId, OpenMode.ForWrite) as DrawOrderTable; ObjectId continLtId = Utils.GetContinuousLinetype(db); Point2d insertPt = Utils.Point2DBy3D(pPtRes.Value); //Vector2d insertVec = new Vector2d(insertPt.X, insertPt.Y); Matrix2d insertTransform = Matrix2d.Displacement(new Vector2d(insertPt.X, insertPt.Y)) * new Matrix2d(new double[] { 1 / EndHorScaling, 0, 0, 0, 1 / EndVertScaling, 0, 0, 0, 1 }); //полилиния поверхности земли using (Polyline surfGroundPoly = new Polyline()) { surfGroundPoly.LayerId = groundSurfLayerId; surfGroundPoly.ColorIndex = 256; surfGroundPoly.LinetypeId = continLtId; for (int i = 0; i < polyPts.Count; i++) { Point2d pt = polyPts[i]; //Point2d convertedPt = new Point2d(pt.X / EndHorScaling, pt.Y / EndVertScaling); //convertedPt = convertedPt + insertVec; Point2d convertedPt = insertTransform * pt; surfGroundPoly.AddVertexAt(i, convertedPt, 0, 0, 0); } ms.AppendEntity(surfGroundPoly); tr.AddNewlyCreatedDBObject(surfGroundPoly, true); } //полилинии штриховок //HashSet<ObjectId> createdLayers = new HashSet<ObjectId>(); ObjectIdCollection hatchIds = new ObjectIdCollection(); foreach (HatchData hd in hatchData) { /* * double patternScale = hd.Hatch.PatternScale; * * string layerName = patternScale != 1 ? hd.Hatch.PatternName + "_" + patternScale.ToString("f2") : hd.Hatch.PatternName; * * ObjectId hatchLayerId = Utils.CreateLayerIfNotExists(layerName, db, tr, * lineWeight: LineWeight.LineWeight030); * createdLayers.Add(hatchLayerId); */ ObjectIdCollection polyIds = new ObjectIdCollection(); foreach (List <Point2d> polygon in hd.Polygons) { if (polygon.Count > 0) { using (Polyline geologPoly = new Polyline()) { geologPoly.LayerId = hd.Hatch.LayerId; //hatchLayerId; geologPoly.ColorIndex = 256; geologPoly.LinetypeId = continLtId; for (int i = 0; i < polygon.Count; i++) { Point2d pt = polygon[i]; //Point2d convertedPt = new Point2d(pt.X / EndHorScaling, pt.Y / EndVertScaling); //convertedPt = convertedPt + insertVec; Point2d convertedPt = insertTransform * pt; geologPoly.AddVertexAt(i, convertedPt, 0, 0, 0); } geologPoly.Closed = true; ObjectId id = ms.AppendEntity(geologPoly); tr.AddNewlyCreatedDBObject(geologPoly, true); if (!id.IsNull && id.IsValid) { polyIds.Add(id); } } } } if (polyIds.Count > 0) { try { using (Hatch oHatch = /*(Hatch)hd.Hatch.Clone()*/ new Hatch()) { oHatch.LayerId = hd.Hatch.LayerId; //hatchLayerId; Vector3d normal = new Vector3d(0.0, 0.0, 1.0); oHatch.Normal = normal; oHatch.Elevation = 0.0; oHatch.PatternScale = hd.Hatch.PatternScale; //oHatch.SetHatchPattern(hd.Hatch.PatternType, hd.Hatch.PatternName); oHatch.SetHatchPattern(HatchPatternType.PreDefined, "SOLID"); oHatch.ColorIndex = 256; //while (oHatch.NumberOfLoops>0) //{ // oHatch.RemoveLoopAt(0); //} ObjectId hatchId = ms.AppendEntity(oHatch); tr.AddNewlyCreatedDBObject(oHatch, true); oHatch.Associative = true; foreach (ObjectId polyId in polyIds) { oHatch.AppendLoop(HatchLoopTypes.Default, new ObjectIdCollection() { polyId }); } oHatch.EvaluateHatch(true); if (!hatchId.IsNull && hatchId.IsValid) { hatchIds.Add(hatchId); } } } catch { } } } /* * short colorIndex = 1; * foreach (ObjectId layerId in createdLayers) * { * LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(layerId, OpenMode.ForWrite); * ltr.Color = Color.FromColorIndex(ColorMethod.ByAci, colorIndex); * * colorIndex = Convert.ToByte((colorIndex + 1) % 256); * } */ drawOrder.MoveToBottom(hatchIds); //GeologyConvertationCommand.ClosePalette(null, null); ps.Visible = false; } tr.Commit(); } } } } catch (System.Exception ex) { GeologyConvertationCommand.ClosePalette(null, null); CommonException(ex, "Ошибка при переводе масштаба профиля геологии"); } }
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 профиля геологии"); } }