Статьи > Тестирование статей
AutoCAD .NET API: Рассечение штриховки.
alz:
Этот код позволяет разрезать штриховку кажущимся пересечением, образованным замкнутым контуром, то есть тем, который визуально отображается на мониторе, плоскости штриховки и контура могут не совпадать, главное что бы было визуальное их пересечение. Для создания кода использовалось достаточно много кода с этого сайта.
alz:
Ух блин, видимо какое то ограничение на длину сообщений. в предварительном просмотре все было нормально, а тут обрезало, надо делить на куски, как отредактировать не вижу :(
alz:
Первая часть кода
--- Код - C# [Выбрать] ---using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.DatabaseServices;using Autodesk.AutoCAD.EditorInput;using Autodesk.AutoCAD.Geometry;using Autodesk.AutoCAD.Runtime;using System;using System.Collections.Generic;using System.Reflection; namespace Trim_objects{ public class CurHatch { [CommandMethod("cut_hatch")] public void c_hatch() { ObjectId plId = GetObjectId(new List<string> { "acdbpolyline", "acdbcircle" }, "Выберите замкнутый секущий контур"); if (plId == ObjectId.Null ) return; ObjectId hId = GetObjectId(new List<string> { "acdbhatch" }, "Выберите разрезаемую штриховку"); if (hId == ObjectId.Null) return; CutHatch(plId, hId); } /// <summary> /// Основная команда, режет штриховку возвращает списко ObjectId полученных штриховок /// </summary> /// <param name="plId">ObjectId разрезающего контура</param> /// <param name="hId">ObjectId разрезаемой штриховки</param> public List<ObjectId> CutHatch(ObjectId plId, ObjectId hId) { List<ObjectId> result = new List<ObjectId>(); //работаем сразу в транзокции и таблице так как частенько придется что-то доставать или что-то записывать using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction()) { using (BlockTableRecord ms = tr.GetObject(HostApplicationServices.WorkingDatabase.CurrentSpaceId, OpenMode.ForWrite, false, true) as BlockTableRecord) { using (Hatch hatch = tr.GetObject(hId, OpenMode.ForWrite, false, true) as Hatch) { //получаем план штриховки Plane plane = hatch.GetPlane(); //получаем вектор текущего вида Vector3d vector = GetViewVector(); //проверяем на самопересечение и замкнутость using (Curve pl1 = tr.GetObject(plId, OpenMode.ForRead, false, true) as Curve) using (Curve pl = pl1.GetProjectedCurve(plane, vector)) using (Curve3d pl3d = pl.GetGeCurve()) using (CurveCurveIntersector3d cuin = new CurveCurveIntersector3d(pl3d, pl3d, vector)) { if (cuin.NumberOfIntersectionPoints > 0 | !pl3d.IsClosed()) { tr.Commit(); return new List<ObjectId> { ObjectId.Null }; } } //получаем лупы из штриховки List<HatchLoop> loops = new List<HatchLoop>(); for (int i = hatch.NumberOfLoops - 1; i >= 0; i--) { loops.Add(hatch.GetLoopAt(i)); } //создаем кривые в чертеже для каждого лупа и записываем их в списки List<ObjectId> LoopCurve = new List<ObjectId>(); foreach (HatchLoop loop in loops) { //получаем куски лупа LoopCurve.AddRange(GetCurveFromLoop(loop, plane, hatch)); } //список удаляемых кривых лупов List<ObjectId> erList = new List<ObjectId>(); //список добавляемых кривых в лупы List<ObjectId> addList = new List<ObjectId>(); //список секущих точек List<Point3d> sPoints = new List<Point3d>(); //разрезаем все контура в штриховке проекцией контура (которые контур рассекает) foreach (ObjectId id in LoopCurve) { //получаем кривую using (Curve cur = tr.GetObject(id, OpenMode.ForWrite, false, true) as Curve) { //получаем точки пересечения List<Point3d> points = IntersectPoints(plId, ObjectId.Null, null, cur.Clone() as Curve, plane, vector, false); //если точки есть то разрезаем кривую, добавляем куски в список и удаляем разрезанную if (points.Count > 0) { sPoints.AddRange(points); using (Point3dCollection collection = new Point3dCollection()) { foreach (Point3d point in points) collection.Add(point); using (DBObjectCollection objects = cur.GetSplitCurves(collection)) { foreach (Object obj in objects) { using (Curve curve = obj as Curve) { if (curve != null) { addList.Add(ms.AppendEntity(curve)); tr.AddNewlyCreatedDBObject(curve, true); } } } } } cur.Erase(); erList.Add(id); } } } //если пересечений не было значит штриховку можно не трогать if (erList.Count == 0) { DeleteObj(LoopCurve); tr.Commit(); return new List<ObjectId> { ObjectId.Null }; } //если были то обновляем список кривых в лупах foreach (ObjectId id in erList) LoopCurve.Remove(id); LoopCurve.AddRange(addList); //создаем списки распределения кривых (других по идее быть не должно) //внутри List<Curve> inner = new List<Curve>(); //снаружи List<Curve> outer = new List<Curve>(); //создаем список с кусками пересекающей кривой, которые будем добавлять в лупы List<ObjectId> kontPartLstId = new List<ObjectId>(); List<Curve> kontPartLst = new List<Curve>(); List<Curve> kontPartLstCopy = new List<Curve>(); //получаем контур в виде проекции на плоскость штриховки using (Curve pl1 = tr.GetObject(plId, OpenMode.ForRead, false, true) as Curve) using (Curve pl = pl1.GetProjectedCurve(plane, vector)) { //распределяем куски лупов по спискам foreach (ObjectId id in LoopCurve) { Curve c = tr.GetObject(id, OpenMode.ForRead, false, true) as Curve; //после всех манипуляций тут должны быть только результаты 1 - 5 //если встретится что-то другое то скорее всего произошла какая-то ошибка и просто прекращаем //если все нормально то все кривые распределятся по спискам кроме номера 3 //он просто игнорируется и никуда не идет, его заменят если что части контура int res = PartIn(pl, c, plane, vector); if (res == 0 | res == 6) { DeleteObj(LoopCurve); tr.Commit(); return new List<ObjectId> { ObjectId.Null }; } if (res == 1 | res == 4) { inner.Add(c); continue; } if (res == 2 | res == 5) { outer.Add(c); continue; } if (res == 3) continue; } //ищем куски разрезающей кривой //сортируем точки по разрезающей кривой sPoints = SortPoint(sPoints, pl); using (Point3dCollection collection = new Point3dCollection()) { foreach (Point3d point in sPoints) collection.Add(point); using (DBObjectCollection objects = pl.GetSplitCurves(collection)) { foreach (Object obj in objects) { using (Curve curve = obj as Curve) { if (curve != null) { //проверяем находится ли кусок контура внутри штриховки int res = CurveInCurves(curve, LoopCurve, plane, vector, null); //если ошибка if (res == 0) { DeleteObj(LoopCurve); DeleteObj(kontPartLstId); tr.Commit(); return new List<ObjectId> { ObjectId.Null }; } //если внутри то добавляем на модель и в список if (res == 1) { kontPartLstId.Add(ms.AppendEntity(curve)); tr.AddNewlyCreatedDBObject(curve, true); } } } } } } //получаем куски контура как кривые и создаем 2 списка для тех областей что внутри и для тех что снаружи List<ObjectId> nkontPartLstId = new List<ObjectId>(); foreach (ObjectId objectId in kontPartLstId) { Curve curve = tr.GetObject(objectId, OpenMode.ForRead, false, true) as Curve; kontPartLst.Add(curve); //добавляем копию на модель и в список Curve curveCopy = curve.Clone() as Curve; nkontPartLstId.Add(ms.AppendEntity(curveCopy)); tr.AddNewlyCreatedDBObject(curveCopy, true); kontPartLstCopy.Add(curveCopy); } //добавляем ObjectId копий в общий список для последующего удаления kontPartLstId.AddRange(nkontPartLstId); //анализируем списки и составляем из кусков новые лупы inner.AddRange(kontPartLstCopy); List<List<ObjectId>> loopsId = GetNewLoops(inner); if (loopsId != null) result.Add(NewHatch(tr, ms, loopsId, hatch)); else { DeleteObj(LoopCurve); DeleteObj(kontPartLstId); tr.Commit(); return new List<ObjectId> { ObjectId.Null }; } outer.AddRange(kontPartLst); loopsId = GetNewLoops(outer); if (loopsId != null) result.Add(NewHatch(tr, ms, loopsId, hatch)); else { DeleteObj(LoopCurve); DeleteObj(kontPartLstId); tr.Commit(); return new List<ObjectId> { ObjectId.Null }; } } hatch.Erase(); } } tr.Commit(); } return result; } /// <summary> /// создает новые лупы из списка кусков путем объединения в замкнутые контуры /// возвращает список со списками ObjectId, объекты в которых образуют замкнутый контур /// </summary> /// <param name="cur"></param> /// <returns></returns> private List<List<ObjectId>> GetNewLoops(List<Curve> cur) { List<List<ObjectId>> loopsId = new List<List<ObjectId>>(); int stop = 0; while (cur.Count > 0) { //на всякий случай выход из цикла stop++; if (stop > 2000) { return null; } //создаем список контуров лупа List<ObjectId> loop = new List<ObjectId>(); //проверяем списки и составляем лупы, пока все не очистим //берем первую кривую Curve curve = cur[0]; loop.Add(curve.Id); cur.RemoveAt(0); //если она замкнута это готовый луп //добавляем в список готовых лупов удаляем из списка обрабатываемых и переходим к следующему if (curve.Closed == true | curve.StartPoint.Equals(curve.EndPoint)) { loopsId.Add(loop); continue; } else { //получаем концы кривой Point3d k1 = curve.StartPoint; Point3d k2 = curve.EndPoint; //проходим по объектам пока не замкнем контур int stop2 = 0; while (!k1.Equals(k2)) { //на всякий случай выход из цикла stop2++; if (stop2 > 2000) { return null; } //проходим по контурам for (int i = 0; i < cur.Count; i++) { if (k1.Equals(cur[i].StartPoint)) { loop.Add(cur[i].Id); k1 = cur[i].EndPoint; cur.RemoveAt(i); if (k1.Equals(k2)) { loopsId.Add(loop); break; } continue; } if (k1.Equals(cur[i].EndPoint)) { loop.Add(cur[i].Id); k1 = cur[i].StartPoint; cur.RemoveAt(i); if (k1.Equals(k2)) { loopsId.Add(loop); break; } continue; } if (k2.Equals(cur[i].StartPoint)) { loop.Add(cur[i].Id); k2 = cur[i].EndPoint; cur.RemoveAt(i); if (k1.Equals(k2)) { loopsId.Add(loop); break; } continue; } if (k2.Equals(cur[i].EndPoint)) { loop.Add(cur[i].Id); k2 = cur[i].StartPoint; cur.RemoveAt(i); if (k1.Equals(k2)) { loopsId.Add(loop); break; } } } } } } return loopsId; } /// <summary> /// возвращает точку центра кривой /// </summary> /// <param name="ob"></param> /// <returns></returns> private Point3d GetCentr(Curve ob) { return ob.GetPointAtDist((ob.GetDistanceAtParameter(ob.StartParam) + ob.GetDistanceAtParameter(ob.EndParam)) / 2); } /// <summary> /// строит штриховку из списка лупов в виде списков ObjecrId элементов используя как шаблон другую штриховку /// возвращает ObjectId построенной штриховки если удалось /// </summary> /// <param name="tr"></param> /// <param name="ms"></param> /// <param name="loopsId"></param> /// <param name="hatch"></param> /// <returns></returns> private ObjectId NewHatch(Transaction tr, BlockTableRecord ms, List<List<ObjectId>> loopsId, Hatch hatch) { ObjectId result = ObjectId.Null; //переменная для фиксации результата bool del = false; using (Hatch h = new Hatch()) { using (Transaction tr2 = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction()) { result = ms.AppendEntity(h); tr2.AddNewlyCreatedDBObject(h, true); tr2.Commit(); } //создаем новую штриховку h.Normal = hatch.Normal; h.Origin = hatch.Origin; h.Elevation = hatch.Elevation; h.SetDatabaseDefaults(); h.VisualStyleId = hatch.VisualStyleId; h.Color = hatch.Color; //тут все сложно, что бы все масштабы корректно отобразились //после их установки надо прописать h.SetHatchPattern(HatchPatternType.PreDefined, hatch.PatternName); //но если перед их установкой не прописать h.SetHatchPattern(hatch.PatternType, hatch.PatternName); //то угол штриховки установить не получится так как видимо базовый тип не предусматривает установки угла, выдает исключение h.SetHatchPattern(hatch.PatternType, hatch.PatternName); h.PatternAngle = hatch.PatternAngle; h.PatternScale = hatch.PatternScale; h.PatternDouble = hatch.PatternDouble; h.SetHatchPattern(HatchPatternType.PreDefined, hatch.PatternName); h.Layer = hatch.Layer; h.Linetype = hatch.Linetype; h.LineWeight = hatch.LineWeight; h.LinetypeScale = hatch.LinetypeScale; h.Transparency = hatch.Transparency; //проходим по всем лупам в списке foreach (List<ObjectId> loopId in loopsId) { if (loopId.Count == 0) continue; //если ошибок не было то вставляем луп if (!del) { //создаем из списка коллекцию using (ObjectIdCollection lId = new ObjectIdCollection()) { foreach (ObjectId curId in loopId) lId.Add(curId); //пробуем добавить коллекцию в штриховку try { h.AppendLoop(HatchLoopTypes.Default, lId); } catch { //если не удалось то удаляем штриховку и возвращаем ObjectId.Null del = true; } } } //удаляем куски лупа foreach (ObjectId curId in loopId) using (Curve cur = tr.GetObject(curId, OpenMode.ForWrite, false, true) as Curve) cur.Erase(); } //если произошла какая-то ошибка то удаляем штриховку if (del) { h.Erase(); return ObjectId.Null; } } return result; } /// <summary> /// возвращает вектор текущего вида в wcs /// </summary> /// <returns></returns> private Vector3d GetViewVector() { if (System.Convert.ToInt32(Application.GetSystemVariable("WORLDUCS")) == 0) { //если установлена ucs то получаем вектор из преобразованной точки Point3d vpoint = (Point3d)Application.GetSystemVariable("VIEWDIR"); return vpoint.GetAsVector().TransformBy(Application.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem).GetNormal(); } else { Point3d vpoint = (Point3d)Application.GetSystemVariable("VIEWDIR"); return vpoint.GetAsVector().GetNormal(); } } /// <summary> /// сортирует точки находящиеся на кривой от начала кривой к концу /// </summary> /// <param name="result">список точек</param> /// <param name="curve">кривая</param> /// <returns></returns> private List<Point3d> SortPoint(List<Point3d> result, Curve curve) { if (result.Count > 1) { List<Point3d> sorted_coll = new List<Point3d>(); while (result.Count > 0) { Point3d? minPoint = null; double? min = null; for (int i = 0; i < result.Count; i++) { double dist = curve.GetDistAtPoint(result[i]); if (minPoint == null) { minPoint = result[i]; min = dist; } else { if (dist < min.Value) { minPoint = result[i]; min = dist; } } } result.Remove(minPoint.Value); sorted_coll.Add(minPoint.Value); } foreach (Point3d coll in sorted_coll) { result.Add(coll); } } return result; }
alz:
Вторая часть кода
--- Код - C# [Выбрать] ---/// <summary> /// возвращает список точек пересечения кривых на плане по вектору /// Использовались части кода от Александра Ривилиса /// </summary> /// <param name="bCurId">ObjectId секущей кривой</param> /// <param name="iCurId">ObjectId пересекаемой кривой </param> /// <param name="bCur">секущая кривая</param> /// <param name="iCur">пересекаемая кривая</param> /// <param name="iBlock">Блок если пересекаемая кривая находится в блоке</param> /// <param name="plane">план на котором ищутся пересечения</param> /// <param name="vector">направление проецирования на план</param> /// <param name="firstLast">возвращать точки пересечения на концах пересекаемой линии?</param> /// <returns>список точек пересечения на пересекаемой кривой</returns> private List<Point3d> IntersectPoints(ObjectId bCurId, ObjectId iCurId, Curve bCur, Curve iCur, Plane plane, Vector3d vector, bool firstLast) { List<Point3d> result = new List<Point3d>(); //если кривых нет то останавливаем if ((bCurId == ObjectId.Null & bCur == null) | (iCurId == ObjectId.Null & iCur == null)) return result; //если кривые заданы через ObjectId то получаем if (bCur == null | iCur == null) { using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction()) { if (bCur == null) { bCur = tr.GetObject(bCurId, OpenMode.ForRead, false, true) as Curve; } if (iCur == null) { iCur = tr.GetObject(iCurId, OpenMode.ForRead, false, true) as Curve; } tr.Commit(); } } //если вдруг что-то пошло не так и кривые мы все таки не получили то прекращаем if (bCur == null | iCur == null) return result; //получаем проекции кривых на плоскость using (Curve bCurPr = bCur.GetProjectedCurve(plane, vector)) using (Curve iCurPr = iCur.GetProjectedCurve(plane, vector)) { //проверяем что проекции имеют длину if ((bCurPr.GetDistanceAtParameter(bCurPr.StartParam) + bCurPr.GetDistanceAtParameter(bCurPr.EndParam)) == 0) return result; if ((iCurPr.GetDistanceAtParameter(iCurPr.StartParam) + iCurPr.GetDistanceAtParameter(iCurPr.EndParam)) == 0) return result; //получаем Curve3d using (Curve3d bCurPr3d = bCurPr.GetGeCurve()) using (Curve3d iCurPr3d = iCurPr.GetGeCurve()) { //получаем точки пересечения кривых using (CurveCurveIntersector3d cInt = new CurveCurveIntersector3d(bCurPr3d, iCurPr3d, vector)) { //если пересечения есть if (cInt.NumberOfIntersectionPoints > 0) { //получаем непроецированную кривую как Curve3d using (Curve3d iCur3d = iCur.GetGeCurve()) { //проходим по пересечениям for (int i = 0; i < cInt.NumberOfIntersectionPoints; i++) { //если касание пропускаем if (cInt.IsTangential(i)) continue; //получаем точку пересечения Point3d point = cInt.GetIntersectionPoint(i); //если это точка начала или конца и она не нужна то пропускаем if (!firstLast) { if ((i == 0 | i == (cInt.NumberOfIntersectionPoints - 1)) & (point.Equals(iCurPr3d.StartPoint) | point.Equals(iCurPr3d.EndPoint))) continue; } //строим линию из этой точки и ищем реальную точку на непроецированной кривой using (Line3d line = new Line3d(point, vector)) { //получаем точки пересечения линии и непроецированной кривой using (CurveCurveIntersector3d cits = new CurveCurveIntersector3d(iCur3d, line, vector)) { if (cits.NumberOfIntersectionPoints > 0) { for (int j = 0; j < cits.NumberOfIntersectionPoints; j++) { //если этой точки нет в списке то добавляем в список if (!result.Contains(cits.GetIntersectionPoint(j))) result.Add(cits.GetIntersectionPoint(j)); } } } } } } } } } } //возвращаем отсортированные точки return SortPoint(result, iCur); } /// <summary> /// Возвращает ObjectId кривых в лупе отрисованных в текущем пространстве /// (немного доработанная функция от Александра Ривилиса) /// </summary> /// <param name="loop"></param> /// <param name="plane"></param> /// <param name="iBlock"></param> /// <returns></returns> private List<ObjectId> GetCurveFromLoop(HatchLoop loop, Plane plane, Hatch hatch) { List<ObjectId> result = new List<ObjectId>(); using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction()) { using (BlockTableRecord ms = tr.GetObject(HostApplicationServices.WorkingDatabase.CurrentSpaceId, OpenMode.ForWrite, false, true) as BlockTableRecord) { if (loop.IsPolyline) { using (Polyline poly = new Polyline()) { int iVertex = 0; foreach (BulgeVertex bv in loop.Polyline) { poly.AddVertexAt(iVertex++, bv.Vertex, bv.Bulge, 0.0, 0.0); } poly.Normal = hatch.Normal; poly.Elevation = hatch.Elevation; result.Add(ms.AppendEntity(poly)); tr.AddNewlyCreatedDBObject(poly, true); } } else { foreach (Curve2d cv in loop.Curves) { LineSegment2d line2d = cv as LineSegment2d; CircularArc2d arc2d = cv as CircularArc2d; EllipticalArc2d ellipse2d = cv as EllipticalArc2d; NurbCurve2d spline2d = cv as NurbCurve2d; if (line2d != null) { using (Line ent = new Line()) { ent.StartPoint = new Point3d(plane, line2d.StartPoint); ent.EndPoint = new Point3d(plane, line2d.EndPoint); result.Add(ms.AppendEntity(ent)); tr.AddNewlyCreatedDBObject(ent, true); } } else if (arc2d != null) { if (arc2d.IsClosed() || Math.Abs(arc2d.EndAngle - arc2d.StartAngle) < 1e-5) { using (Circle ent = new Circle(new Point3d(plane, arc2d.Center), plane.Normal, arc2d.Radius)) { result.Add(ms.AppendEntity(ent)); tr.AddNewlyCreatedDBObject(ent, true); } } else { if (arc2d.IsClockWise) { arc2d = arc2d.GetReverseParameterCurve() as CircularArc2d; } double angle = new Vector3d(plane, arc2d.ReferenceVector).AngleOnPlane(plane); double startAngle = arc2d.StartAngle + angle; double endAngle = arc2d.EndAngle + angle; using (Arc ent = new Arc(new Point3d(plane, arc2d.Center), plane.Normal, arc2d.Radius, startAngle, endAngle)) { result.Add(ms.AppendEntity(ent)); tr.AddNewlyCreatedDBObject(ent, true); } } } else if (ellipse2d != null) { //------------------------------------------------------------------------------------------- // Bug: Can not assign StartParam and EndParam of Ellipse: // Ellipse ent = new Ellipse(new Point3d(plane, e2d.Center), plane.Normal, // new Vector3d(plane,e2d.MajorAxis) * e2d.MajorRadius, // e2d.MinorRadius / e2d.MajorRadius, e2d.StartAngle, e2d.EndAngle); // ent.StartParam = e2d.StartAngle; // ent.EndParam = e2d.EndAngle; // error CS0200: Property or indexer 'Autodesk.AutoCAD.DatabaseServices.Curve.StartParam' cannot be assigned to -- it is read only // error CS0200: Property or indexer 'Autodesk.AutoCAD.DatabaseServices.Curve.EndParam' cannot be assigned to -- it is read only //--------------------------------------------------------------------------------------------- // Workaround is using Reflection // using (Ellipse ent = new Ellipse(new Point3d(plane, ellipse2d.Center), plane.Normal, new Vector3d(plane, ellipse2d.MajorAxis) * ellipse2d.MajorRadius, ellipse2d.MinorRadius / ellipse2d.MajorRadius, ellipse2d.StartAngle, ellipse2d.EndAngle)) { ent.GetType().InvokeMember("StartParam", BindingFlags.SetProperty, null, ent, new object[] { ellipse2d.StartAngle }); ent.GetType().InvokeMember("EndParam", BindingFlags.SetProperty, null, ent, new object[] { ellipse2d.EndAngle }); result.Add(ms.AppendEntity(ent)); tr.AddNewlyCreatedDBObject(ent, true); } } else if (spline2d != null) { if (spline2d.HasFitData) { NurbCurve2dFitData n2fd = spline2d.FitData; using (Point3dCollection p3ds = new Point3dCollection()) { foreach (Point2d p in n2fd.FitPoints) p3ds.Add(new Point3d(plane, p)); using (Spline ent = new Spline(p3ds, new Vector3d(plane, n2fd.StartTangent), new Vector3d(plane, n2fd.EndTangent), /* n2fd.KnotParam, */ n2fd.Degree, n2fd.FitTolerance.EqualPoint)) { result.Add(ms.AppendEntity(ent)); tr.AddNewlyCreatedDBObject(ent, true); } } } else { NurbCurve2dData n2fd = spline2d.DefinitionData; using (Point3dCollection p3ds = new Point3dCollection()) { DoubleCollection knots = new DoubleCollection(n2fd.Knots.Count); foreach (Point2d p in n2fd.ControlPoints) p3ds.Add(new Point3d(plane, p)); foreach (double k in n2fd.Knots) knots.Add(k); double period = 0; using (Spline ent = new Spline(n2fd.Degree, n2fd.Rational, spline2d.IsClosed(), spline2d.IsPeriodic(out period), p3ds, knots, n2fd.Weights, n2fd.Knots.Tolerance, n2fd.Knots.Tolerance)) { result.Add(ms.AppendEntity(ent)); tr.AddNewlyCreatedDBObject(ent, true); } } } } } } } tr.Commit(); } return result; } /// <summary> /// выбор объекта на чертеже и возврат его ObjectId /// </summary> /// <param name="objTypes">список с типами допущенных для выбора объектов, пустой лист любого объекта</param> /// <param name="soob">Выводимое сообщение при выборе</param> /// <returns></returns> private ObjectId GetObjectId(List<string> objTypes, string soob) { //повторяем пока не выбран нужный объект while (true) { //Выбираем объект на чертеже PromptEntityResult entRes = Application.DocumentManager.MdiActiveDocument.Editor.GetEntity("\n" + soob); //Если объект не выбран то прекращаем программу if (entRes.Status == PromptStatus.Cancel) { return ObjectId.Null; } //проверка на тип объекта если выбранный объект корректен то выходим из цикла выбора if (objTypes.Count == 0) return entRes.ObjectId; foreach (string objType in objTypes) if (entRes.ObjectId.ObjectClass.Name.ToLower().Equals(objType.ToLower())) return entRes.ObjectId; } } /// <summary> /// используется что бы определить положение объекта относительно других кривых /// даст точный результат если объекты из списка образуют замкнутый контур /// </summary> /// <param name="cur">элемент который проверяется (кривая или точка)</param> /// <param name="curvesId">список ObjectId кривых</param> /// <param name="plane"></param> /// <param name="vector"></param> /// <param name="kontur">кривая если нужно передать уже открытую</param> /// <returns> /// 0 - ошибка исходных данных /// 1 - внутри кривых /// 2 - снаружи кривых /// </returns> private int CurveInCurves(Object cur, List<ObjectId> curvesId, Plane plane, Vector3d vector, Curve kontur) { if ((curvesId.Count == 0 & kontur == null) | cur == null ) return 0; //счетчик общего числа пересечений //создаем список точек что бы не задваивать пересечения //если вдруг точка пересечения попадет в стык между двумя кривыми //встречается часто если сечется прямоугольником так как вектор параллелен оси List<Point3d> points = new List<Point3d>(); using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction()) { //строим луч из центра кривой в плане штриховки using (Ray ray = new Ray()) { //создаем луч из центра кривой if (cur is Curve) ray.BasePoint = GetCentr(cur as Curve); if (cur is Point3d) ray.BasePoint = (Point3d)cur; ray.UnitDir = plane.Normal.GetPerpendicularVector(); //проходим по всем кривым и ищем пересечения using (Curve3d ray3d = ray.GetGeCurve()) { List<Curve> curves = new List<Curve>(); foreach (ObjectId id in curvesId) curves.Add(tr.GetObject(id, OpenMode.ForRead, false, true) as Curve); if (kontur != null) curves.Add(kontur); foreach (Curve curve in curves) { using (Curve3d loopCur3d = curve.GetGeCurve()) using (CurveCurveIntersector3d cuin = new CurveCurveIntersector3d(ray3d, loopCur3d, vector)) { if (cuin.NumberOfIntersectionPoints > 0) { //ищем число пересечений не считая касательных for (int i = 0; i < cuin.NumberOfIntersectionPoints; i++) if (cuin.IsTransversal(i)) { if (!points.Contains(cuin.GetIntersectionPoint(i))) { points.Add(cuin.GetIntersectionPoint(i)); } } } } } } } tr.Commit(); } //если число пересечений нечетное то точка изнутри, если четное или ноль то снаружи if (points.Count % 2 != 0) return 1; else return 2; } /// <summary> /// удаляет объекты из списка по id /// </summary> /// <param name="ids"></param> private void DeleteObj(List<ObjectId> ids) { using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction()) { foreach (ObjectId id in ids) { using (Entity c = tr.GetObject(id, OpenMode.ForWrite, false, true) as Entity) { c.Erase(); } } tr.Commit(); } } /// <summary> /// проверяет положение кривой part относительно кривой kontur /// </summary> /// <param name="kontur"></param> /// <param name="part"></param> /// <param name="iBlock"></param> /// <returns> /// 0 - ошибка исходных данных /// 1 - внутри /// 2 - снаружи /// 3 - на границе /// 4 - внутри и касается контура /// 5 - снаружи и касается контура /// 6 - пересекает контур /// </returns> private int PartIn(Curve kontur, Curve part, Plane plane, Vector3d vector) { if (kontur == null | part == null) return 0; //внутри контура bool into = false; //снаружи контура bool outer = false; //на границе контура bool g = false; //создаем список из трех точек List<Point3d> points = new List<Point3d> { part.StartPoint, part.EndPoint, GetCentr(part) }; //проверяем на пересечение List<Point3d> per = IntersectPoints(ObjectId.Null, ObjectId.Null, kontur.Clone() as Curve, part.Clone() as Curve, plane, vector, false); if (per.Count > 0) return 6; foreach (Point3d point in points) { //проверяем на нахождение на контуре //если проекция точки на контур совпадает с точкой то она на контуре if (kontur.GetClosestPointTo(point, false).Equals(point)) { g = true; continue; } //если не на границе то пользуемся определением положения через луч int res = CurveInCurves(point, new List<ObjectId>(), plane, vector, kontur); if (res == 1) into = true; if (res == 2) outer = true; } //точки только внутри if (into & !outer & !g) { return 1; } //точки только снаружи if (!into & outer & !g) { return 2; } //точки только на границe if (!into & !outer & g) { return 3; } //точки внутри и на границе if (into & !outer & g) { return 4; } //точки снаружи и на границе if (!into & outer & g) { return 5; } return 6; } }}
alz:
Потестировав этот вариант разрезания нашел нестандартное поведение получившихся элементов. Разрезанные этим методом штриховки невозможно разделить встроенным методом "Отдельные штриховки". Есть к у кого какие мысли, может быть я что-то не учел при создании новой штриховки?
Навигация
Перейти к полной версии