Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Draw polyline to nearest point

10 REPLIES 10
SOLVED
Reply
Message 1 of 11
emvy03
3437 Views, 10 Replies

Draw polyline to nearest point

Hello,

 

I started this post within the generic AutoCAD forum but as suggested I have moved it here (old thread here).

 

What I want to do is create a command whereby the user would click a block, and it would search for a polyline within a given area and then draw a new 3D polyline between the block insertion point and the perpendicular point of the existing polyline.

 

I've attached a very basic before/after which also hopefully demonstrates what I'm talking about.

 

To explain further, my block will have a z level of 0 and be placed adjacent to 'Polyline A' which will have a varying z level. So the command would need to first search for Polyline A within a pre-determined area, before drawing a new 3D polyline to connect the block to Polyline A.

 

Any help would be appreciated.

 

Cheers

 

Matt

Tags (1)
10 REPLIES 10
Message 2 of 11
kean.walmsley
in reply to: emvy03

Hello Matt,

 

I'm unfortunately still not fully clear on the problem, but I think it's safe that we can break the problem down into a few steps:

 

  1. Looking for nearby polylines
    • While you might try some kind of window selection, I think you're going to have to analyse the complete modelspace contents for this. If it's going to be an operation that's run repeatedly, you could maintain a spatial index of polylines in memory, so the 2nd run would be quicker.
    • In LISP you'd use (ssget "X") and if in .NET Editor.SelectAll(); then it's all about processing the selection set...
  2. Processing the polylines
    • The analysis is likely to start with getting bounding boxes of the various polylines (which can be placed in an index, as mentioned above) and working out which are likely candidates. The analysis on the shortlist will involve working out the closest point on the polyline to the block, which will give us the endpoint of the line to be created. This could be tricky, so I don't want to gloss over this step (it's the meat of the problem), but then as I'm not 100% clear on the problem statement, I can't really go into greater detail, at this stage.
  3. Drawing the line
    • This is easy, at least.

I noticed in the original thread that the choice of language isn't yet set in stone. If I were to try this, myself, I'd probably use .NET: mainly because of familiarity but also because of the geometry-related functions you have easier access to. You could do it in LISP, but it would personally take me longer.

 

I hope this is of some help... if I could get a better understanding of the exact problem, I might even be able to put together a quick blog post about it.

 

Kean



Kean Walmsley

Platform Architect & Evangelist, Autodesk Research

Blog | Twitter
Message 3 of 11
emvy03
in reply to: kean.walmsley

Hi Kean,

 

Thanks so much for your reply.

 

I apologise for the lack of clarity in my description; hopefully if I provide some context it may clear things up.

 

I am designing a highway drainage system, and will be running a main carrier pipe along the length of the highway (which is the long polyline in the drawing).

 

Into this pipe will be a number of gully pots ( replicated by a block with insertion point) and are running adjacent to the pipe alebit at a different z-level.

 

If I didn't have the use of a tool/script, I would have to go through each block and draw a 3d poline between the insertion pipe of the block and a perpendicular point on the main polyline (or pipe).

 

Since there will be 100's of blocks across my proposal, I would like to create a command where I could choose the main polyline, then choose the blocks and the connection polylines would be drawn automatically. Perhaps I was trying to run before I could even walk, as such maybe we could remove the search function and simply have the user define the polyline with which to connect to.

 

Does this make things any clearer?

 

Cheers

 

Matt

Message 4 of 11
kean.walmsley
in reply to: emvy03

Hi Matt,

 

Thanks for the clarification - that helps me a lot.

 

Yes, absolutely - the very first step should probably be to select a polyline and a block and then create the line between the two. Then you can add the search piece once that's working properly.

 

I'm a bit tied up for the next 10 days or so, but this is an interesting problem to look at. It might actually be easier than I think: GetClosestPointTo() on the polyline might just give the answer... (this is .NET rather than LISP, using the geometry library.)

 

I'll see whether I sneak some time to take a look at this over the coming days.

 

Cheers,

 

Kean



Kean Walmsley

Platform Architect & Evangelist, Autodesk Research

Blog | Twitter
Message 5 of 11
emvy03
in reply to: kean.walmsley

Hi Kean,

 

Excellent! As I say I am quite the novice with coding but I will go away and do some research on .net and see what I can come up with.

 

Please don't let this distract you from your work but any help would be greatly appreciated.

 

Thanks very much

 

Matt

Message 6 of 11
kean.walmsley
in reply to: emvy03

Here's a basic command to get you started... (apologies to all for posting C# code in the LISP forum)

 

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

namespace ConnectBlockToPolyline
{
  public class Commands
  {
    [CommandMethod("B2P")]
    public static void Block2Polyline()
    {
      var doc = Application.DocumentManager.MdiActiveDocument;
      if (doc == null)
        return;

      var db = doc.Database;
      var ed = doc.Editor;

      // Get the block to connect

      var peo = new PromptEntityOptions("\nSelect the block");
      peo.SetRejectMessage("\nMust be a block.");
      peo.AddAllowedClass(typeof(BlockReference), false);

      var per = ed.GetEntity(peo);
      if (per.Status != PromptStatus.OK)
        return;

      var brId = per.ObjectId;

      var peo2 = new PromptEntityOptions("\nSelect the curve");
      peo2.SetRejectMessage("\nMust be a curve.");
      peo2.AddAllowedClass(typeof(Curve), false);

      var per2 = ed.GetEntity(peo2);
      if (per2.Status != PromptStatus.OK)
        return;

      var cId = per2.ObjectId;

      using (var tr = doc.TransactionManager.StartTransaction())
      {
        var br = tr.GetObject(brId, OpenMode.ForRead) as BlockReference;
        if (br != null)
        {
          var btr =
            tr.GetObject(
              SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite
            ) as BlockTableRecord;

          if (btr != null)
          {
            var c = tr.GetObject(cId, OpenMode.ForRead) as Curve;
            if (c != null)
            {
              var pt = c.GetClosestPointTo(br.Position, false);

              var ln = new Line(br.Position, pt);
              btr.AppendEntity(ln);
              tr.AddNewlyCreatedDBObject(ln, true);
            }
          }
        }
        tr.Commit();
      }
    }
  }
}

 



Kean Walmsley

Platform Architect & Evangelist, Autodesk Research

Blog | Twitter
Message 7 of 11
kean.walmsley
in reply to: emvy03

Here's the first post in the series... I'll post the follow-up on Monday:

 

http://through-the-interface.typepad.com/through_the_interface/2016/05/connecting-points-to-curves-b...

 

Kean



Kean Walmsley

Platform Architect & Evangelist, Autodesk Research

Blog | Twitter
Message 8 of 11
emvy03
in reply to: kean.walmsley

Many thanks for your assistance, Kean.

 

I've just seen your second post on the topic and it has been of great help, not only with the highway design but also in getting to grips with the language in general.

 

Thanks again.

 

Matt

Message 9 of 11
emvy03
in reply to: kean.walmsley

Hi,

 

I was tweaking the code to insert a 3D polyline rather than a line which worked absolutely fine. I then tweaked it slightly to insert the 3D polyline at a certain distance below the insertion point of the block. The 3dpointcollection part now looks like:

 

 

var pts = new Point3dCollection();

                foreach (ObjectId id in refIds)
                {

                    var br = tr.GetObject(id, OpenMode.ForRead) as BlockReference;

                    Point3d pt3 = new Point3d(br.Position.X, br.Position.Y, br.Position.Z);
                    
                    pts.Add(pt3);

                };

 

 

If I write "br.Position.Z - 0.6" it correctly starts the 3D polyline 0.6m below the insertion point. However I would eventually like the user to be able to specify the vertical offset, rather than a fixed 0.6.

 

So far I have written the following such that the user can select depth of two choices, but I can't get a way of changing the 'gdchkstring' into a double so it can be subtracted from the block x position:

 

 var gd = new PromptKeywordOptions("\nSelect gully depth to invert");

            gd.AllowNone = true;
            gd.Keywords.Add("0.6");
            gd.Keywords.Add("0.75");
            gd.Keywords.Default = ("0.6");


            var gdchk = ed.GetKeywords(gd);


            if (gdchk.Status != PromptStatus.OK)
                return;

            string gdchkdstring = gdchk.ToString();

 

Any help would be appreciated.

 

Cheers

 

Matt

 

 

Message 10 of 11
kean.walmsley
in reply to: emvy03

Hi Matt,

 

If you want to convert a string to a double, try double.Parse(str). That said, you'd probably be better off using GetDouble(), unless you want to restrict to a set of options. 

 

The other way to do it would be to present a set of options in a list, such as this:

 

1. 0.6

2. 0.75

 

And then use GetInteger() to get one of the items. This would work well if you have a long list of possible options, but want to make sure they choose from a list.

 

I hope this helps,

 

Kean

 

 



Kean Walmsley

Platform Architect & Evangelist, Autodesk Research

Blog | Twitter
Message 11 of 11
emvy03
in reply to: kean.walmsley

Thanks Kean! All sorted!!!

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

”Boost