automationautodeskautodesk-designautomation

AutoLISP batch plot: Want to output each frame as a PDF page, but entire drawing is repeated


I’m trying to create a batch plot in AutoLISP. My DWG contains 6 drawing frames, each defined by a LWPOLYLINE.

I want to generate a single PDF with 6 pages, where each page corresponds to one frame (i.e., each LWPOLYLINE).

The script runs without errors and creates a PDF, but the result is not what I expect. Instead of 6 pages with different frame views, I get a 116-page PDF where every page looks almost the same — the full drawing is printed repeatedly.

Here’s the code I’m using:

(defun c:batchplot ()
  (vl-load-com)
  (prompt "\n🚀: batchplot start")

  ;; LWPOLYLINE
   (setq ss (ssget "_X" '((0 . "LWPOLYLINE"))))
  ;; (setq ss (ssget "_X" '((0 . "LWPOLYLINE") (8 . "TITLEBLOCK") (70 . 1))))

  (if ss
    (progn
      (setq count 0)

      (repeat (sslength ss)
        (setq ent (ssname ss count))
        (setq entObj (vlax-ename->vla-object ent))

        (prompt (strcat "\n✅ #" (itoa count) " process"))

        ;; minPt, maxPt
        (setq minPt (vlax-make-safearray vlax-vbDouble '(0 . 2)))
        (setq maxPt (vlax-make-safearray vlax-vbDouble '(0 . 2)))

        ;; GetBoundingBox start
        (setq bboxResult (vl-catch-all-apply
          '(lambda ()
             (vla-GetBoundingBox entObj 'minPt 'maxPt)
           )
        ))

        (if (not (vl-catch-all-error-p bboxResult))
          (progn
            (setq pt1 (vlax-safearray->list minPt))
            (setq pt2 (vlax-safearray->list maxPt))

            (setq centerX (/ (+ (car pt1) (car pt2)) 2.0))
            (setq centerY (/ (+ (cadr pt1) (cadr pt2)) 2.0))
            (setq center (list centerX centerY))

            ;; zoom
            (command "_.zoom" "_object" ent)
            (command "")

           
            (setq outFile (strcat "C:\\Users\\Administrator\\Documents\\output-" (itoa count) ".pdf"))

            ;; plot
            (command "-plot")
            (command "yes")
            (command "model")
            (command "DWG To PDF.pc3")
            (command "ISO_full_bleed_A3_(420.00_x_297.00_MM)")
            (command "millimeters")
            (command "portrait")
            (command "no")
            (command "extents")
            (command "fit")
            (command "center")
            (command "yes")
            (command "monochrome.ctb")
            (command "yes")
            (command "as displayed")
            (command outFile)
            (command "no")
            (command "yes")

            (prompt (strcat "\n📄 complete: " outFile))
          )
          (prompt (strcat "\n⚠️ #" (itoa count) " - GetBoundingBox x"))
        )

        (setq count (1+ count))
      )

      (prompt (strcat "\n🎉 총 " (itoa count) "count"))
    )
    (prompt "\n❌ no LWPOLYLINE")
  )

  (princ)
)

(c:batchplot)
•   There are 6 LWPOLYLINE frames in the drawing
•   I want one PDF page per frame
•   But the result is a 116-page PDF where every page seems to repeat the same full view

•   Used zoom _object on each polyline before plotting
•   Tried adding REGEN to refresh the view
•   Used -plot with various settings: extents, fit, center, as displayed
•   Running from model space
•   Loop iterates correctly over the polylines

Expected Output

How can I make sure that -plot actually uses the current object or bounding box so that each page of the PDF corresponds to a different frame?

Right now it seems like the plot range is not updating per frame. Is there a reliable way to update the plot window dynamically for each object?


Solution

  • You don't need these, the Get-BoundingBox API will create a safe array for you and populate.

    (setq minPt (vlax-make-safearray vlax-vbDouble '(0 . 2)))
    (setq maxPt (vlax-make-safearray vlax-vbDouble '(0 . 2)))
    

    Instead of this

    (command "_.zoom" "_object" ent)
    

    I would recommend get all polyframes, a good practice would be to keep all the PLINES on same layer like "FRAME", would be easier for you get all these enities, and use Window to zoom.

    (defun c:PlotFrames ( / ss i ent ename minpt maxpt)
      (setq dwgPath (getvar "DWGPREFIX"))
      (setq ss (ssget "X" '((0 . "LWPOLYLINE") (8 . "Frame")))) ; Select all polylines on 'Frame' layer
      (if ss
        (progn
          (setq i 0)
          (setq total (sslength ss))
          (repeat total
            (setq ename (ssname ss i))
            (setq ent (entget ename))
            (vla-getboundingbox
              (vlax-ename->vla-object ename)
              'minpt
              'maxpt
            )
            (setq minpt (vlax-safearray->list minpt))
            (setq maxpt (vlax-safearray->list maxpt))
            ;; Zoom to window
            (command "_.zoom" "W" minpt maxpt)
            (setq outFile (strcat dwgPath "Frame-" (itoa (1+ i)) "-of-" (itoa total) ".pdf"))
            ;; Plot window
            (command "_.plot" "Y" "Model" "DWG To PDF.pc3" "ANSI A (11.00 x 8.50 Inches)" "Inches" "Portrait" "No" "Window" minpt maxpt "Fit" "Center" "Yes" "acad.stb" "No" "As displayed" outFile "No" "Yes")
            (setq i (1+ i))
          )
        )
        (princ "\nNo frames found on layer 'Frame'.")
      )
      (princ)
    )
    

    Here is Test drawing used with LISP code.

    https://github.com/MadhukarMoogala/AnyShareable/blob/main/Plotframes_test.dwg