Expanding drawlists (14 Nov 2017)

Last week, someone posted a question to a customer forum for CoCreate Modeling (aka PTC Creo Elements/Direct Modeling), providing the perfect excuse for me to dabble with LISP again.

The question centered on how to expand the results of the API call sd-inq-vp-drawlist-objects which returns a list of all currently visible objects.


In the example to the right, the following objects are checked, and are therefore visible:

  • Assembly "a1"
  • Part "cone" in assembly "a1"
  • Part "cube" in assembly "a1"
  • Part "backplate" in assembly "act_assy"
  • Part "housing" in assembly "act_assy"
  • Part "pistonhead" in assembly "act_assy/pst_subassy"
  • Part "shaft" in assembly "act_assy/pst_subassy"

To reduce the amount of data it has to return, sd-inq-vp-drawlist-objects "compresses" its result as follows:

  • If all objects below an assembly are checked (=visible), only the assembly is returned
  • In partially visible assemblies, visible objects are returned individually

So in our example, sd-inq-vp-drawlist-objects would return a list containing:

  • /a1
  • /act_assy/backplate
  • /act_assy/housing
  • /act_assy/pst_subassy

This representation is perfectly fine for many purposes, but in the specific circumstances of the forum post, the user needed a way to "uncompress" the result, and wasn't interested in the assemblies, only in parts. So in the given example, the desired output would have been:

  • /a1/cone
  • /a1/cube
  • /act_assy/backplate
  • /act_assy/housing
  • /act_assy/pst_subassy/piston-head
  • /act_assy/pst_subassy/shaft

Assembly structures can be highly nested, of course, and so a recursive solution is needed.

My first solution revisited an approach I used in a previous blog post which discussed how to recurse over a hierarchy of objects and build a flat list from it.

(in-package :de.clausbrod.expanddrawlist)
(use-package :oli)

(defun flatten-assembly-mapcan(node) (cons node (mapcan #'flatten-assembly-mapcan (sd-inq-obj-children node))))

(defun expand-objects(objects) (loop for obj in objects nconc (remove-if-not #'sd-inq-part-p (flatten-assembly-mapcan obj))))

(defun show-part(p) (display (sd-inq-obj-pathname p)))

(let ((displayed-objects (sd-inq-vp-drawlist-objects (sd-inq-current-vp)))) (mapc #'show-part (expand-objects displayed-objects)))

This worked and returns lists as described above. However, if you're actually not really interested in those intermediate lists, but instead simply want to visit all visible parts in the assembly tree and execute some action for each of those parts, then the problem can be solved more succinctly:

(in-package :de.clausbrod.expanddrawlist)
(use-package :oli)

(defun show-part(p) (display (sd-inq-obj-pathname p)))

(defun visit-parts(obj) (if (sd-inq-part-p obj) (show-part obj) (mapc #'visit-parts (sd-inq-obj-children obj))))

(let ((displayed-objects (sd-inq-vp-drawlist-objects (sd-inq-current-vp)))) (mapc #'visit-parts displayed-objects)))

Previous month: Click here.

Revision: r1.1 - 14 Nov 2017 - 20:47 - ClausBrod
Blog > WebLeftBar > DefinePrivatePublic201711
Copyright © 1999-2023 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback