Deze LISP‑routine leest een IFC‑bestand, zoekt de IFCMapConversion en IFCIUnit parameters, haalt daar coördinaten, rotatie en eenheid uit, tekent hulpcirkels in de tekening en (in BricsCAD V26) zet automatisch de Project Location. Hieronder staat een duidelijke, stap‑voor‑stap uitleg van wat elk deel van de code doet.
🧩 Overzicht van de functionaliteit
De routine command: ReadIFCMapConversion doet een aantal dingen:
- Zoekt in een IFC‑bestand naar de regel met
IFCMAPCONVERSION→ haalt X, Y, Z, cosinus, sinus en dus de rotatiehoek op. - Zoekt naar de
IFCIUNITregel → bepaalt of het model in metres of millimetres staat. - Tekent drie cirkels rond het MapConversion‑punt → radii: 60 / 660 / 6660 m (of mm‑equivalent).
- Stelt Project Location en Site Location in met rotatie
- Neemt de EPSG code over van de IFC → hierdoor kun je direct een luchtfoto activeren (alleen voor m.)
;;-- BRICSCAD BIM
;;------------------------------------------------------------
;; Utility: convert IFC unit token to meters
;; ------------------------------------------------------------
(defun ifc-unit->meters (u)
(cond
((= (strcase u) ".METRE.") 1.0)
((= (strcase u) ".MILLIMETRE.") 0.001)
((= (strcase u) ".CENTIMETRE.") 0.01)
((= (strcase u) ".KILOMETRE.") 1000.0)
((= (strcase u) ".FOOT.") 0.3048)
((= (strcase u) ".INCH.") 0.0254)
(T 1.0)
)
)
;; ------------------------------------------------------------
;; Utility: convert DWG INSUNITS to meters
;; ------------------------------------------------------------
(defun dwg-units->meters (code)
(cond
((= code 1) 0.0254) ;; Inches
((= code 2) 0.3048) ;; Feet
((= code 4) 0.001) ;; Millimeters
((= code 5) 0.01) ;; Centimeters
((= code 6) 1.0) ;; Meters
(T 1.0)
)
)
;; ------------------------------------------------------------
;; Utility: readable DWG unit text
;; ------------------------------------------------------------
(defun dwg-units->text (code)
(cond
((= code 1) "inch")
((= code 2) "feet")
((= code 4) "mm")
((= code 5) "cm")
((= code 6) "m")
(T "unknown")
)
)
;; ------------------------------------------------------------
;; Compute scale factor IFC → DWG
;; ------------------------------------------------------------
(defun get-scale-factor (ifc-unit-token / ifc-m dwg-m)
(setq ifc-m (ifc-unit->meters ifc-unit-token))
(setq dwg-m (dwg-units->meters (getvar "INSUNITS")))
(/ ifc-m dwg-m)
)
;; ------------------------------------------------------------
;; Utility: notify rotation direction
;; ------------------------------------------------------------
(defun rot-direction (angle)
(cond
((> angle 0) "CCW")
((< angle 0) "CW")
(T "Geen rotatie"))
)
;; ------------------------------------------------------------
;; Utility: split IFC parameter list safely
;; ------------------------------------------------------------
(defun ifc-split-params (s / out level c token)
(setq out '()
token ""
level 0)
(foreach c (vl-string->list s)
(cond
((= c 40) (setq level (1+ level)) (setq token (strcat token (chr c))))
((= c 41) (setq level (1- level)) (setq token (strcat token (chr c))))
((and (= c 44) (= level 0))
(setq out (cons token out))
(setq token ""))
(t (setq token (strcat token (chr c))))))
(reverse (cons token out))
)
;; ------------------------------------------------------------
;; Utility: extract substring between first "(" and last ")"
;; ------------------------------------------------------------
(defun ifc-extract-params (line / a b)
(setq a (vl-string-search "(" line))
(setq b (vl-string-search ")" line a))
(if (and a b)
(substr line (+ a 2) (- b a 1))
)
)
;; ------------------------------------------------------------
;; Utility: extract first EPSG:xxxx from IFCPROJECTEDCRS line
;; ------------------------------------------------------------
(defun ifc-extract-epsg (line / params first)
(if (wcmatch (strcase line) "*IFCPROJECTEDCRS(*")
(progn
(setq params (ifc-split-params (ifc-extract-params line)))
(setq first (vl-string-trim "'" (nth 0 params)))
(if (wcmatch (strcase first) "EPSG:*")
first
)
)
)
)
;; ------------------------------------------------------------
;; Main command
;; ------------------------------------------------------------
(defun c:ReadIFCMapConversion (/ file path line mapline unitline epsg
params x y z cosv sinv rot unit
radius radius1 cs scale)
(setq path (getfiled "Select IFC file" "" "ifc" 0))
(if (not path)
(progn (alert "No file selected.") (princ) (exit)))
(setq file (open path "r"))
(if (not file)
(progn (alert "Unable to open file.") (princ) (exit)))
;; Scan IFC
(while (setq line (read-line file))
(cond
((wcmatch (strcase line) "*IFCMAPCONVERSION(*")
(setq mapline line))
((and (wcmatch (strcase line) "*IFCIUNIT(*")
(wcmatch (strcase line) "*,.LENGTHUNIT.,*"))
(setq unitline line))
((not epsg)
(setq epsg (ifc-extract-epsg line)))
)
)
(close file)
;; Extract IFC units
(setq unit ".METRE.")
(if unitline
(progn
(setq params (ifc-split-params (ifc-extract-params unitline)))
(if (nth 3 params)
(setq unit (nth 3 params)))))
;; Compute scale factor
(setq scale (get-scale-factor unit))
;; Extract IFCMAPCONVERSION
(setq params (ifc-split-params (ifc-extract-params mapline)))
(setq x (* scale (atof (nth 2 params))))
(setq y (* scale (atof (nth 3 params))))
(setq z (* scale (atof (nth 4 params))))
(setq cosv (atof (nth 5 params)))
(setq sinv (atof (nth 6 params)))
(setq rot (* -180.0 (/ (atan sinv cosv) pi)))
;; Draw circles (scaled)
(setq radius (* scale (if (= (strcase unit) ".METRE.") 60.0 60000.0)))
(setq radius1 (* scale (if (= (strcase unit) ".METRE.") 660.0 660000.0)))
(command "_.CIRCLE" (list x y z) radius)
(command "_.CIRCLE" (list x y z) radius1)
;; ------------------------------------------------------------
;; BricsCAD V26 project location (FIXED: uses scaled coordinates)
;; ------------------------------------------------------------
(if (= (atoi (substr (getvar "ACADVER") 1 2)) 26)
(progn
;; apply scale here
(setq sx (* x 1))
(setq sy (* y 1))
(setq sz (* z 1))
(setq pt (strcat (rtos sx 2 6) "," (rtos sy 2 6) "," (rtos sz 2 6)))
(setq ang (rtos rot 2 8))
(command "_.SETPROJECTLOCATION" "POINT" pt "angle" ang "")
(command "_.SETSITELOCATION" "POINT" pt "angle" ang "")
)
)
;; EPSG → Geographic Location
(if epsg
(progn
(setq cs (vl-string-subst "" "'" epsg))
(alert (strcat "Setting Geographic Location to: " cs))
(vl-cmdf "-GEOGRAPHICLOCATION" cs)
)
)
;; Final message
(alert
(strcat
"IFCMapConversion found:\n"
mapline
"\n\nXYZ (scaled): " (rtos x 2 3) ", " (rtos y 2 3) ", " (rtos z 2 3)
"\nRotation (deg): " (rtos rot 2 8)
"\nRotation direction: " (rot-direction rot)
"\n\nIFC units: " unit
"\nDWG units: " (dwg-units->text (getvar "INSUNITS"))
"\nScale factor applied: " (rtos scale 2 6)
"\n" (if epsg epsg "Not found")
"\n\nCircles drawn."
)
)
(princ)
)
;; FOR CIVIL3D
;; ------------------------------------------------------------
;; Copy text to clipboard (safe for spaces)
;; ------------------------------------------------------------
(defun copy-to-clipboard (txt / sh cmd)
(if txt
(progn
(setq sh (vlax-create-object "WScript.Shell"))
(setq cmd (strcat "cmd /c echo " "\"" txt "\"" " | clip"))
(vlax-invoke sh 'Run cmd 0 t)
(vlax-release-object sh)
)
)
)
;; ------------------------------------------------------------
;; Extract numeric EPSG code (e.g. "28992" from "EPSG:28992")
;; ------------------------------------------------------------
(defun epsg-number (epsg)
(if (and epsg (wcmatch (strcase epsg) "EPSG:*"))
(substr epsg 6)
nil
)
)
;; ------------------------------------------------------------
;; IFC unit token ? meters
;; ------------------------------------------------------------
(defun ifc-unit->meters (u)
(cond
((= (strcase u) ".METRE.") 1.0)
((= (strcase u) ".MILLIMETRE.") 0.001)
((= (strcase u) ".CENTIMETRE.") 0.01)
((= (strcase u) ".KILOMETRE.") 1000.0)
((= (strcase u) ".FOOT.") 0.3048)
((= (strcase u) ".INCH.") 0.0254)
(T 1.0)
)
)
;; ------------------------------------------------------------
;; DWG INSUNITS ? meters
;; ------------------------------------------------------------
(defun dwg-units->meters (code)
(cond
((= code 1) 0.0254)
((= code 2) 0.3048)
((= code 4) 0.001)
((= code 5) 0.01)
((= code 6) 1.0)
(T 1.0)
)
)
;; ------------------------------------------------------------
;; DWG INSUNITS ? readable text
;; ------------------------------------------------------------
(defun dwg-units->text (code)
(cond
((= code 1) "inch")
((= code 2) "feet")
((= code 4) "mm")
((= code 5) "cm")
((= code 6) "m")
(T "unknown")
)
)
;; ------------------------------------------------------------
;; Compute IFC ? DWG scale factor
;; ------------------------------------------------------------
(defun get-scale-factor (ifc-unit-token / ifc-m dwg-m)
(setq ifc-m (ifc-unit->meters ifc-unit-token))
(setq dwg-m (dwg-units->meters (getvar "INSUNITS")))
(/ ifc-m dwg-m)
)
;; ------------------------------------------------------------
;; Rotation direction text
;; ------------------------------------------------------------
(defun rot-direction (angle)
(cond
((> angle 0) "CCW")
((< angle 0) "CW")
(T "Geen rotatie")
)
)
;; ------------------------------------------------------------
;; Split IFC parameter list safely
;; ------------------------------------------------------------
(defun ifc-split-params (s / out level c token)
(setq out '() token "" level 0)
(foreach c (vl-string->list s)
(cond
((= c 40) (setq level (1+ level)) (setq token (strcat token (chr c))))
((= c 41) (setq level (1- level)) (setq token (strcat token (chr c))))
((and (= c 44) (= level 0))
(setq out (cons token out))
(setq token ""))
(T (setq token (strcat token (chr c))))
)
)
(reverse (cons token out))
)
;; ------------------------------------------------------------
;; Extract substring between first "(" and matching ")"
;; ------------------------------------------------------------
(defun ifc-extract-params (line / a b)
(setq a (vl-string-search "(" line))
(setq b (vl-string-search ")" line (1+ a)))
(if (and a b)
(substr line (+ a 2) (- b a 1))
)
)
;; ------------------------------------------------------------
;; Extract EPSG:xxxx from IFCPROJECTEDCRS
;; ------------------------------------------------------------
(defun ifc-extract-epsg (line / params first)
(if (wcmatch (strcase line) "*IFCPROJECTEDCRS(*")
(progn
(setq params (ifc-split-params (ifc-extract-params line)))
(setq first (vl-string-trim "'" (nth 0 params)))
(if (wcmatch (strcase first) "EPSG:*")
first
)
)
)
)
;; ------------------------------------------------------------
;; MAIN COMMAND
;; ------------------------------------------------------------
(defun c:ReadIFCMapConversion
(/ file path line mapline unitline epsg epsg-num
params x y z cosv sinv rot unit scale
radius radius1 pt msg sx sy sz)
;; Select IFC
(setq path (getfiled "Select IFC file" (getvar "DWGPREFIX") "ifc" 0))
(if (not path)
(progn
(alert "No file selected.")
(princ)
(exit)
)
)
(setq file (open path "r"))
(if (not file)
(progn
(alert "Unable to open file.")
(princ)
(exit)
)
)
;; Open file
(setq file (open path "r"))
(if (not file)
(progn
(alert "Unable to open file.")
(princ)
(exit)
)
)
;; Scan IFC
(while (setq line (read-line file))
(cond
((wcmatch (strcase line) "*IFCMAPCONVERSION(*")
(setq mapline line))
((and (wcmatch (strcase line) "*IFCIUNIT(*")
(wcmatch (strcase line) "*,.LENGTHUNIT.,*"))
(setq unitline line))
((not epsg)
(setq epsg (ifc-extract-epsg line)))
)
)
(close file)
;; Default IFC unit
(setq unit ".METRE.")
;; Extract IFC unit
(if unitline
(progn
(setq params (ifc-split-params (ifc-extract-params unitline)))
(if (nth 3 params)
(setq unit (nth 3 params))
)
)
)
;; Scale factor
(setq scale (get-scale-factor unit))
;; Ensure IFCMAPCONVERSION exists
(if (not mapline)
(progn (alert "No IFCMAPCONVERSION found.") (return))
)
;; Extract parameters
(setq params (ifc-split-params (ifc-extract-params mapline)))
(setq x (* scale (atof (nth 2 params))))
(setq y (* scale (atof (nth 3 params))))
(setq z (* scale (atof (nth 4 params))))
(setq cosv (atof (nth 5 params)))
(setq sinv (atof (nth 6 params)))
;; Rotation
(setq rot (* 180.0 (/ (atan sinv cosv) pi)))
;; Draw circles
(setq radius (* scale (if (= (strcase unit) ".METRE.") 60.0 60000.0)))
(setq radius1 (* scale (if (= (strcase unit) ".METRE.") 660.0 660000.0)))
(command "_.CIRCLE" (list x y z) radius)
(command "_.CIRCLE" (list x y z) radius1)
(command "_.ZOOM" "_E")
;; UCS creation
(setq pt (list x y z))
(command "_.UCS" "_W")
(command "_.UCS" "_O" pt)
(command "_.UCS" "_Z" rot)
(setvar "UCSICON" 3)
(command "_.UCSICON" "ORIGIN")
;(command "_.PLAN" "")
;; EPSG numeric
(if epsg (setq epsg-num (epsg-number epsg)))
;; Build message
(setq msg
(strcat
"IFCMapConversion found:\n"
mapline
"\n\nXYZ (scaled): " (rtos x 2 3)"," (rtos y 2 3) "," (rtos z 2 3)
"\nRotation (deg): " (rtos rot 2 8)
"\nRotation direction: " (rot-direction rot)
"\n\nIFC units: " unit
"\nDWG units: " (dwg-units->text (getvar "INSUNITS"))
"\nScale factor applied: " (rtos scale 2 6)
"\n" (if epsg epsg "No EPSG found")
"\nUse Select Coordinate System and search for: "
(if epsg-num epsg-num "N/A")
)
)
(alert msg)
(princ msg)
(setvar "GEOMARKERVISIBILITY" 0) (princ)
;; Copy EPSG number
(if epsg-num
(progn
(copy-to-clipboard epsg-num)
(alert (strcat "EPSG number copied to clipboard: " epsg-num))
)
(alert "No EPSG code found to copy.")
)
(command "geocsassign") (princ)
(princ)
)
