Hi!
I'm searching for a solution to achieve the following:
I need my users to pick a point p, enter a distance r and a direction v. A new point should be created r units away in vectorial direction. Therefore, the new point is located on an imaginary circle with radius r and center p.
Currently, the user picks the first point and enters a distance. Then, he has to pick another point (Editor.GetPoint with UseBasePoint = true), I calculate the vector between both points, create a new point (with location = BasePoint.location) and translate it d units in vectorial direction. This works of course, but the problem is, that the user doesn't see directly, where his new point is located, since he may pick a point closer to or farther away then r units.
Naively spoken, I want to restrict the line between BasePoint and new point while prompting the user to a fixed length. Is there any way to achieve this? Native calls to ObjectARX-methods would be also okay.
Thank you!
Solved! Go to Solution.
Solved by _gile. Go to Solution.
I like this sample project http://spiderinnet1.typepad.com/blog/2012/01/autocad-net-entityjig-jig-circle-by-center-and-radius.h...
Hi,
Maybe you can use a Jig to show the point durring the prompt for angle.
using System; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.GraphicsInterface; using Autodesk.AutoCAD.Runtime; [assembly: CommandClass(typeof(JigPointOnCircleSample.CommandMethods))] namespace JigPointOnCircleSample { public class CommandMethods { [CommandMethod("Test", CommandFlags.Modal)] public void Test() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; int pdmode = db.Pdmode; double pdsize = db.Pdsize; try { db.Pdmode = 3; db.Pdsize = -3.0; PromptPointResult ppr = ed.GetPoint("\nCenter: "); if (ppr.Status != PromptStatus.OK) return; PromptDistanceOptions pdo = new PromptDistanceOptions("\nRadius: "); pdo.BasePoint = ppr.Value; pdo.UseBasePoint = true; PromptDoubleResult pdr = ed.GetDistance(pdo); if (pdr.Status != PromptStatus.OK) return; Point3d center = ppr.Value.TransformBy(ed.CurrentUserCoordinateSystem); double radius = pdr.Value; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); while (true) { using (DBPoint point = new DBPoint()) { DBPointJig jig = new DBPointJig(point, center, radius); PromptResult pr = ed.Drag(jig); if (pr.Status != PromptStatus.OK) break; btr.AppendEntity(point); tr.AddNewlyCreatedDBObject(point, true); db.TransactionManager.QueueForGraphicsFlush(); } } tr.Commit(); } } catch (System.Exception ex) { ed.WriteMessage("\nError: " + ex.Message + ex.StackTrace); } finally { db.Pdmode = pdmode; db.Pdsize = pdsize; ed.Regen(); } } } class DBPointJig : EntityJig { private double radius, angle; private Point3d center; private DBPoint point; public DBPointJig(DBPoint point, Point3d center, double radius) : base(point) { this.point = point; this.center = center; this.radius = radius; } protected override bool Update() { point.Position = Polar(center, angle, radius); return true; } protected override SamplerStatus Sampler(JigPrompts prompts) { JigPromptAngleOptions opt = new JigPromptAngleOptions("\nAngle: "); opt.BasePoint = center; opt.UseBasePoint = true; opt.Cursor = CursorType.RubberBand; opt.UserInputControls = UserInputControls.UseBasePointElevation | UserInputControls.NullResponseAccepted; PromptDoubleResult pdr = prompts.AcquireAngle(opt); if (pdr.Status == PromptStatus.Cancel || pdr.Status == PromptStatus.Error) return SamplerStatus.Cancel; else if (pdr.Value == angle) return SamplerStatus.NoChange; else { angle = pdr.Value; return SamplerStatus.OK; } } private Point3d Polar(Point3d center, double angle, double distance) { return new Point3d( center.X + distance * Math.Cos(this.angle), center.Y + distance * Math.Sin(this.angle), center.Z); } } }
Hi _gine,
seems to be the solution, for the moment. Thank you.
If anyone is curious how _gine's solution looks like: see the attached screenshot. The 'x' marks a point on an (imaginary) circle with pre-entered center and radius.
I have an old C++-code snippet, which (I guess) allows picking a point at specified distance with a fixed-length rubberband. Unfortunately, I'm not able to validate my assumptions, since it's an old, abandoned project which I'm not able to compile. Furthermore, I wasn't able to find any documentation on the used ads_*-functions. Maybe someone is interesed in this.
int GetPointAtDistance(ads_point base, double dDistance, ads_point retPoint, int *piKeyCode) { int ret = 0; int result; struct resbuf ergebnis; double angle_old, angle; angle_old = 0; World2Ucs(base); ads_polar(base,0,dDistance,retPoint); ads_grdraw(base,retPoint,-1,0); do { result = 0; ret = ads_grread(15,&result,&ergebnis); if (ret != RTNORM) { ads_grdraw(base,retPoint,-1,0); return ret; } switch(result) { case 2: if(piKeyCode) { ads_grdraw(base,retPoint,-1,0); *piKeyCode = ergebnis.resval.rint; ret = RTKWORD; } break; case 5: angle = ads_angle(base,ergebnis.resval.rpoint); if (angle != angle_old) { ads_grdraw(base,retPoint,-1,0); ads_polar(base,angle,dDistance,retPoint); ads_grdraw(base,retPoint,-1,0); } angle_old = angle; break; case 3: ads_grdraw(base,retPoint,-1,0); angle = ads_angle(base,ergebnis.resval.rpoint); ads_polar(base,angle,dDistance,retPoint); break; case 12: ads_grdraw(base,retPoint,-1,0); ret = RTCAN; break; } } while(result != 3 && ret == RTNORM); return ret; }
Can't find what you're looking for? Ask the community or share your knowledge.