;;; --------------------------------------------------------------------- ;;; FACE2PLN-bgol.lsp ;;; Command: F2PL ;;; ;;; PURPOSE ;;; Converts selected 3DFACE entities into equivalent closed 3D ;;; polylines tracing the same vertices/outline. Unlocks area ;;; calculation and other polyline-based tools on triangulated ;;; surface data (a TIN of 3D faces), which the native AREA command ;;; cannot operate on directly. ;;; ;;; USAGE ;;; 1. Load this file (APPLOAD or drag-drop onto the drawing window). ;;; 2. Type F2PL at the command line and press Enter. ;;; 3. Select one or more 3DFACE entities. ;;; 4. Each 3DFACE is converted into an equivalent closed 3D ;;; polyline on layer "BGOL-F2PL". The original 3DFACE entities ;;; are left untouched. ;;; ;;; NOTES ;;; - This is an original, independently written implementation. ;;; It is INSPIRED by the general idea of 3DFACE-to-polyline ;;; conversion utilities common in CAD/survey drafting ;;; workflows, but the code, command name and file name here are ;;; new and are NOT copied from, nor identical to, any specific ;;; third-party product. ;;; ;;; --------------------------------------------------------------------- ;;; Developed and shared for the CAD community by: BGol Community ;;; Community website: https://bgol.in/ ;;; License: Open-source & free to use, modify, and share for all. ;;; Provided "as is", without warranty of any kind. ;;; --------------------------------------------------------------------- (vl-load-com) (defun BGOL:F2PL-EnsureLayer (lname / ) (if (not (tblsearch "LAYER" lname)) (entmake (list '(0 . "LAYER") '(100 . "AcDbSymbolTableRecord") '(100 . "AcDbLayerTableRecord") (cons 2 lname) '(70 . 0) '(62 . 6) ; magenta '(6 . "Continuous"))) ) ) ;; Build a closed heavy 3D polyline (POLYLINE + VERTEX + SEQEND) through ;; a list of 3D points, skipping consecutive duplicate points. (defun BGOL:F2PL-Make3DPoly (pts lname / uniq p prev) (setq uniq '()) (setq prev nil) (foreach p pts (if (or (not prev) (> (distance p prev) 1e-8)) (setq uniq (append uniq (list p))) ) (setq prev p) ) (if (and (> (length uniq) 2) (< (distance (car uniq) (last uniq)) 1e-8)) (setq uniq (reverse (cdr (reverse uniq)))) ; drop duplicate closing pt ) (if (>= (length uniq) 3) (progn (entmake (list '(0 . "POLYLINE") '(100 . "AcDbEntity") (cons 8 lname) '(100 . "AcDb3dPolyline") '(66 . 1) '(70 . 9) ; 3D polyline + closed '(10 (0.0 0.0 0.0)) ) ) (foreach p uniq (entmake (list '(0 . "VERTEX") '(100 . "AcDbEntity") (cons 8 lname) '(100 . "AcDbVertex") '(100 . "AcDb3dPolylineVertex") (cons 10 p) '(70 . 32) ) ) ) (entmake (list '(0 . "SEQEND") '(100 . "AcDbEntity") (cons 8 lname))) T ) nil ) ) (defun BGOL:F2PL-FaceVerts (edata / p1 p2 p3 p4) (setq p1 (cdr (assoc 10 edata))) (setq p2 (cdr (assoc 11 edata))) (setq p3 (cdr (assoc 12 edata))) (setq p4 (cdr (assoc 13 edata))) (list p1 p2 p3 p4) ) (defun C:F2PL ( / ss n i ename edata pts converted) (BGOL:F2PL-EnsureLayer "BGOL-F2PL") (princ "\nSelect 3DFACE entities to convert: ") (setq ss (ssget '((0 . "3DFACE")))) (if ss (progn (setq n (sslength ss)) (setq converted 0) (setq i 0) (while (< i n) (setq ename (ssname ss i)) (setq edata (entget ename)) (setq pts (BGOL:F2PL-FaceVerts edata)) (if (BGOL:F2PL-Make3DPoly pts "BGOL-F2PL") (setq converted (1+ converted)) ) (setq i (1+ i)) ) (princ (strcat "\nF2PL: " (itoa converted) " of " (itoa n) " 3DFACE(s) converted to 3D polyline (layer BGOL-F2PL).")) ) (princ "\nNo 3DFACE entities selected.") ) (princ) ) (princ "\nFACE2PLN-bgol.lsp loaded. Type F2PL to convert 3DFACE entities to 3D polylines.") (princ "\n -- Free & open-source, courtesy of BGol Community (https://bgol.in/) --") (princ)