Jump to content

Block Distance From Nearest Point on a Polyline


wannabe

Recommended Posts

  • Replies 65
  • Created
  • Last Reply

Top Posters In This Topic

  • Lee Mac

    33

  • wannabe

    16

  • ASMI

    8

  • SEANT

    5

Top Posters In This Topic

Posted Images

> Lee Mac

 

About right and left side. Create a temporary curve using _OFFSET on minimal distance and measure the distance from the block to the main and to the temporary curve. Do you understand what I hinted?

 

Thats a nice idea ASMI, offset it one side, say RHS, then say, if the distance to the temp curve is greater than the main curve its on the left and if not, its on the right :)

Link to comment
Share on other sites

This is possibly a “non-issue” but interesting none the less.

 

The closest point from an object to a 3D polyline may not give meaningful information if:

 

 

 

The attached example is exaggerated to illustrate the point.

 

I have used the 3D closest point and then just used simple pythagorean geometry on the x,y coords to get 2D distance. - is this not correct?

Link to comment
Share on other sites

> SEANT, Lee Mac

 

 

 

There is vlax-curve-getClosestPointToProjection function, especially for such cases.

 

I have read the ACAD help file on this, but how would one specify the normal vector, in what format?

Link to comment
Share on other sites

Ok, using ASMI's suggestion:

 

(defun c:pdis (/    varlist     oldvars  cCurve   nlist    sAng     cBlock   txtpnt   index    ent
          dPt1    dPt2     blkDist  blkDist2 blkDist3 blklist  txt      dCurve   lPt1    rl
         )

   (defun makelay (x)
   (if (not (tblsearch "Layer" x))
       (progn
       (setvar "cmdecho" 0)
       (command "-layer" "m" x "")
       (setvar "cmdecho" 1)
       ) ;_  end progn
   ) ;_  end if
   ) ;_  end defun

   (defun Make_Text (txt_pt txt_val)
   (entmake
       (list '(0 . "TEXT")
         '(8 . "TEXT")
         (cons 10 txt_pt)
         (cons 40 2.5)
         (cons 1 txt_val)
         '(50 . 0.0)
         '(7 . "STANDARD")
         '(71 . 0)
         '(72 . 0)
         '(73 . 0)
       ) ; end list
   ) ; end entmake
   ) ;_  end defun

   (defun massoc (key alist / x)
   (foreach x alist
       (if    (eq key (car x))
       (setq nlist (cons (cdr x) nlist))
       ) ;_  end if
   ) ;_  end foreach
   (setq nlist (reverse nlist))
   ) ;_  end defun

   (setq varlist (list "CMDECHO" "CLAYER")
     oldvars (mapcar 'getvar varlist)
   ) ;_  end setq
   (setvar "cmdecho" 0)
   (vl-load-com)
   (if
   (and
       (setq cCurve (car (entsel "\nSelect curve to measure > ")))
       (member (cdr (assoc 0 (entget cCurve)))
           '("LINE" "POLYLINE" "LWPOLYLINE" "SPLINE" "ARC" "CIRCLE" "ELLIPSE")
       ) ;_  end member
   ) ; end and
      (progn
          (massoc 10 (entget cCurve))
          (setq sAng (angle (nth 0 nlist)
                (nth 1 nlist)
             ) ;_  end angle
          ) ;_  end setq
          (while
          (and
              (setq cBlock (ssget '((0 . "INSERT"))))
              (setq txtpnt (getpoint "\nSelect Point for Table > "))
          ) ;_  end and
             (makelay "TEXT")
             (setq index   (1- (sslength cBlock))
               blklist "\n"
               txt        1
             ) ;_  end setq
             (command "_offset" "0.01" cCurve (polar (nth 0 nlist) (- sAng (/ pi 2)) 0.01) "")
             (setq dCurve (entlast))
             (while (not (minusp index))
             (setq    ent     (entget (ssname cBlock index))
               dPt1     (cdr (assoc 10 ent))
               dPt2     (vlax-curve-getClosestPointTo cCurve dPt1)
               blkDist2 (distance dPt1 dPt2)
               blkDist     (expt (+ (expt (- (car dPt1) (car dPt2)) 2)
                         (expt (- (cadr dPt1) (cadr dPt2)) 2)
                          ) ;_  end +
                          0.5
                    ) ;_  end exp
             ) ;_  end setq
             (setq    lPt1     (vlax-curve-getClosestPointTo dCurve dPt1)
               blkDist3 (distance dPt1 lPt1)
             ) ;_  end setq
             (if (< blkDist3 blkDist2)
                 (setq rl "RIGHT")
                 (setq rl "LEFT")
             ) ;_  end if
             (setq    blklist    (strcat    "Block Coord: "
                       (rtos (car dPt1) 2 1)
                       ","
                       (rtos (cadr dPt1) 2 1)
                       "  Distance: "
                       (rtos blkDist 2 1)
                       " : "
                       rl
                   ) ;_  end strcat
             ) ;_  end setq
             (Make_Text (polar txtpnt (* pi 1.5) (* 3.5 txt)) blklist)
             (setq    index (1- index)
               txt   (1+ txt)
             ) ;_  end setq
             ) ; end while
             (entdel dCurve)
          ) ;_  end while
      ) ;_  end progn
      (princ "\n<!> Empty selection or this isn't a Curve (line, polyline, etc.) <!> ")
   ) ; end if
   (mapcar 'setvar varlist oldvars)
   (princ)
) ;_  end defun

Link to comment
Share on other sites

I have used the 3D closest point and then just used simple pythagorean geometry on the x,y coords to get 2D distance. - is this not correct?

 

In a “real world” view, I’d say your method is correct. I brought up the issue to highlight the problems associated with a 2D only requirement.

 

For example, if a local zoning board were interested in offsets only as they appeared on a 2D map, the closest point may be different than one would find in the field (see “3dPolyIssue.dwg”). The objective of these zoning laws may be better served with the inclusion of the third dimension, but my experience has been that zoning departments are woefully behind technically, and put too much trust in their old hand drawn maps.

Link to comment
Share on other sites

In a “real world” view, I’d say your method is correct. I brought up the issue to highlight the problems associated with a 2D only requirement.

 

For example, if a local zoning board were interested in offsets only as they appeared on a 2D map, the closest point may be different than one would find in the field (see “3dPolyIssue.dwg”). The objective of these zoning laws may be better served with the inclusion of the third dimension, but my experience has been that zoning departments are woefully behind technically, and put too much trust in their old hand drawn maps.

 

I understand where you are coming from SEANT - I suppose the error percentage is negligible for such an application.

Link to comment
Share on other sites

I understand where you are coming from SEANT - I suppose the error percentage is negligible for such an application.

 

I suspect that as well. I actually only brought it up as a matter of interest.:geek:

 

:)

Link to comment
Share on other sites

I suspect that as well. I actually only brought it up as a matter of interest.:geek:

 

:)

 

 

And its a good point, as a lecturer at my university pointed out:

 

"With Mathematics there is the possibility of perfect rigour, so why settle for less?"

Link to comment
Share on other sites

> Lee Mac

 

I have read the ACAD help file on this, but how would one specify the normal vector, in what format?

 

This is variant, array of doubles with 3 members (x, y, z). For X,Y plane it equal (0.0 0.0 1.0) because normal vector directed as Z axis. Use vlax-3d-point function to make it variant-array:

 

Command: (vlax-3d-point '(0.0 0.0 1.0))
#<variant 8197 ...>

Link to comment
Share on other sites

And its a good point, as a lecturer at my university pointed out:

 

"With Mathematics there is the possibility of perfect rigour, so why settle for less?"

 

He doesn’t sound like the type to give “partial credit” to incorrect answers on exams. :unsure:

Link to comment
Share on other sites

> Lee Mac

 

 

 

This is variant, array of doubles with 3 members (x, y, z). For X,Y plane it equal (0.0 0.0 1.0) because normal vector directed as Z axis. Use vlax-3d-point function to make it variant-array:

 

Command: (vlax-3d-point '(0.0 0.0 1.0))
#<variant 8197 ...>

 

I tried to check the result of this with no luck:

 

(setq a (getpoint))
(vlax-curve-getClosestPointToProjection (car (entsel)) a (vlax-3d-point '(0.0 0.0 1.0)))

 

Should this return a 2D point? (with z coord zero)

Link to comment
Share on other sites

Excuse me you should to use ordinary coordinates list, not variant.

 

(vlax-curve-getClosestPointToProjection (car (entsel)) a '(0.0 0.0 1.0))

Link to comment
Share on other sites

So I suppose something like this if I have used it properly:

 

(defun c:pdis (/    varlist     oldvars  cCurve   nlist    sAng     cBlock   txtpnt   index    ent
          dPt1    dPt2     blkDist  blkDist2 blkDist3 blklist  txt      dCurve   lPt1    rl
         )

   (defun makelay (x)
   (if (not (tblsearch "Layer" x))
       (progn
       (setvar "cmdecho" 0)
       (command "-layer" "m" x "")
       (setvar "cmdecho" 1)
       ) ;_  end progn
   ) ;_  end if
   ) ;_  end defun

   (defun Make_Text (txt_pt txt_val)
   (entmake
       (list '(0 . "TEXT")
         '(8 . "TEXT")
         (cons 10 txt_pt)
         (cons 40 2.5)
         (cons 1 txt_val)
         '(50 . 0.0)
         '(7 . "STANDARD")
         '(71 . 0)
         '(72 . 0)
         '(73 . 0)
       ) ; end list
   ) ; end entmake
   ) ;_  end defun

   (defun massoc (key alist / x)
   (foreach x alist
       (if    (eq key (car x))
       (setq nlist (cons (cdr x) nlist))
       ) ;_  end if
   ) ;_  end foreach
   (setq nlist (reverse nlist))
   ) ;_  end defun

   (setq varlist (list "CMDECHO" "CLAYER")
     oldvars (mapcar 'getvar varlist)
   ) ;_  end setq
   (setvar "cmdecho" 0)
   (vl-load-com)
   (if
   (and
       (setq cCurve (car (entsel "\nSelect curve to measure > ")))
       (member (cdr (assoc 0 (entget cCurve)))
           '("LINE" "POLYLINE" "LWPOLYLINE" "SPLINE" "ARC" "CIRCLE" "ELLIPSE")
       ) ;_  end member
   ) ; end and
      (progn
          (massoc 10 (entget cCurve))
          (setq sAng (angle (nth 0 nlist)
                (nth 1 nlist)
             ) ;_  end angle
          ) ;_  end setq
          (while
          (and
              (setq cBlock (ssget '((0 . "INSERT"))))
              (setq txtpnt (getpoint "\nSelect Point for Table > "))
          ) ;_  end and
             (makelay "TEXT")
             (setq index   (1- (sslength cBlock))
               blklist "\n"
               txt        1
             ) ;_  end setq
             (command "_offset" "0.01" cCurve (polar (nth 0 nlist) (- sAng (/ pi 2)) 0.01) "")
             (setq dCurve (entlast))
             (while (not (minusp index))
             (setq    ent     (entget (ssname cBlock index))
               dPt1     (cdr (assoc 10 ent))
               dPt2     (vlax-curve-getClosestPointToProjection cCurve dPt1 '(0.0 0.0 1.0))
               blkDist2 (distance dPt1 dPt2)
               blkDist     (expt (+ (expt (- (car dPt1) (car dPt2)) 2)
                         (expt (- (cadr dPt1) (cadr dPt2)) 2)
                          ) ;_  end +
                          0.5
                    ) ;_  end exp
             ) ;_  end setq
             (setq    lPt1     (vlax-curve-getClosestPointToProjection dCurve dPt1 '(0.0 0.0 1.0))
               blkDist3 (distance dPt1 lPt1)
             ) ;_  end setq
             (if (< blkDist3 blkDist2)
                 (setq rl "RIGHT")
                 (setq rl "LEFT")
             ) ;_  end if
             (setq    blklist    (strcat    "Block Coord: "
                       (rtos (car dPt1) 2 1)
                       ","
                       (rtos (cadr dPt1) 2 1)
                       "  Distance: "
                       (rtos blkDist 2 1)
                       " : "
                       rl
                   ) ;_  end strcat
             ) ;_  end setq
             (Make_Text (polar txtpnt (* pi 1.5) (* 3.5 txt)) blklist)
             (setq    index (1- index)
               txt   (1+ txt)
             ) ;_  end setq
             ) ; end while
             (entdel dCurve)
          ) ;_  end while
      ) ;_  end progn
      (princ "\n<!> Empty selection or this isn't a Curve (line, polyline, etc.) <!> ")
   ) ; end if
   (mapcar 'setvar varlist oldvars)
   (princ)
) ;_  end defun

Link to comment
Share on other sites

Lee I tried the routine on page 5 of this thread and it gives the following error: Select curve to measure > ; error: bad argument type: 2D/3D point: nil.

 

Is the one posted above worth giving a shot?

Link to comment
Share on other sites

It doesn't work on my 3D polyline, but normal ones it does.

 

EDIT: Works amazingly on 2D pl's. How is the side it is on being worked out?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...