### Author Topic: .NET GEOMETRY Routines  (Read 52907 times)

0 Members and 1 Guest are viewing this topic.

#### gile

• Water Moccasin
• Posts: 2411
• Marseille, France
##### Re: .NET GEOMETRY Routines
« Reply #15 on: April 19, 2011, 01:16:01 PM »
Thanks, Oleg. You're very welcome.
Speaking English as a French Frog

#### gile

• Water Moccasin
• Posts: 2411
• Marseille, France
##### Re: .NET GEOMETRY Routines
« Reply #16 on: April 25, 2011, 01:55:10 PM »
A new C# implementation of the ConvexHull using Linq (.NET Framework 3 or upper)

Code - C#: [Select]
1. using System;
2. using System.Collections.Generic;
3. using System.Linq;
10.
11. namespace LinqConvexHull
12. {
13.     public class Commands
14.     {
15.         private Point2d _p0;
16.
17.         private bool Clockwise(Point2d p1, Point2d p2, Point2d p3)
18.         {
19.             return ((p2.X - p1.X) * (p3.Y - p1.Y) - (p2.Y - p1.Y) * (p3.X - p1.X)) < 1e-9;
20.         }
21.
22.         private double Cosine(Point2d pt)
23.         {
24.             double d = _p0.GetDistanceTo(pt);
25.             return d == 0.0 ? 1.0 : Math.Round((pt.X - _p0.X) / d, 9);
26.         }
27.
28.         private List<Point2d> ConvexHull(List<Point2d> pts)
29.         {
30.             _p0 = pts.OrderBy(p => p.Y).ThenBy(p => p.X).First();
31.             pts = pts.OrderByDescending(p => Cosine(p)).ThenBy(p => _p0.GetDistanceTo(p)).ToList();
32.             for (int i = 1; i < pts.Count - 1; i++)
33.             {
34.                 while (i > 0 && Clockwise(pts[i - 1], pts[i], pts[i + 1]))
35.                 {
36.                     pts.RemoveAt(i);
37.                     i--;
38.                 }
39.             }
40.             return pts;
41.         }
42.
43.         [CommandMethod("Test")]
44.         public void Test()
45.         {
46.             Document doc = AcAp.DocumentManager.MdiActiveDocument;
47.             Database db = doc.Database;
48.             Editor ed = doc.Editor;
49.             TypedValue[] filter = new TypedValue[1] { new TypedValue(0, "POINT") };
50.             PromptSelectionResult psr = ed.GetSelection(new SelectionFilter(filter));
51.             if (psr.Status != PromptStatus.OK) return;
52.             using (Transaction tr = db.TransactionManager.StartTransaction())
53.             using (Polyline pline = new Polyline())
54.             {
55.                 List<Point2d> pts = new List<Point2d>();
56.                 foreach (SelectedObject so in psr.Value)
57.                 {
58.                     DBPoint dbPt = (DBPoint)tr.GetObject(so.ObjectId, OpenMode.ForRead);
60.                 }
61.                 pts = ConvexHull(pts);
62.                 for (int i = 0; i < pts.Count; i++)
63.                 {
64.                     pline.AddVertexAt(i, pts[i], 0.0, 0.0, 0.0);
65.                 }
66.                 pline.Closed = true;
67.                 pline.SetDatabaseDefaults();
68.                 BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
69.                 btr.AppendEntity(pline);
71.                 tr.Commit();
72.             }
73.         }
74.     }
75. }
76.
« Last Edit: October 20, 2020, 01:13:28 AM by gile »
Speaking English as a French Frog

#### gile

• Water Moccasin
• Posts: 2411
• Marseille, France
##### Re: .NET GEOMETRY Routines
« Reply #17 on: July 10, 2011, 10:41:46 AM »
Hi,

I made a minor update in GeometryExtensions and I added comments to create a documentation file using Sandcastle Help File Builder.

Speaking English as a French Frog

#### qjchen

• Bull Frog
• Posts: 285
• Best wishes to all
##### Re: .NET GEOMETRY Routines
« Reply #18 on: July 13, 2011, 09:41:50 AM »
Gile, Thank you your great library, I will learn a lot from it~

And this code about convex hull which using Linq is so concise, very cool~
« Last Edit: July 13, 2011, 10:11:29 AM by qjchen »
http://qjchen.mjtd.com
My blog http://chenqj.blogspot.com (Chinese, can be translate into English)

#### kaefer

• Swamp Rat
• Posts: 572
##### Re: .NET GEOMETRY Routines
« Reply #19 on: July 13, 2011, 10:39:07 AM »
Gile, Thank you your great library, I will learn a lot from it~

I can only second that. Merci beaucoup!

Alas, there was a minor snag in appropriating your intellectual property: The paper space transformations are extension methods to Editor, whereas I needed them for Viewport to replicate the CHSPACE command. Any chance to make them more generic?

Code: [Select]
`type Viewport with    member vp.DCS2PSDCS =        Matrix3d.Scaling(vp.CustomScale, vp.CenterPoint) *        Matrix3d.Displacement(vp.CenterPoint - Point3d.Origin) *        Matrix3d.Displacement(Point3d.Origin - vp.ViewCenter.To3d)    member vp.PSDCS2DCS = vp.DCS2PSDCS.Inverse()    member vp.DCS2WCS =        Matrix3d.Rotation(-vp.TwistAngle, vp.ViewDirection, vp.ViewTarget) *        Matrix3d.Displacement(vp.ViewTarget - Point3d.Origin) *        Matrix3d.PlaneToWorld vp.ViewDirection    member vp.WCS2DCS = vp.DCS2WCS.Inverse()`

#### gile

• Water Moccasin
• Posts: 2411
• Marseille, France
##### Re: .NET GEOMETRY Routines
« Reply #20 on: July 13, 2011, 01:39:14 PM »
Thank you both.

Quote
there was a minor snag in appropriating your intellectual property
I do not really care about "intellectual property" with the code I post on TheSwamp or elsewhere. I learn a lot from you and others and most of the code I write is "hacked" from what I read.
If I can bring my "two cents" sometimes, it makes me happy when other find it usefull.

Anyway, you're right, the Viewport extensions methods may be useful as the actual methods only work with the current (or last activated) one (I wanted to mimic the AutoLISP trans function with the Point3d.Trans() method).

If you don't mind it's an "appropriation of your intellectual proprety" , I'd add them to the library.
Speaking English as a French Frog

#### jgr

• Guest
##### Re: .NET GEOMETRY Routines
« Reply #21 on: July 15, 2011, 07:49:05 PM »

#### gile

• Water Moccasin
• Posts: 2411
• Marseille, France
##### Re: .NET GEOMETRY Routines
« Reply #22 on: August 29, 2011, 04:16:38 AM »
Hi,

Here's a method to write the Brep (Boundary Representation) geométric informations of Solid3d, Region, Surface to an Xml file.
Requires A2009 or upper.

Method parameters:
- id: A Solid3d, Region or Surface ObjectId
- filename: The Xml file complete path
- append: If the file exists and this parameter is True, the new data is append to the file, else, the file is overwritten

Code - C#: [Select]
1.         public void WriteBrepToXml(ObjectId id, string filename, bool append)
2.         {
3.             XmlDocument xmlDoc = new XmlDocument();
4.             if (System.IO.File.Exists(filename) && append)
5.             {
7.             }
8.             else
9.             {
10.                 string s = @"<?xml version='1.0' ?>
11.                <Brep>
12.                </Brep>";
14.             }
15.             Database db = HostApplicationServices.WorkingDatabase;
16.             using (Transaction tr = db.TransactionManager.StartTransaction())
17.             {
18.                 Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead);
19.                 string solidType;
20.                 if (ent is Solid3d) solidType = "Solide";
21.                 else if (ent is Region) solidType = "Region";
22.                 else if (ent is AcDb.Surface) solidType = "Surface";
23.                 else return;
24.                 using (Brep brp = new Brep(ent))
25.                 {
26.                     XmlElement entNode = xmlDoc.CreateElement(solidType);
27.                     entNode.SetAttribute("Handle", ent.Handle.ToString());
28.                     xmlDoc.DocumentElement.AppendChild(entNode);
29.                     foreach (Complex cplx in brp.Complexes)
30.                     {
31.                         XmlElement cplxNode = xmlDoc.CreateElement("Complex");
32.                         entNode.AppendChild(cplxNode);
33.                         foreach (Shell shl in cplx.Shells)
34.                         {
35.                             XmlElement shlNode = xmlDoc.CreateElement("Shell");
36.                             shlNode.SetAttribute("Type", shl.ShellType.ToString());
37.                             cplxNode.AppendChild(shlNode);
38.                             foreach (AcBr.Face face in shl.Faces)
39.                             {
40.                                 XmlElement faceNode = xmlDoc.CreateElement("Face");
41.                                 shlNode.AppendChild(faceNode);
42.                                 try
43.                                 {
44.                                     foreach (BoundaryLoop loop in face.Loops)
45.                                     {
46.                                         XmlElement loopNode = xmlDoc.CreateElement("Loop");
47.                                         loopNode.SetAttribute("Type", loop.LoopType.ToString());
48.                                         faceNode.AppendChild(loopNode);
49.                                         foreach (Edge edge in loop.Edges)
50.                                         {
51.                                             ExternalCurve3d curve = (ExternalCurve3d)edge.Curve;
52.                                             switch (curve.NativeCurve.GetType().Name)
53.                                             {
54.                                                 case "LineSegment3d":
55.                                                     LineSegment3d ls = (LineSegment3d)curve.NativeCurve;
56.                                                     XmlElement lsNode = xmlDoc.CreateElement("LineSegment3d");
57.                                                     lsNode.SetAttribute("StartPoint", ls.StartPoint.ToString());
58.                                                     lsNode.SetAttribute("EndPoint", ls.EndPoint.ToString());
59.                                                     lsNode.SetAttribute("Direction", ls.Direction.ToString());
60.                                                     loopNode.AppendChild(lsNode);
61.                                                     break;
62.                                                 case "CircularArc3d":
63.                                                     CircularArc3d ca = (CircularArc3d)curve.NativeCurve;
64.                                                     double angle = Vector3d.XAxis
65.                                                          .TransformBy(Matrix3d.PlaneToWorld(ca.Normal))
66.                                                          .GetAngleTo(ca.ReferenceVector, ca.Normal);
67.                                                     XmlElement caNode = xmlDoc.CreateElement("CircularArc3d");
68.                                                     caNode.SetAttribute("StartPoint", ca.StartPoint.ToString());
69.                                                     caNode.SetAttribute("EndPoint", ca.EndPoint.ToString());
70.                                                     caNode.SetAttribute("Center", ca.Center.ToString());
72.                                                     caNode.SetAttribute("StartAngle", (ca.StartAngle + angle).ToString());
73.                                                     caNode.SetAttribute("EndAngle", (ca.EndAngle + angle).ToString());
74.                                                     caNode.SetAttribute("Normal", ca.Normal.ToString());
75.                                                     loopNode.AppendChild(caNode);
76.                                                     break;
77.                                                 case "EllipticalArc3d":
78.                                                     EllipticalArc3d ea = (EllipticalArc3d)curve.NativeCurve;
79.                                                     XmlElement eaNode = xmlDoc.CreateElement("EllipticalArc3d");
80.                                                     eaNode.SetAttribute("StartPoint", ea.StartPoint.ToString());
81.                                                     eaNode.SetAttribute("EndPoint", ea.EndPoint.ToString());
82.                                                     eaNode.SetAttribute("Center", ea.Center.ToString());
83.                                                     eaNode.SetAttribute("StartAngle", ea.StartAngle.ToString());
84.                                                     eaNode.SetAttribute("EndAngle", ea.EndAngle.ToString());
85.                                                     eaNode.SetAttribute("MajorAxis", ea.MajorAxis.ToString());
86.                                                     eaNode.SetAttribute("MinorAxis", ea.MinorAxis.ToString());
89.                                                     eaNode.SetAttribute("Normal", ea.Normal.ToString());
90.                                                     loopNode.AppendChild(eaNode);
91.                                                     break;
92.                                                 case "NurbCurve3d":
93.                                                     XmlElement ncNode = xmlDoc.CreateElement("NurbCurve3d");
94.                                                     NurbCurve3d nc = (NurbCurve3d)curve.NativeCurve;
95.                                                     NurbCurve3dData data = nc.DefinitionData;
96.                                                     ncNode.SetAttribute("StartPoint", nc.StartPoint.ToString());
97.                                                     ncNode.SetAttribute("EndPoint", nc.EndPoint.ToString());
98.                                                     ncNode.SetAttribute("Degree", data.Degree.ToString());
99.                                                     ncNode.SetAttribute("Periodic", data.Periodic.ToString());
100.                                                     ncNode.SetAttribute("Rational", data.Rational.ToString());
101.                                                     for (int i = 0; i < data.Knots.Count; i++)
102.                                                     {
103.                                                         ncNode.SetAttribute(string.Format("Knot_{0}", i + 1), data.Knots[i].ToString());
104.                                                     }
105.                                                     for (int i = 0; i < data.Weights.Count; i++)
106.                                                     {
107.                                                         ncNode.SetAttribute(string.Format("Weight_{0}", i + 1), data.Weights[i].ToString());
108.                                                     }
109.                                                     for (int i = 0; i < data.ControlPoints.Count; i++)
110.                                                     {
111.                                                         ncNode.SetAttribute(string.Format("ControlPoint_{0}", i + 1), data.ControlPoints[i].ToString());
112.                                                     }
113.                                                     loopNode.AppendChild(ncNode);
114.                                                     break;
115.                                             }
116.                                         }
117.                                     }
118.                                 }
119.                                 catch
120.                                 {
121.                                     XmlElement loopNode = xmlDoc.CreateElement("LoopUnbounded");
122.                                     faceNode.AppendChild(loopNode);
123.                                 }
124.                             }
125.                         }
126.                     }
127.                     xmlDoc.Save(filename);
128.                 }
129.                 tr.Commit();
130.             }
131.         }

Heres a little example of the returned file content for a region made of a rectangle from 0,0 to 80,50 with a circular hole which center is at 20,30 and a 10 radius:
Code - XML: [Select]
1. <?xml version="1.0"?>
2. <Brep>
3.   <Region Handle="2747">
4.     <Complex>
5.       <Shell Type="ShellExterior">
6.         <Face>
7.           <Loop Type="LoopInterior">
8.             <CircularArc3d StartPoint="(30,30,0)" EndPoint="(30,30,0)" Center="(20,30,0)" Radius="10" StartAngle="3.14159265358979" EndAngle="9.42477796076938" Normal="(0,0,-1)" />
9.           </Loop>
10.           <Loop Type="LoopExterior">
11.             <LineSegment3d StartPoint="(0,0,0)" EndPoint="(80,0,0)" Direction="(1,0,0)" />
12.             <LineSegment3d StartPoint="(80,0,0)" EndPoint="(80,50,0)" Direction="(0,1,0)" />
13.             <LineSegment3d StartPoint="(80,50,0)" EndPoint="(0,50,0)" Direction="(-1,0,0)" />
14.             <LineSegment3d StartPoint="(0,50,0)" EndPoint="(0,0,0)" Direction="(0,-1,0)" />
15.           </Loop>
16.         </Face>
17.       </Shell>
18.     </Complex>
19.   </Region>
20. </Brep>
« Last Edit: July 12, 2016, 06:31:08 AM by gile »
Speaking English as a French Frog

#### gile

• Water Moccasin
• Posts: 2411
• Marseille, France
##### Re: .NET GEOMETRY Routines
« Reply #23 on: September 11, 2011, 08:36:50 AM »
Hi,

I expanded a little the GeometryExtensions library.
There're two more classes: PolylineSegment and PolylineSegmentCollection (which inherits from List<PolylineSegment>) and a new extension method: Ellipse.ToPolyline().
I hope these classes make easier some work with polylines or to create polylines from other entities.

Here's a quick and dirty example (will give unexpected result with entities which don't lies on the WCS XY plane).
The MJOIN command joins the selected entities: line, arc, polyline, ellipse and spline (A2010 or later for spline) into one or more polyline(s).

Code: [Select]
`using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.DatabaseServices;using Autodesk.AutoCAD.EditorInput;using Autodesk.AutoCAD.Geometry;using Autodesk.AutoCAD.Runtime;using GeometryExtensions;using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;namespace GeometryExtensionsTestCommands{    public class MjoinCommand    {        [CommandMethod("mjoin")]        public void PolyJoin()        {            Document doc = AcAp.DocumentManager.MdiActiveDocument;            Database db = doc.Database;            Editor ed = doc.Editor;            TypedValue[] filter = {                   new TypedValue(-4,"<OR"),                new TypedValue(0, "ARC,ELLIPSE,LINE,LWPOLYLINE"),                new TypedValue(-4, "<AND"),                new TypedValue(0, "SPLINE"),                new TypedValue(-4, "&"),                new TypedValue(70, 8),                new TypedValue(-4, "AND>"),                new TypedValue(-4, "OR>")};            PromptSelectionResult psr = ed.GetSelection(new SelectionFilter(filter));            if (psr.Status != PromptStatus.OK) return;            using (Transaction tr = db.TransactionManager.StartTransaction())            {                BlockTableRecord btr =                    (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);                PolylineSegmentCollection psc = new PolylineSegmentCollection();                Plane plane = new Plane(Point3d.Origin, Vector3d.ZAxis);                foreach (ObjectId id in psr.Value.GetObjectIds())                {                    Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead);                    switch (ent.GetType().Name)                    {                        case "Arc":                            Arc arc = (Arc)ent;                            psc.Add(new PolylineSegment(                                new CircularArc2d(                                    arc.Center.Convert2d(plane),                                    arc.Radius,                                    arc.StartAngle,                                    arc.EndAngle,                                    Vector2d.XAxis,                                    false)));                            break;                        case "Ellipse":                            Ellipse el = (Ellipse)ent;                            psc.AddRange(new PolylineSegmentCollection(el));                            break;                        case "Line":                            Line l = (Line)ent;                            psc.Add(new PolylineSegment(                                new LineSegment2d(                                    l.StartPoint.Convert2d(plane),                                    l.EndPoint.Convert2d(plane))));                            break;                        case "Polyline":                            Polyline pl = (Polyline)ent;                            psc.AddRange(new PolylineSegmentCollection(pl));                            break;                        case "Spline":                            try                            {                                Spline spl = (Spline)ent;                                psc.AddRange(new PolylineSegmentCollection((Polyline)spl.ToPolyline()));                            }                            catch { }                            break;                        default:                            break;                    }                }                foreach (PolylineSegmentCollection segs in psc.Join())                {                    Polyline pline = segs.ToPolyline();                    btr.AppendEntity(pline);                    tr.AddNewlyCreatedDBObject(pline, true);                }                tr.Commit();            }        }    }}`
Speaking English as a French Frog

#### gile

• Water Moccasin
• Posts: 2411
• Marseille, France
##### Re: .NET GEOMETRY Routines
« Reply #24 on: October 16, 2011, 11:02:36 AM »
Hi,

The GeometryExtension librairy keeps on growing.

The main new things are Polyline, Polyline2d and Polyline3d extensions methods : GetProjectedPolyline and GetOrthoProjectedPolyline.

These methods create a new Polyline object and may replace the GetProjectedCurve and GetOrthoProjectedCurve methods which do not give expected results with Polyline and Polyline2d entities.
The elliptical arcs resulting of the polyline arcs projection are approximated using the PolylineSegmentCollection(Ellipse ellipse) constructor. This constructor uses the same geometric method as the 'old' AutoCAD native approximation of ellipses (i.e. PELLIPSE = 1).
« Last Edit: October 16, 2011, 11:16:30 AM by gile »
Speaking English as a French Frog

#### gile

• Water Moccasin
• Posts: 2411
• Marseille, France
##### Re: .NET GEOMETRY Routines
« Reply #25 on: November 14, 2011, 03:13:32 PM »
New version of GeometryExtensions (1.3).
Corrected some bugs with the GetProjectedPolyline and GetOrthoProjectedPolyline methods.
Speaking English as a French Frog

#### fixo

• Guest
##### Re: .NET GEOMETRY Routines
« Reply #26 on: May 05, 2012, 04:56:14 AM »
Draw bisector berween 2 lines
Code: [Select]
`        [CommandMethod("bisect", CommandFlags.Modal | CommandFlags.Redraw)]        public static void TestForBiLine()        {            // Get the current document and database             Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;             Database db = doc.Database;             Editor ed = doc.Editor;            // Select lines            PromptEntityOptions opt = new PromptEntityOptions("\nSelect a first line:");            opt.SetRejectMessage("\nMust be selected the line only!");            opt.AddAllowedClass(typeof(Line),false);            PromptEntityResult res1 = ed.GetEntity(opt);            // Set 'black hole' to exit if something wrong            if (res1.Status != PromptStatus.OK)return;         opt=   new PromptEntityOptions("\nSelect a second line:");            PromptEntityResult res2 = ed.GetEntity(opt);            // Set 'black hole' to exit if something wrong            if (res2.Status != PromptStatus.OK) return;            // Open transaction             Transaction tr = db.TransactionManager.StartTransaction();             using (tr)             {                              DBObject obj1 = tr.GetObject(res1.ObjectId, OpenMode.ForWrite);                 Line ln1 = obj1 as Line;                 // Set 'black hole' to exit if something wrong                 if (ln1 == null) return;                                 DBObject obj2 = tr.GetObject(res2.ObjectId, OpenMode.ForWrite);                 Line ln2 = obj2 as Line;                 // Set 'black hole' to exit if something wrong                 if (ln2 == null) return;                          Point3d ps1 = ln1.StartPoint;                 Point3d pe1 = ln1.EndPoint;                 Point3d ps2 = ln2.StartPoint;                 Point3d pe2 = ln2.EndPoint;                 Point3dCollection pts = new Point3dCollection();                 ln1.IntersectWith(ln2, Intersect.ExtendBoth, pts, 0, 0);                 // Set 'black hole' to exit if no intersection                 if (pts.Count != 1)                 {                     acadApp.ShowAlertDialog("Lines are colinear or does not intersects each another");                     return;                 }                 // Calculate nearest point to the first line                 Point3d pk1 = res1.PickedPoint;                 pk1 = ln1.GetClosestPointTo(pk1, true);                 // Calculate nearest point to the first line                 Point3d pk2 = res2.PickedPoint;                 pk2 = ln2.GetClosestPointTo(pk2, true);                 // Swap start and end points if lines has different direction                 if (ps1.DistanceTo(ps2) + pe1.DistanceTo(pe2) > (ps1.DistanceTo(pe2) + pe1.DistanceTo(ps2)))                 {                     Point3d tp = new Point3d(ps1.X, ps1.Y, ps1.Z);                     ps1 = pe1;                     pe1 = tp;                 }                 // create the first temporary Line3d object                 Line3d tl1 = new Line3d(ps1, ps2);                 // Calculate midpoint of this line                 Point3d tp1 = tl1.EvaluatePoint(0.5);                 // create the second temporary Line3d object                 Line3d tl2 = new Line3d(pe1, pe2);                 // Calculate midpoint of this line                 Point3d tp2 = tl2.EvaluatePoint(0.5);                 // Create bisector line                 Line ln = new Line(tp1, tp2);                 ln.SetDatabaseDefaults();                 BlockTableRecord btr = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;                 // Append line to the current space and transaction                 btr.AppendEntity(ln);                 tr.AddNewlyCreatedDBObject(ln, true);                 // Commit transaction                 tr.Commit();             }        }`
Regards,

~'J'~
« Last Edit: May 05, 2012, 03:21:03 PM by fixo »

#### gile

• Water Moccasin
• Posts: 2411
• Marseille, France
##### Re: .NET GEOMETRY Routines
« Reply #27 on: May 05, 2012, 03:13:26 PM »
Hi Oleg,

Here's another way using vectors

Code - C#: [Select]
1.         [CommandMethod("Bisect")]
2.         public void Bisector()
3.         {
4.             Document doc = AcAp.DocumentManager.MdiActiveDocument;
5.             Database db = doc.Database;
6.             Editor ed = doc.Editor;
7.             PromptEntityOptions peo = new PromptEntityOptions("\nSelect the first line: ");
8.             peo.SetRejectMessage("Selected object is not a line !");
10.             PromptEntityResult per = ed.GetEntity(peo);
11.             if (per.Status != PromptStatus.OK) return;
12.             Point3d p1 = per.PickedPoint.TransformBy(ed.CurrentUserCoordinateSystem);
13.             ObjectId id1 = per.ObjectId;
14.             peo.Message = "\nSelect the second line: ";
15.             per = ed.GetEntity(peo);
16.             if (per.Status != PromptStatus.OK) return;
17.             Point3d p2 = per.PickedPoint.TransformBy(ed.CurrentUserCoordinateSystem);
18.             ObjectId id2 = per.ObjectId;
19.             using (Transaction tr = db.TransactionManager.StartTransaction())
20.             {
21.                 Line l1 = (Line)tr.GetObject(id1, OpenMode.ForRead);
22.                 Line l2 = (Line)tr.GetObject(id2, OpenMode.ForRead);
23.
24.                 // Checks if lines intersect
25.                 Plane plane;
26.                 Line3d line1 = new Line3d(l1.StartPoint, l1.EndPoint);
27.                 Line3d line2 = new Line3d(l2.StartPoint, l2.EndPoint);
28.                 if (!line1.IsCoplanarWith(line2, out plane) || line1.IsParallelTo(line2))
29.                     return;
30.
31.                 // Calculates the bisector
32.                 Point3d inters = line1.IntersectWith(line2)[0];
33.                 Vector3d vec1 = line1.Direction;
34.                 Vector3d vec2 = line2.Direction;
35.                 // Corrects the vectors direction according to picked points
36.                 if (vec1.DotProduct(inters.GetVectorTo(p1)) < 0)
37.                     vec1 = vec1.Negate();
38.                 if (vec2.DotProduct(inters.GetVectorTo(p2)) < 0)
39.                     vec2 = vec2.Negate();
40.                 Vector3d bisectDir = (vec1 + vec2) / 2.0;
41.
42.                 // Draws the bisector (XLine)
43.                 Xline xline = new Xline();
44.                 xline.UnitDir = bisectDir.GetNormal();
45.                 xline.BasePoint = inters;
46.                 BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
47.                 btr.AppendEntity(xline);
49.                 tr.Commit();
50.             }
51.         }

Note: AFAIK, there's no need to call Dispose() on Line3d objects (as for Vector3d, Point3d, ...).
Speaking English as a French Frog

#### fixo

• Guest
##### Re: .NET GEOMETRY Routines
« Reply #28 on: May 05, 2012, 03:22:47 PM »
Thanks, Gilles, I removed these lines from code
Regards,
Oleg

#### fixo

• Guest
##### Re: .NET GEOMETRY Routines
« Reply #29 on: May 06, 2012, 02:27:34 AM »
Circle by 3 points
Code: [Select]
`        [CommandMethod("circ3p")]// This method can have any name        public static void TestFor3PointCircle()        {            // Get the document and database            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;            Database db = doc.Database;            Editor ed = doc.Editor;            // If we have a valid point selection, get all 3 points           PromptPointOptions ppo =   new PromptPointOptions("\nPick a point : ");            ppo.AllowNone = true;            PromptPointResult ppr;                ppr = ed.GetPoint(ppo);                if (ppr.Status != PromptStatus.OK) return;            Point3d p1= ppr.Value;            ppo =   new PromptPointOptions("\nPick a second point : ");                 ppr = ed.GetPoint(ppo);                if (ppr.Status != PromptStatus.OK) return;            Point3d p2= ppr.Value;                        ppo =   new PromptPointOptions("\nPick a third point : ");                 ppr = ed.GetPoint(ppo);                if (ppr.Status != PromptStatus.OK) return;            Point3d p3= ppr.Value;            // To pass center point by reference            Point3d pc = new Point3d();            // Get result            bool result = CircleCenter(p1, p2, p3, out pc);            if (result)                ed.WriteMessage("\nCenter point calculated:\t{0:f3},{1:f3},{2:f3}", pc.X, pc.Y, pc.Z);            else return;            // Calculate radius            double rad = pc.DistanceTo(p1);            // Open transaction and add circle to the current space            using (Transaction tr = db.TransactionManager.StartTransaction())            {                Circle circ = new Circle(pc, Vector3d.ZAxis, rad);                BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);                btr.AppendEntity(circ);                tr.AddNewlyCreatedDBObject(circ, true);                // Commit transaction                tr.Commit();                            }                  }        public static bool CircleCenter(Point3d p0, Point3d pm, Point3d p1, out Point3d pc)        {            Vector3d v1 = p0 - pm;            Vector3d v2 = p1 - pm;            if (v1.IsParallelTo(v2))            {                pc = new Point3d();                return false;            }            CircularArc3d crc = new CircularArc3d(p0, pm, p1);            pc = crc.Center;            return true;        }    }`
Regards,

~'J'~