.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Prompt user to pick point on circle with given radius

3 REPLIES 3
SOLVED
Reply
Message 1 of 4
m.schilder
1844 Views, 3 Replies

Prompt user to pick point on circle with given radius

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!

 

3 REPLIES 3
Message 2 of 4
fenton.webb
in reply to: m.schilder

I like this sample project http://spiderinnet1.typepad.com/blog/2012/01/autocad-net-entityjig-jig-circle-by-center-and-radius.h...




Fenton Webb
AutoCAD Engineering
Autodesk

Message 3 of 4
_gile
in reply to: m.schilder

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);
        }
    }
}

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 4 of 4
m.schilder
in reply to: m.schilder

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.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost