public void CDS_FindClosestPointOnSurface() { ObjectId surfaceId = promptForTinSurface(); if (surfaceId.IsNull) { write("\nNo TIN Surface selected."); return; } PromptPointResult result = _editor.GetPoint( "\nSelect point outside surface: "); if (result.Status != PromptStatus.OK) { write("\nNo point selected."); return; } Point3d selectedPoint = result.Value; Point3d closestPointFound = Point3d.Origin; double shortestDistanceSoFar = Double.MaxValue; using (Transaction tr = startTransaction()) { TinSurface surface = surfaceId.GetObject(OpenMode.ForRead) as TinSurface; write("\nSelected surface: " + surface.Name); write("\nSelected point: " + selectedPoint.ToString()); ObjectIdCollection borders = surface.ExtractBorder( SurfaceExtractionSettingsType.Model); foreach (ObjectId borderId in borders) { Polyline3d border = borderId.GetObject(OpenMode.ForRead) as Polyline3d; Point3d closestToBorder = border.GetClosestPointTo(selectedPoint, false); double distance = selectedPoint.DistanceTo(closestToBorder); if (distance < shortestDistanceSoFar) { closestPointFound = closestToBorder; shortestDistanceSoFar = distance; } } } write("\nClosest point found: " + closestPointFound.ToString()); using (Transaction tr = startTransaction()) { BlockTableRecord btr = tr.GetObject(_database.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord; Line line = new Line(selectedPoint, closestPointFound); btr.AppendEntity(line); tr.AddNewlyCreatedDBObject(line, true); tr.Commit(); } }
public static Point3d FindClosestPoint(Transaction trans, ObjectId idA, ObjectId idB) { Polyline3d curveA = trans.GetObject(idA, OpenMode.ForRead) as Polyline3d; Polyline3d curveB = trans.GetObject(idB, OpenMode.ForRead) as Polyline3d; double distance = double.MaxValue; Point3d result = Point3d.Origin; for (double param = curveA.StartParam; param < curveA.EndParam; param += ((curveA.EndParam - curveA.StartParam) / 100)) { Point3d pointOnA = curveA.GetPointAtParameter(param); Point3d closestPointOnB = curveB.GetClosestPointTo(pointOnA, false); double distanceBetweenPoints = pointOnA.DistanceTo(closestPointOnB); if (distanceBetweenPoints < distance) { distance = distanceBetweenPoints; result = pointOnA; // equals closestPointOnB } } return(result); }
///<summary> /// Get the intersection points between this planar entity and a curve. ///</summary> ///<param name="cur">The curve to check intersections against.</param> ///<returns>An array of Point3d intersections.</returns> public static Point3d IntersectWith(Point3d pt, Vector3d vect, Polyline3d poly0, Polyline3d poly, double testWidth, Document doc) { Database db = doc.Database; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, false); BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite, false); string layerName = CreateAndAssignALayer(Setting.defaultLayerName);//incase if this layer not exist if (layerName == string.Empty) { layerName = "0"; } #region create a 2d line on XY plane in order to find the intersect point for on TBM centerline //create a 2d point Point3d pt0 = new Point3d(pt.X, pt.Y, 0); Vector3d v = vect.GetNormal() * testWidth; Matrix3d mat = Matrix3d.Displacement(v); Point3d npt = pt0.TransformBy(mat); v = vect.GetNormal() * -testWidth; mat = Matrix3d.Displacement(v); Point3d npt1 = pt0.TransformBy(mat); //create a 2d line in XY plane and add to drawing, this use to intersect with TBM alignment, so I can find the point in TBM alignment to create circle Line ln = new Line(npt, npt1); ln.Layer = layerName; btr.AppendEntity(ln); tr.AddNewlyCreatedDBObject(ln, true); //get the alignment object and find the nearest point to the nominated point Point3dCollection pts3D = new Point3dCollection(); Point3d pt_intersect_in_TBM = Point3d.Origin; try { poly0.IntersectWith(ln, Intersect.OnBothOperands, pts3D, IntPtr.Zero, IntPtr.Zero); if (pts3D.Count > 0) { Point3d p = pts3D[0]; DBPoint db_pt = new DBPoint(p); db_pt.Layer = layerName; btr.AppendEntity(db_pt); tr.AddNewlyCreatedDBObject(db_pt, true); try { double para = poly0.GetParameterAtPoint(pts3D[0]);//this is where it will fail, don't know why! //ed.WriteMessage($"{pts3D[0]}, {para}\n"); pt_intersect_in_TBM = poly.GetPointAtParameter(para); return(pt_intersect_in_TBM); } catch { pt_intersect_in_TBM = poly.GetClosestPointTo(p, Vector3d.ZAxis, true);//when GetParameterAtPoint fail, this is should work. but use in caution! } } #endregion } catch { } tr.Commit(); return(pt_intersect_in_TBM); } }