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

autolisp pFace

13 REPLIES 13
SOLVED
Reply
Message 1 of 14
eharrisonTZS2M
938 Views, 13 Replies

autolisp pFace

PLEASE HELP ME WRITE A AUTOLISP SCRIPT THAT DOES THE FOLLOWING:

i normally can create simple enough lisp files, but i'm not sure how to use the PFACE command, select my vertices, then have autocad fill out the faces for me based on my mathematical pattern. to determine the total number of faces that the polyfacemesh will have, one would take the total number of vertices and divide by 2. each face will always have 4 vertices for this autolisp.

(defun c:pfacetest1 ()
; Prompt user to select vertices
(command "pface")
)

for example i have a rectangle at with a Z height of 0. i have the same shape at the z height of 1.25, directly above the previous shape... i type in the command PFACE, then autocad asks me for my vertices. i manually select them so there is a specific order. the higher rectangle is where i start the selection process and the lower rectangle is the next. so the top rectangle is vertices 1,3,5,7 and the bottom is 2,4,6,8... after i'm done, selecting all my vertices, i will hit enter on my keyboard. autocad then asks for the information for face 1, vertex, 1...i go through the process to create face 1 in the vertex order of...

face 1: 1,2,4,3
face 2: 3,4,6,5
face 3: 5,6,8,7
face 4: 7,8,2,1

on the last face, the final two numbers will always be 2, then 1.

in one particular case, i have 112 vertices...

i'd like for my autolisp file to be able to be used with any amount of vertices with a minimum of 6 and then utilize this pattern. 


"shining the @Kent1Cooper signal"

thanks ahead of time to any and all responses!


13 REPLIES 13
Message 2 of 14

update: i got a very basic version of it working. the downside here is that this is based on a rectangle/square shape. I would need to update this lisp to work with my new shape every time, thus having to know the total number of vertices and faces ahead of time.

I'll keep working on it for now, but any help in the meantime would be greatly appreciated. 

(defun c:pfacetest1 ()

(setq a1 (getpoint "\nEnter 1st Vertex : "))
(setq a2 (getpoint "\nEnter 2nd Vertex : "))
(setq a3 (getpoint "\nEnter 3rd Vertex : "))
(setq a4 (getpoint "\nEnter 4th Vertex : "))
(setq a5 (getpoint "\nEnter 5th Vertex : "))
(setq a6 (getpoint "\nEnter 6th Vertex : "))
(setq a7 (getpoint "\nEnter 7th Vertex : "))
(setq a8 (getpoint "\nEnter 8th Vertex : "))

(command "pface" a1 a2 a3 a4 a5 a6 a7 a8 ""
1 2 4 3 ""
3 4 6 5 ""
5 6 8 7 ""
7 8 2 1 "" "")
)

Message 3 of 14

update 2:
the following section allows me to select all my vertex points manually, then allow me to hit enter when i'm done.

(setq vertices '()) ; Initialize an empty list to store vertices
(setq vertexIndex 1) ; Initialize vertex index
(setq vertex (getpoint (strcat "\nEnter Vertex " (itoa vertexIndex) " (Press ENTER to finish) : "))) ; Prompt for the first vertex
(while vertex ; Loop until the user presses ENTER
(setq vertices (cons vertex vertices)) ; Add the vertex to the list
(setq vertexIndex (1+ vertexIndex)) ; Increment vertex index
(setq vertex (getpoint (strcat "\nEnter Vertex " (itoa vertexIndex) " (Press ENTER to finish) : "))) ; Prompt for the next vertex
)

now i need to modify my second half of my original code. long story short is, i'm trying to create a "outside band" effect with the polyfacemesh. so i'd need to have this half look at the first half for the total number of vertex, then divide by two, and probably use some "if, and, or" statements below to know when it needs to stop making faces.
(command "pface" a1 a2 a3 a4 a5 a6 a7 a8 ""
1 2 4 3 ""
3 4 6 5 ""
5 6 8 7 ""
7 8 2 1 "" "")
)

Message 4 of 14

update 3: i added a portion to tell me how many vertices and faces the lisp has collected. so far, so good. 

(defun c:pfacetest1 ()
;Collect vertices
(setq vertices '()) ; Initialize an empty list to store vertices
(setq vertexIndex 1) ; Initialize vertex index
(setq vertex (getpoint (strcat "\nEnter Vertex " (itoa vertexIndex) " (Collect All Vertices, starting at top then go down, up down, up down, etc. Press ENTER to finish) : "))) ; Prompt for the first vertex
(while vertex ; Loop until the user presses ENTER
(setq vertices (cons vertex vertices)) ; Add the vertex to the list
(setq vertexIndex (1+ vertexIndex)) ; Increment vertex index
(setq vertex (getpoint (strcat "\nEnter Vertex " (itoa vertexIndex) " (Press ENTER to finish) : "))) ; Prompt for the next vertex
)

; Determine the number of faces based on the total number of vertices
(setq numVertices (length vertices))
(setq numFaces (/ numVertices 2))

; Output the number of faces and vertices to the command prompt
(princ (strcat "\nTotal Vertices: " (itoa numVertices)))
(princ (strcat "\nTotal Faces: " (itoa numFaces)))

);end



Message 5 of 14

as if this doesn't get any harder...i found out that PFACE command can't utilize and load a list. so in update 3, i had a list of vertices called 'vertices'.
well, i can't use (command "pface" vertices) in my lisp... i apparently have to extract each point via..
(command "pface" (nth 1 vertices) (nth 2 vertices) (nth 3 vertices) (nth 4 vertices)
(nth 5 vertices) (nth 6 vertices) (nth 7 vertices) (nth 8 vertices) and so on and so on if i need to have it there...

well i thought was getting somewhere until...

i tried it on a square shape.

autocad returned with ...

Command: PFACETEST1
Enter Vertex 1 (Collect All Vertices, starting at top then go down, up down, up down, etc. Press ENTER to finish) :
Enter Vertex 2 (Press ENTER to finish) :
Enter Vertex 3 (Press ENTER to finish) :
Enter Vertex 4 (Press ENTER to finish) :
Enter Vertex 5 (Press ENTER to finish) :
Enter Vertex 6 (Press ENTER to finish) :
Enter Vertex 7 (Press ENTER to finish) :
Enter Vertex 8 (Press ENTER to finish) :
Enter Vertex 9 (Press ENTER to finish) :
Total Vertices: 8
Total Faces: 4
Vertices List:
Vertex: 10.000, 10.000, 1.250
Vertex: 10.000, 10.000, 0.000
Vertex: 10.000, 0.000, 1.250
Vertex: 10.000, 0.000, 0.000
Vertex: 0.000, 0.000, 1.250
Vertex: 0.000, 0.000, 0.000
Vertex: 0.000, 10.000, 1.250
Vertex: 0.000, 10.000, 0.000
Command: pface (from here the vertices were listed via the 'nth' stuff in the lisp)
Specify location for vertex 1:
Specify location for vertex 2 or <define faces>:
Specify location for vertex 3 or <define faces>:
Specify location for vertex 4 or <define faces>:
Specify location for vertex 5 or <define faces>:
Specify location for vertex 6 or <define faces>:
Specify location for vertex 7 or <define faces>:
Specify location for vertex 8 or <define faces>:
Command: nil

so it extracted all the vertices but it wouldn't move onto the "face 1, vertex 1" questions...it just tries to move onto a new command!

so i look back at my more simple autolisp in the first update above...what is it about that one that allows me to continue but i can't with my current code??

i don't want to limit or have to alter the autolisp everytime i have more than 8 vertices on my shape, so i thought i was going somewhere in update 3, but when i found out pface rejects lists and wants me to extract each point, i do that, but it won't continue on with it's normal questions, it just stops!

what am i doing wrong?

i don't undersand the 'if and or' functions, otherwise i'd attempt to write the lisp to allow me to have an infinite amount of 'getpoint' features.

to be honest, i got to this point because i'm trying to learn autolisp as quickly as possible, so i'm working with an AI to help me create the code and then i'm debugging it if i have an issue...

Message 6 of 14
Sea-Haven
in reply to: eharrisonTZS2M

I have used pface but as a single face. I have a sneaky feeling that wrote a script to do this task as you suggested can not invoke (nth x lst)

 

Yep found it.

 

(setq fo (open "multi.scr" "w"))
(write-line "pface" fo)
followed by correct order of values for pface
included pick points

(close fo)
(setvar "clayer" roof--2)
(command "script" "multi")

 

 

Message 7 of 14
eharrisonTZS2M
in reply to: Sea-Haven

thanks @Sea-Haven,

So from what I’m gathering in your script/lisp is…

1. (setq fo (open "multi.scr" "w")): It opens a file named “multi.scr” in write mode and assigns the file handle to the variable fo.
2. (write-line "pface" fo): It writes the command “pface” to the file.
3. The code then writes the correct order of values for the pface command to the file. These values likely represent the vertices or coordinates for creating a Polyface mesh.
4. It then includes pick points in the file, likely specifying points to be selected during the execution of the script.
5. (close fo): It closes the file handle.
6. (setvar "clayer" roof--2): It sets the current layer to “roof–2”.
7. (command "script" "multi"): It executes the script file “multi.scr” in AutoCAD, causing the commands written to the file to be executed in the AutoCAD environment.

 

what I don’t know is will “multi.scr” always start as blank, and be utilized everytime I would run my lisp? Or would a new .scr file need to be created each time I run the lisp? I haven’t used .scr files in AutoCAD before.

 

i also can’t test anything at this point until Monday when I’m back in the office.

Message 8 of 14
Sea-Haven
in reply to: eharrisonTZS2M

When you open a file like MULTI.scr you make sure it includes a full path that way it only ever exists once, you can if you want as part of the script delete the file as last step.

 

When you use "W" write, it erases the old file so is only ever the current file. 

(setq fo (open "D:\\acadtemp\\multi.scr" "w"))

You are correct the full code has a (While where you pick points. 

Message 9 of 14
eharrisonTZS2M
in reply to: Sea-Haven

@Sea-Haven 

So in your lisp….

 

“followed by correct order of values for pface included pick points”

 

 

How would I utilize my lisp (that allows an infinite amount of vertices) and pull each vertex, assign each vertex a variable? 

then, depending on how many vertices I have, automatically make a list that knows when to stop?

Message 10 of 14
Sea-Haven
in reply to: eharrisonTZS2M

You need to save the points into a list so you know exactly that how many points make up the pface, then look at the pface command and write the file with correct matching steps. 

 

A 4 point pface sequence of sorts.

 

 

: PFACE
Position of mesh vertex 1: XY
Position of mesh vertex 2/<Enter to define faces>: XY
Position of mesh vertex 3/<Enter to define faces>: Xy
Position of mesh vertex 4/<Enter to define faces>: XY
Position of mesh vertex 5/<Enter to define faces>: Enter in lisp (command "")
Face 1, Vertex 1: [Color/Layer] <Exit>:1
Face 1, Vertex 2: [Color/Layer] <Define next face>:2
Face 1, Vertex 3: [Color/Layer] <Define next face>:3
Face 1, Vertex 4: [Color/Layer] <Define next face>:4
Face 1, Vertex 5: [Color/Layer] <Define next face>:Enter in lisp (command "")
Face 2, Vertex 1: [Color/Layer] <Exit>: Enter in lisp (command "")

 

 

A pface sequence use a foreach for the XYZ points and a repeat for the 1 2 3 4 then can add next pface pts and vertices.  So the list of points can be a list of lists ((list1 points)(list2 points)(list3 points)) where the (list points) may have anywhere from say 3 to say 8 items.

 

Script

 

pface
10.000,10.000,1.250
10.000,10.000,0.000
10.000,0.000,1.250
10.000,0.000,0.000
0.000,0.000,1.250
0.000,0.000,0.000
0.000,10.000,1.250
0.000,10.000,0.000

1
2
3
4
5
6
7
8
(command "")
(command "")

 

Message 11 of 14

@Sea-Haven 
THANKS!
(this post is updated per the latest comment. updated rtos 2 3 sections to be rtos 2 8 for more accurate vertex snap locations)
you set me on the right track, but i had some things to work through. I had to change some Registry settings for the .scr file to work.
i'm sure this thing could be compressed some how, but i'm pretty excited it works, so i left it as is.
here is the code...i also attached the .lsp file, and a .jpg file showing how to start the process. the end result is a "complete" polyfacemesh around the "edge" and another polyfacemesh on the top and bottom, selectable as one cohesive unit. when you move each section, you'll see the original polylines you start with. i'll probably add more to the code to delete these original polylines at a later time. that was a rough few days getting through this.

(defun c:pfacetest1 ();SPECIAL THANKS TO @SEA-HAVEN on the autodesk forums. @eharrisonTZS2M - EDH 5/6/24
;Collect vertices
(setq vertices '()) ; Initialize an empty list to store vertices
(setq vertexIndex 1) ; Initialize vertex index
(setq vertex (getpoint (strcat "\nEnter Vertex " (itoa vertexIndex) " (Collect All Vertices, starting at top then go down, up down, up down, etc. Press ENTER to finish) : "))) ; Prompt for the first vertex
(while vertex ; Loop until the user presses ENTER
(setq vertices (cons vertex vertices)) ; Add the vertex to the list
(setq vertexIndex (1+ vertexIndex)) ; Increment vertex index
(setq vertex (getpoint (strcat "\nEnter Vertex " (itoa vertexIndex) " (Press ENTER to finish) : "))) ; Prompt for the next vertex
)


;START SECTION---------------------------------------------------------------------------------------------------

; Ensure vertices are in the correct order (top-left, top-right, bottom-right, bottom-left)
(setq vertices (reverse vertices))

;END SECTION------------------------------------------------------------------------------------------------


; Determine the number of faces based on the total number of vertices
(setq numVertices (length vertices))
(setq numFaces (/ numVertices 2))

; Output the number of faces and vertices to the command prompt
(princ (strcat "\nTotal Vertices: " (itoa numVertices)))
(princ (strcat "\nTotal Faces: " (itoa numFaces)))
(princ "\n") ; Add a newline character

 

;START SECTION---------------------------------------------------------------------------------------------------

; Print vertices list
(princ "\nVertices List:")
(foreach vert vertices
(princ (strcat "\nVertex: " (rtos (car vert) 2 8) ", " (rtos (cadr vert) 2 8) ", " (rtos (caddr vert) 2 8))))

;END SECTION---------------------------------------------------------------------------------------------------

;(princ "\nCommand: ") ; Add a newline character


;START SECTION-------------------------------------------------------------------------------------------------

(setq fo (open "C:\\LISP FOR POLYFACE MESH\\AUTOPFACE.scr" "w"))
(if fo
(progn
(write-line "pface" fo) ; Write the pface command
; Iterate over vertices list and write each vertex coordinates to the .scr file
(foreach vert vertices
(write-line (strcat
(rtos (car vert) 2 8) ","
(rtos (cadr vert) 2 8) ","
(rtos (caddr vert) 2 8)) fo))
(write-line "" fo) ; Add an empty line

;END SECTION---------------------------------------------------------------------------------------------------

;NEW WRITE SCR FILE FACES LIST-------------------------------------------------------------------------------------------------

; Write faces to the .scr file
(setq vertexIndex 1)
(setq counter 0)
(setq lastVertexIndex (- numVertices 1)) ; Index of the last vertex

(while (<= vertexIndex numVertices)
(write-line (itoa vertexIndex) fo) ; Write current vertex index
(write-line (itoa (+ vertexIndex 1)) fo) ; Write next vertex index
(write-line (itoa (+ vertexIndex 3)) fo) ; Write the vertex index skipping one
(write-line (itoa (+ vertexIndex 2)) fo) ; Write the vertex index skipping one and two
(setq vertexIndex (+ vertexIndex 2)) ; Increment by 2 for the next face
(setq counter (1+ counter)) ; Increment counter

; Check if this is the last face
(if (= vertexIndex lastVertexIndex) ; Check if this is the last vertex
(progn
; Write the last face indices
(write-line "" fo) ; Add a newline between faces
(write-line (itoa (- numVertices 1)) fo)
(write-line (itoa numVertices) fo)
; Write '2' and '1' as the last two numbers
(write-line "2" fo)
(write-line "1" fo)
; Exit the loop as we've completed writing the faces
(setq vertexIndex (1+ numVertices)) ; Set vertexIndex greater than numVertices to exit the loop
)
(if (= counter 4) ; Check if counter reaches 4
(progn
(write-line "" fo) ; Add a newline after every 4 numbers
(setq counter 0) ; Reset counter
)
(write-line "" fo) ; Add a newline between faces
)
)
)

 

;START SECTION---------------------------------------------------------------------------------------------------------

(write-line "" fo)
(write-line "" fo)

;END SECTION------------------------------------------------------------------------------------------------------------


;START TOP & BOTTOM SECTION---------------------------------------------------------------------------------------------

(write-line "pface" fo) ; Write the pface command
; Iterate over vertices list and write each vertex coordinates to the .scr file
(foreach vert vertices
(write-line (strcat
(rtos (car vert) 2 8) ","
(rtos (cadr vert) 2 8) ","
(rtos (caddr vert) 2 8)) fo))
(write-line "" fo) ; Add an empty line

; Write faces for the odd-numbered vertices
(setq vertexIndex -1) ; Start with the first vertex
(while (<= vertexIndex numVertices)
(write-line (itoa vertexIndex) fo)
(setq vertexIndex (+ vertexIndex 2)) ; Move to the next odd-numbered vertex
)

(write-line "" fo) ; Add a newline between the two sets of faces

; Write faces for the even-numbered vertices
(setq vertexIndex 0) ; Start with the second vertex for the even-numbered vertices
(while (< vertexIndex numVertices) ; Change condition to stop before reaching the last vertex
(setq vertexIndex (+ vertexIndex 2)) ; Move to the next even-numbered vertex
(write-line (itoa vertexIndex) fo)
)


;END TOP & BOTTOM SECTION---------------------------------------------------------------------------------------------

;START SECTION---------------------------------------------------------------------------------------------------------

(write-line "" fo)
(write-line "" fo)

;END SECTION------------------------------------------------------------------------------------------------------------

;START SECTION---------------------------------------------------------------------------------------------------------
(close fo)
(setvar "clayer" "0")
(command "script" "C:\\LISP FOR POLYFACE MESH\\AUTOPFACE.scr")
)
(princ "\nFailed to open file for writing.")
)
;END SECTION------------------------------------------------------------------------------------------------------------

;END ALL CODE-----------------------------------------------------------------------------------------------------------
);end

 

Message 12 of 14

update: 

i changed all the (rtos (car vert) 2 3) "," in the above code to be (rtos (car vert) 2 8) ",". i did this for all places that utilized rtos. since it was all automated, the ended result of pfaces did not go exactly where i originally selected vs if the pface command was manually used...i'm sure there is probably another way to get a more accurate location, but i don't have any more time to spend on this code right now.

eventually, the end goal is to use the FindVertices.lsp (attached). it is a 3D version of the polyvert.lsp (attached). FindVertices references the polyvert inside of it. FindVertices.lsp allows one to select the objects you want and it gives a list of vertices. it could probably be simplified, but "if it ain't broke, don't fix it", though i know simplifying the code would speed up the process...

this was my original goal, however, i was finding it difficult to quickly figure out how to list all the vertices in a particular "up down up down up down" or "top bottom top bottom to bottom" order. 

 

to get it to function how i'd like, i think i'll have to have it sort the vertices starting at 0,0,1.25, then 0,0,0, then have it incorporate a version of a "clockwise.lisp" (https://www.lee-mac.com/clockwisep.html) to list all the vertices in a clockwise order starting at the 0,0,1.25 point, then 0,0,0, then the next X,Y,1.25, followed by X,Y,0, and so on and so on...this would entirely automate my process instead of me having to manually select each vertex i want to utilize. 

Message 13 of 14
Sea-Haven
in reply to: eharrisonTZS2M

I have this by DEXUS. Rotates co-ordinates so start at selected point.

 

; BY Dexus rotates points of a pline

(defun rotate-rectange (lst / corner)
  (setq corner ; find left most corner with a sort
    (car
      (vl-sort lst
        (function
          (lambda (a b)
            (if (equal (car a) (car b) 1e-4)
              (< (cadr a) (cadr b))
              (< (car a) (car b))
            )
          )
        )
      )
    )
  )
  (while (/= (car lst) corner) ; rotate until corner is the first item
    (setq lst (append (cdr lst) (list (car lst))))
  )
  lst ; return lst
)

 

 

Message 14 of 14
eharrisonTZS2M
in reply to: Sea-Haven

thanks @Sea-Haven i'll give it a shot!

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

Post to forums  

Forma Design Contest


AutoCAD Beta