Jump to content

Check-distance between a 3D polyline in a block reference and a 2D polyline


CFORD

Recommended Posts

Hello wonderful people,

 

I was wondering if I could have a hand with creating a lisp command. I have used this forum before and you guys have been super helpful! I dont want to seem like I am taking the piss asking for help all the time so I have recently had some time to start learning lisp from scratch. Unfortunately I have a long way to go from this https://www.cadtutor.net/tutorials/autolisp/quick-start.php# to get what I want to do so I was hoping I could get some help?

 

I want it to do the following. Firstly, invoke the command and it should be called check-distance. Next I want to select a polyline which will be closed and 2D. I want to store the x and y coordinates of each vertex for later. Next I want to select a block reference. Within this block reference there is a 3D polyline I want to store all the x and y coordinates of all the 3D polylines that are found on the model and ignore all other objects (in this case 3D solids) in the block reference. Next I want the code to only perform the calculation if the 3D polyline is found inside of the 2D polyline and ignore all the 3D polylines on the outside of the 2D polyline. Now we can use the x and y of each vertices of both the 2D polyline and 3D polyline to get the line segments and see how close the corresponding line segments get to each other. If there are areas where the 3D polyline line segments gets closer than 4m to the 2D polylines line segments I want it to draw a small 1m circle round the block reference that is closer than 4m and colour the circle red. The circle should go into a layer called check-distance. If it is not closer than 4m no need to do anything and check the next 3D polyline until all 3D polylines from the block reference that were selected which are inside the 2D polyline have been checked to see if they are closer than 4m to the 2D polyline. 

 

Attached is an example drawing to help you understand what I am trying to convey.

 

Many thanks again.

 Chech-distance.dwg

 

 

Link to comment
Share on other sites

Do you want to do this in stages - and maybe we can all chip in a few answers, build up a LISP and then you can learn what we are doing?

 

Basics the below is the very very basics for a LISP - stop me when I am being too simplistic. checkdistance is the function name, 'c : ' so that it runs as a command from the command line ( / ) is where we can define variables after the / are local variables, before the / any that are passed to the LISP from other LISPs if that is needed

 

(defun c:checkdistance ( / )


  (princ) ; end quietly
) ; end defun

 

Save this as a text file with a .lsp extension. You can copy and paste all the other ideas into there to make up your program.

 

Selecting a polyline can be done 2 ways, with an entsel or with ssget. ssget might be the way to go and filter with that to a polyline (http://lee-mac.com/ssget.html is a good reference)

 

(setq MyPoly (ssname (ssget "_+.:E:S" '((0 . "LWPOLYLINE")(70 . 1)) ) 0 ) )

 

This creates a variable MyPoly grabbing a single entiy (E:S), LWPolyline that is closed (70 . 1 - closed, 70 . 0 - Open, leave out for either)

 

Put MyPoly as a local variable in the definition line (after the '/')

 

This has given you a simple LISP that lets you select an LWPolyline - try putting this together and then we can maybe loop through what we select to make a list of coordinates.

 

We can adjust the ssget later to select more polylines 

 

 

You might want to get something back on the display to show it has done something - add this at the end

 

(princ (entget MyPoly))

 

Which will display a list of what the polyline definition is. In that there are some details like (10 . xx xx xx ) - these are the coordinates that we need to grab next

 

 

a lot of words to give you: (for now)

 

(defun c:checkdistance ( / )

  (setq MyPoly (ssname (ssget "_+.:E:S" '((0 . "LWPOLYLINE")(70 . 1)) ) 0 ) )
  (princ (entget MyPoly))


  (princ) ; end quietly
) ; end defun

 

Link to comment
Share on other sites

Ok brilliant thank you for letting me take up some of your time. Yea that is very useful My knowledge thus far extents to the content of this site https://www.cadtutor.net/tutorials/autolisp/quick-start.php# so basic is good. I will have a read of the site you posted as well that look really useful.

 

So in effect it would look like this?

(defun c:checkdistance ( / MyPoly )

  (setq MyPoly (ssname (ssget "_+.:E:S" '((0 . "POLYLINE")(70 . 1)) ) 0 ) )
  (princ (entget MyPoly))

  (princ) 
) 

 

When I ran this in AutoCad I got this 

"Command: CHECKDISTANCE
Select objects:
; error: bad argument type: lselsetp nil"

 

Maybe I did something wrong and that is why I didn't get a list?

Link to comment
Share on other sites

Small typing error, it wants to see "LWPOLYLINE" and not just polyline in the ssget line (Light Weight Polyline - a 2D polyline). You can use a wild card in this feature, a star to give *POLYLINE which will get any entity type containing 'polyline' and is often used for example in text selection where you have Mtext or text, *text will get them both

 

I guess the next thing to look at is an error function in that line to stop if you don't select the right thing -will have to come back to this later

Link to comment
Share on other sites

So did some work to try and understand this further and add in the error function you mentioned and got to this.

(defun c:checkdistance ( / Mypoly )

(setq MyPoly (ssname (ssget "_+.:E:S" '((0 . "*POLYLINE"))) 0)) 

(if Mypoly ;start the if statment 

    (princ (entget MyPoly)) ;if it is a valid polyline then get the Mypoly information

(princ "No polyline found in the drawing.")) ;if it is not valid print this 

  (princ) ;end the command neatly

)

For some reason having the '(70 . 1)' was throwing up the "; error: bad argument type: lselsetp nil" not sure why 

Edited by CFORD
  • Like 1
Link to comment
Share on other sites

So for the ssget filters, these filter by the entity information, each dotted pair list eg ( 0 . "*POLYLINE") making up the entity. 70 for polylines is the marker for open of closed, 1 being a closed polyline, 0 being an open ended polyline - so if your filter is looking for open and you select closed it will make the error - if that makes sense. You don't need to use filters of course, and the example above is an 'and' list, (if this And that are true)

 

Right so next step is to get the coordinates?

 

This is a really useful little snippet to put in the command line:

 

(entget (car (entsel "Select Entity") ))

 

The display in the command line is how the entity is made up. Noting that this is the other way to select an entity to the ssget (no filters possible though), (entsel will return the entity name and the point you clicked, as a list, (car will return the first element in a list, in this case the element name (something like <Entity name: 14c1ec4d5f0>  and entget will 'get' the entity information from that entity name.

 

In this list are a load of dotted pairs, the coordiantes for most things are (10 . xyx) or ( 11. xyz) - here we want to get the 10's as a list

 

The first example in the link below loops through the polyline stuff to get the coordiantes, see if you cn fix it in your code?

 

 

 

Edited by Steven P
Link to comment
Share on other sites

Ok 2d and 3d poly co-ordinates sample code.

 

; pline co-ords example
; By Alan H

(defun getcoords (ent)
  (vlax-safearray->list
    (vlax-variant-value
      (vlax-get-property
    (vlax-ename->vla-object ent)
    "Coordinates"
      )
    )
  )
)


 
; convert now to xyz
(defun co-ords2xy (xyz / )
(setq co-ordsxy '())
(if (= xyz 2)
(progn
(setq I 0)
(repeat (/ (length co-ords) 2)
(setq xy (list (nth i co-ords)(nth (+ I 1) co-ords) ))
(setq co-ordsxy (cons xy co-ordsxy))
(setq I (+ I 2))
)
)
)
(if (= xyz 3)
(progn
(setq I 0)
(repeat (/ (length co-ords) 3)
(setq xy (list (nth i co-ords)(nth (+ I 1) co-ords)(nth (+ I 2) co-ords) ))
(setq co-ordsxy (cons xy co-ordsxy))
(setq I (+ I 3))
)
)
)
)

(defun c:wow ( / )
(setq obj (vlax-ename->vla-object (car  (entsel "Pick obj"))))

(setq co-ords (vlax-get obj 'coordinates))
(cond 
  (( = (vla-get-objectname obj) "AcDb2dPolyline")(co-ords2xy 2))
  (( = (vla-get-objectname obj) "AcDb3dPolyline")(co-ords2xy 3))
)
(princ co-ordsxy)

(foreach pt co-ordsxy
  (setq pt (list (car pt)(cadr pt) (caddr pt)))
  (command "text" "C" pt 1.5 0.0 (rtos (caddr pt) 2 2))
)

(princ)
)
(c:wow)

 

  • Like 2
Link to comment
Share on other sites

Right so this how far I got but something isn't correct what did I do wrong here? Posting this even though it is wrong because I need to know why it is wrong not because I haven't put in the effort to fix it.

 

(defun c:checkdistance (/ Mypoly MyPolyVertexes )
(if (setq MyPoly (ssname (ssget "_+.:E:S" '((0 . "*POLYLINE"))) 0 ))
    (progn
    (setq MyPoly (entget (ssname Mypoly 0)))
    (foreach sublist Mypoly
     (if (= (car sublist) '10)
      (setq MyPolyVertexes (append MyPolyVertexes (list (cdr sublist))))))
(princ (entget MyPolyVertexes)))
(princ "No polyline found in the drawing."))
  (princ)
)

 

Thank you @BIGAL I look forward to implementing that into the code.

 

Many thanks to you as well @Steven P

Edited by CFORD
  • Like 1
Link to comment
Share on other sites

A couple of quick corrections and an explanation

If you are appending to a list (MypolyVertexes), it is often a good idea to create it as a blank list first - so that there is a list existing to add to (setq MyPolyVertexes (list)) does the trick there

 

The main change to make is to MyPoly, we have grabbed a polyline and used ssname to get the entity name of that using ssname function, but we have repeated that again 2 lines later (copy and pasted that) - ssname works on a selection set but now we are trying to do the same to an entity name... and it doesn't like that - so we will get rid of that

 

Final thing is the (princ (entget MyPoly..... )), trying to get the wrong information from the type of variable. 'ent' for entities but now we are looking at a list, so we can get rid of that too to give:

 

(defun c:checkdistance (/ Mypoly MyPolyVertexes )
  (setq MyPolyVertexes (list))
  (if (setq MyPoly (ssname (ssget "_+.:E:S" '((0 . "*POLYLINE"))) 0 ))
    (progn
      (setq MyPoly (entget MyPoly))
      (foreach sublist Mypoly
        (if (= (car sublist) '10)
          (setq MyPolyVertexes (append MyPolyVertexes (list (cdr sublist))))
        ) ; end if
      ) ; end foreach

      (princ MyPolyVertexes)
    ) ; end progn
  (princ "No polyline found in the drawing.")
  ) ; end if
  (princ)
)

 

 

So close!! But frustratingly not quite there - this should work OK now.

 

 

 

 

Another way to do this and stealing BigAls code for a moment for 2D polylines

 

(defun getcoords (ent / )
  (vlax-safearray->list
    (vlax-variant-value
      (vlax-get-property
    (vlax-ename->vla-object ent)
    "Coordinates"
      )
    )
  )
)


(defun c:checkdistance (/ Mypoly MyPolyVertexes )
  (if (setq MyPoly (ssname (ssget "_+.:E:S" '((0 . "*POLYLINE"))) 0 ))
    (progn
      (setq MyPolyVertexes (getcoords MyPoly)) ; this part calls the other function
      (princ MyPolyVertexes)
    ) ; end progn
  (princ "No polyline found in the drawing.")
  ) ; end if
  (princ)
)

 

Here your main code is  lot shorter by calling another function (and you can use this other function for other LISPs later also). Put the function in brackets ( ) and as it is types after the defun for example (getcoords ..... or (c:checkdistance..... . If the defun brackets has something before the / then the function is expecting some information, here with BigAl an entity name, so you'll need to include that - see above, (getcoords MyPoly)

 

Hope this is making sense so far!!

Right, the next step then - what shall we do next?

 

Link to comment
Share on other sites

and BIgAl has put it all together handily for you with wow at the end of his code to look for 2d and 3d polylines

Link to comment
Share on other sites

Brilliant that makes more sense now just a few questions then. why was it necessary to move the if function from after this  "(setq MyPoly (ssname (ssget "_+.:E:S" '((0 . "*POLYLINE"))) 0 ))" to now before "(if (setq MyPoly (ssname (ssget "_+.:E:S" '((0 . "*POLYLINE"))) 0 ))". 

 

I we keep to what was written in the AutoLISP Quick Start we are still at the gathering data stage. So we need to do this part "Next I want to select a block reference. Within this block reference there is a 3D polyline I want to store all the x and y coordinates of all the 3D polylines that are found on the model and ignore all other objects (in this case 3D solids) in the block reference." 

 

So we have some of the code already for this so here is my attempt to try do this next part based on what I have gathered so far to select a block reference

(defun c:checkdistance (/ Mypoly MyPolyVertexes blockref Blockcoords )
  (setq MyPolyVertexes (list))
  ((Setq Blockcoords (list))
  (if (setq MyPoly (ssname (ssget "_+.:E:S" '((0 . "*POLYLINE"))) 0 ))
    (progn
      (setq MyPoly (entget MyPoly))
      (foreach sublist Mypoly
        (if (= (car sublist) '10)
          (setq MyPolyVertexes (append MyPolyVertexes (list (cdr sublist))))
        ) ; end if
      ) ; end foreach
      (princ MyPolyVertexes)
    ) ; end progn
  (princ "No polyline found in the drawing.")
  ) ; end if
(if(setq blockref (ssname (ssget "N:" '((0 . "blockreference")))0))
   (Progn
	(Setq Blockcoords (entget blockref))
	(foreach sublist blockref
	  (if (= (car sublist) '10)
		(set Blockcoords (append Blockcoords (list (cdr sublist))))
	  )
	)
  (princ)
)

And trying BIgal's way

(defun getcoords (ent / )
  (vlax-safearray->list
    (vlax-variant-value
      (vlax-get-property
    (vlax-ename->vla-object ent)
    "Coordinates"
      )
    )
  )
)


(defun c:checkdistance (/ Mypoly MyPolyVertexes blockref Blockcoords)
  (if (setq MyPoly (ssname (ssget "_+.:E:S" '((0 . "*POLYLINE"))) 0 ))
    (progn
      (setq MyPolyVertexes (getcoords MyPoly)) ; this part calls the other function
      (princ MyPolyVertexes)
    ) ; end progn
  (princ "No polyline found in the drawing.")
  ) ; end if
(if (setq blockref (ssname (ssget "N:" '((0 . "blockreference")))0))
   (progn
	(set blockcoords (getcoords blockref))
      (princ blockcoords))
(princ "No blockref found in the drawing.")
)
  (princ)
)

. Looking at the link you sent earlier it looks like I need to use this.image.thumb.png.7f558316d45f41f246c4dd850223d4d7.png

Edited by CFORD
Link to comment
Share on other sites

Lunchtime here in a few minutes I'll look after then - but they way we're going you'll be off and finished this soon yourself

  • Like 1
Link to comment
Share on other sites

thought I had posted this snippet:

 

(entget (car (entsel)))

 

This will show how an entities is made up, in the case of a block reference, select one, and the definitition for ( 0 . ..... ) will show as (0 . "INSERT")

Link to comment
Share on other sites

Enjoy your lunch! Ok given it a go at amending it based on that

(defun c:checkdistance (/ Mypoly MyPolyVertexes Blockcoords )
  (setq MyPolyVertexes (list))
  ((Setq Blockcoords (list))
  (if (setq MyPoly (ssname (ssget "_+.:E:S" '((0 . "*POLYLINE"))) 0 ))
    (progn
      (setq MyPoly (entget MyPoly))
      (foreach sublist Mypoly
        (if (= (car sublist) '10)
          (setq MyPolyVertexes (append MyPolyVertexes (list (cdr sublist))))
        ) ; end if
      ) ; end foreach
      (princ MyPolyVertexes)
    ) ; end progn
  (princ "No polyline found in the drawing.")
  ) ; end if
(if(setq blockref (ssname (ssget "N:" '((0 . "insert")))0))
   (Progn
	(Setq Blockcoords (entget (car (entsel blockref)))
	(foreach sublist blockref
	  (if (= (car sublist) '10)
		(set Blockcoords (append Blockcoords (list (cdr sublist))))
	  )
	)
  (princ)
)



(defun getcoords (ent / )
  (vlax-safearray->list
    (vlax-variant-value
      (vlax-get-property
    (vlax-ename->vla-object ent)
    "Coordinates"
      )
    )
  )
)


(defun c:checkdistance (/ Mypoly MyPolyVertexes Blockcoords)
  (if (setq MyPoly (ssname (ssget "_+.:E:S" '((0 . "*POLYLINE"))) 0 ))
    (progn
      (setq MyPolyVertexes (getcoords MyPoly)) ; this part calls the other function
      (princ MyPolyVertexes)
    ) ; end progn
  (princ "No polyline found in the drawing.")
  ) ; end if
(if (setq blockref (ssname (ssget "N:" '((0 . "insert")))0))
   (progn
	(set blockcoords (getcoords blockref))
      (princ blockcoords))
(princ "No blockref found in the drawing.")
)
  (princ)
)

 

Link to comment
Share on other sites

I've run out of time to do more this week on this one, sorry - got a holiday planed from tomorrow - looks like you are heading in the right direction

Link to comment
Share on other sites

  • 2 months later...

A long time since I have been on this thread but I have developed the code a bit further on my own. By all means it is not perfect I am still in the beginning of fixing the many issues I have made but it is getting somewhere. 

Here is how I have laid out the code 

1. Input 1 - I first want to be prompted to "select a 2D polyline/polygon" and once the polyline/polygon has been selected I want to store the X and y vertices in a list called "2DpolyXY".

2. input 2 - I then want to select 3 blocks. With the three blocks (Each block will have it's own unique name) that have been selected I need to select all identical blocks within the 2D polyline. I want to use the select similar command to select all the other similar block references in the drawing. This is not ideal but for some reason if I use the block names to try and find all the other blocks with the same name in the 2D polyline it returns nothing. I think it is to do with these blocks being generated by Pvcase.

3. Process 1 - I want to create a new layer called "Block Copy" and copy only the blocks within the 2D polyline.

4. Process 2 - with the blocks that have now been copied into "block Copy" layer I want to explode the blocks.

5. Process 3 - once exploded I want it to filter to find all the 3D polylines in the layer "block copy" and get the x and y coordinates of these 3d polylines and store then in a list called "3DpolyXY"

6. Calculation 1 - with list 2DpolyXY and 3DpolyXY - I want to see if any coordinates from the 3DpolyXY are closer than 3m to the 2DpolyXY coordinates. If there are coordinates where the distance between each coordinate is less than 3m then I want the 3DpolyXY coordinates to be stored in a new list called "3mandless". You can now ignore the coordinates that were added to the list "3mandless" in calculation 1 from being used in calculations 2 and 3.

7. Calculation 2 - I want to see form the resulting line between 2 3DpolyXY coordinates and if there are any 2DpolyXY coordinates that are closer than 3m to this line. If there is a point where the line segment is closer than 3m to the 2DpolyXY coordinate then I want both 3DpolyXY coordinates being stored in the list "3mandless". You can now ignore the coordinates that were added to the list "3mandless" in calculation 1 and 2 from being used in calculations 3.

8.Calculation 3 - I want to see form the resulting line between 2 2DpolyXY coordinates and if there are any 3DpolyXY coordinates that are closer than 3m to this line. If there is a point where the line segment is closer than 3m to the 3DpolyXY coordinate then I want both 3DpolyXY coordinates being stored in the list "3mandless".

9. I then want to draw a circles around all the coordinates in the "3mandless" list and this circle should be in a layer called "Red3m"

I should probably add another step to delete everything in "block copy" at the end but I haven't got that far yet 

 

For the calculation and processing steps I used online sources and amended them to match my code.

(defun c:Check-Distance (/ 2DpolyXY MyPoly ss-three-blocks ss-identical-blocks inside-blocks 3DpolyXY 3mandless dist pt1 pt2 Ax Ay Bx By Px Py lenAB u)
    
    ; 1. Select a 2D polyline/polygon.
    (if (setq MyPoly (ssname (ssget "_+.:E:S" '((0 . "*POLYLINE"))) 0))
        (progn
            (setq MyPoly (entget MyPoly) 2DpolyXY nil)
            (foreach sublist MyPoly
                (if (= (car sublist) 10)
                    (setq 2DpolyXY (append 2DpolyXY (list (cdr sublist))))
                )
            )
            (princ 2DpolyXY)
        )
        (princ "No polyline found in the drawing.")
    )

    ; 2. Selection of three blocks and using select similar.
    (prompt "\nSelect three reference blocks: ")
    (if (setq ss-three-blocks (ssget '((0 . "INSERT"))))
        (progn
            (if (= (sslength ss-three-blocks) 3)
                (progn
                    (command "_.selectsimilar" ss-three-blocks "")
                    (setq ss-identical-blocks (ssget "_P"))

                    ; Print entity names from the selection set of stage 2
                    (princ "\nEntities from Stage 2: ")
                
                    (setq n 0)
                    (while (setq entity (ssname ss-identical-blocks n))
                        (princ entity)
                        (setq n (+ n 1))
                    )
                )
                (progn
                    (princ "\nYou didn't select exactly 3 blocks. Exiting function.")
                    (exit)
                )
            )
        )
    )

    ; 2.1. Filter blocks that are inside the polygon.
    (setq inside-blocks
        (vl-remove-if-not
            '(lambda (blk)
                (let ((pt (cdr (assoc 10 (entget blk))))
                      (count 0) px py p1 p2)
                    (setq px (car pt) py (cadr pt))
                    (foreach p1 2DpolyXY
                        (setq p2 (cadr (member p1 2DpolyXY)))
                        (if (or (and (<= (cadr p1) py) (< py (cadr p2)))
                                (and (<= (cadr p2) py) (< py (cadr p1))))
                            (if (< px 
                                  (/ (+ (* (car p1) (- (cadr p2) (cadr p1))) 
                                         (* (car p2) (- (cadr p1) py))) 
                                     (- (cadr p2) (cadr p1))))
                                (setq count (+ count 1))
                            )
                        )
                    )
                    (= (rem count 2) 1)
                )
            )
            (mapcar 'ssname ss-identical-blocks)
        )
    )

    ; Print entity names from the filtered set of stage 2.1
    (princ "\nEntities inside the polygon (Stage 2.1): ")
    (if inside-blocks
        (foreach entity inside-blocks
            (princ (strcat "\n" entity))
        )
        (princ "\nNo entities found inside the polygon.")
    )

            ; 2.3. Continue if blocks inside the polygon are found.
            (if inside-blocks
                (progn
                    ; 3. Process 1: Create a new layer "Block Copy" and set it current.
                    (if (not (tblsearch "LAYER" "Block Copy")) 
                        (command "-LAYER" "M" "Block Copy" "")
                    )
                    (setvar "CLAYER" "Block Copy")

                    ; Copy the blocks to the "Block Copy" layer.
                    (foreach blk inside-blocks
                        (entmod (append (entget blk) (list (cons 8 "Block Copy"))))
                    )

                    ; 4. Process 2: Explode the blocks in the "Block Copy" layer.
                    (command "EXPLODE" inside-blocks "")

                    ; 5. Process 3: Filter 3D polylines and get only the X and Y coordinates.
                    (setq 3DpolyXY (list))
                    (foreach ent (mapcar 'cadr (ssnamex (ssget '((0 . "POLYLINE") (8 . "Block Copy")))))
                        (setq 3DpolyXY 
                            (append 3DpolyXY 
                                    (mapcar '(lambda (e) 
                                              (list (car (cdr (assoc 10 e))) (cadr (cdr (assoc 10 e)))))
                                            (entget ent)))
                        )
                    )

                    ; 6. Calculation 1: Check distance between 2D and 3D polylines.
                    (setq 3mandless
                          (vl-remove-if-not
                           '(lambda (pt)
                              (vl-some
                               '(lambda (chkpt) (< (distance pt chkpt) 3.0))
                               2DpolyXY
                              )
                           )
                           3DpolyXY
                          )
                    )

                    ; Update lists to exclude points from 3mandless.
                    (setq 2DpolyXY (vl-remove-if '(lambda (pt) (member pt 3mandless)) 2DpolyXY))
                    (setq 3DpolyXY (vl-remove-if '(lambda (pt) (member pt 3mandless)) 3DpolyXY))

                    ; 7. Calculation 2: Check distance from line segments of 3D polyline to 2D polyline.
                    (setq dist nil)
                    (foreach pt1 2DpolyXY
                        (foreach pt2 3DpolyXY
                            (setq Ax (car pt1) Ay (cadr pt1) Bx (car pt2) By (cadr pt2))
                            (foreach pt 3DpolyXY
                                (setq Px (car pt) Py (cadr pt))
                                (setq lenAB (sqrt ((- Bx Ax) ** 2.0) + ((- By Ay) ** 2.0)))
                                (setq u (/ ((Px - Ax) * (Bx - Ax) + (Py - Ay) * (By - Ay)) (lenAB ** 2.0)))
                                (if (or (< u 0.0) (> u 1.0))
                                    (setq dist (append dist (min (distance pt1 pt) (distance pt2 pt))))
                                    (setq dist 
                                          (append dist (sqrt ((- Px (Ax + u * (Bx - Ax))) ** 2.0) + 
                                                      ((- Py (Ay + u * (By - Ay))) ** 2.0))))
                                )
                            )
                        )
                    )
                    ; 8. Calculation 3: Check distance from line segments of 2D polyline to 3D points.
                    (foreach pt1 2DpolyXY
                        (foreach pt2 3DpolyXY
                            (let* ((Ax (car pt1))
                                   (Ay (cadr pt1))
                                   (Bx (car (cadr (member pt1 2DpolyXY))))
                                   (By (cadr (cadr (member pt1 2DpolyXY))))
                                   (Px (car pt2))
                                   (Py (cadr pt2))
                                   (lenAB (+ (* (- Bx Ax) (- Bx Ax)) (* (- By Ay) (- By Ay))))
                                   (u (+ (* (- Px Ax) (- Bx Ax)) (* (- Py Ay) (- By Ay)))))
                                (setq u (/ u lenAB))
                                (if (or (< u 0.0) (> u 1.0))
                                    (setq dist (min (distance pt1 pt2) (distance pt1 (list Bx By))))
                                    (setq dist (distance pt1 (list (+ Ax (* u (- Bx Ax))) (+ Ay (* u (- By Ay))))))
                                )
                                (if (< dist 3.0)
                                    (setq 3mandless (cons pt2 3mandless))
                                )
                            )
                        )
                    )
                    
                    ; 9. Draw circles around all the points in the 3mandless list.
                    ; Create a layer "Red3m" and set it current.
                    (if (not (tblsearch "LAYER" "Red3m"))
                        (command "-LAYER" "M" "Red3m" "C" "1" "")
                    )
                    (setvar "CLAYER" "Red3m")
                    (foreach pt 3mandless
                        (command "CIRCLE" pt 3.0)
                    )

                    ; 10. Concluding Remarks
                    (if (not 3mandless)
                        (princ "\nAll points from the exploded 3D polylines are more than 3 units away from the 2D polyline.")
                        (progn
                            (princ "\nThe following points from the exploded 3D polylines are less than or equal to 3 units away from the 2D polyline:")
                            (princ "\n")
                            (princ 3mandless)
                        )
                    )
                )
                (princ "\nNo blocks inside the polygon.")
            )
        (princ) ; To clear the command line and return to AutoCAD command prompt.
    )

 

The problem that I am having is the selection of the blocks. Because these blocks are generated by PVcase the block names are "3P54@18DEG F FX ID1 PVBlock" "3P9@18DEG F FX ID1 PVBlock" "3P27@18DEG F FX ID1 PVBlock" so I have tried using the selection method to select blocks with the same name but it always returns nothing at the end of it. Not sure why that is so I tried another method select similar command. The problem with this is in this line of code

"(command "_.selectsimilar" ss-three-blocks "")

                    (setq ss-identical-blocks (ssget "_P"))"

because instead of setting "ss-identical-blocks" to selection of the select similar command it is selecting the three block selected in the first place.

I was wondering if you can help me solve this? I know this "(ssget "_P")" isn't great but I dont know if I have another option. Let me know if you have some smart ideas?

 

many thanks in advance!

Edited by CFORD
Link to comment
Share on other sites

Some suggestions

 

"select a 2D polyline/polygon" (if (setq MyPoly (ssname (ssget '((0 . "LWPOLYLINE"))) 0)) this will make a selection set of 2d Poly lines.

get points list (if plent (setq co-ord (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget (car plent))))))

 

select 3 blocks (setq ss-three-blocks (ssget '((0 . "INSERT") )))  ok you can use a While counting the blocks each time you pick a block is it one of the 3 desired block names, if yes use SSADD to add to ss-three-block. Once found remove that name  from block check list.

 

I think it a case of take each step and improve on that, rather than trying to do down to step 9 in one go.

 

For any realistic answer need a sample dwg.

Edited by BIGAL
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...