Seeking good ways to conceptually group solids into larger 'objects'

35 views
Skip to first unread message

Cameron White

unread,
Feb 16, 2024, 5:33:46 PM2/16/24
to CadQuery
I'm currently learning cadquery and hoping to use it to model some structural framing for a wood framed home

The only 3d modeling experience I have is in SketchUp (so not actually standard software CAD) but I'm a reasonably experienced programmer

I feel confident I could draw all the solids I need to make the shape I want. But I don't know the best way to keep it logically organized

For example, in SketchUp, one thing I could do is
  1. draw and extrude a solid to represent a wooden 2x4 stud
  2. Group all the faces + edges of that solid as if to say "this is one thing" and name it. Conceptually, "this is a wood stud"
  3. Make a bunch of copies of my stud
  4. Select all of those and group those studs together as if to say "this is all one thing. It is a wall" 



Does anyone know of a good way to organize cad projects in a similar way in general? And then more specifically, does anyone know of a good way to do this with CadQuery. Ideally when my generated models are opened in a given cad software, they are organized into logical discrete parts as opposed to one huge complex shape or a ton of simple shapes with no relation to one another

neri-engineering

unread,
Feb 16, 2024, 6:20:11 PM2/16/24
to Cameron White, CadQuery
Yes I can chime in with the problem you're trying to solve because I have created some MASSIVE designs in a very similar tool (called OpenSCAD).  Just a disclaimer, I come from a computer science and mathematics background, so I describe an approach taken in the field of 3D computer graphics.  I am not exactly sure what carpenters or mechanical engineers are taught when they study their respective arts.  I think the use of tools such as computers is relatively new to all areas of study, so there is room for exploration, discovery, and innovation.

In the topic of 3D computer graphics courses that you would take at a higher learning institution, the jargon they would use for what you're referring to is a "scene graph".  To render a scene, you traverse the entire "tree" or "graph", where as you descend into each branch or node there is associated with it a transformation (3D translation and 3D rotation, or change of coordinate axes).  In other words you try to make everything highly orderly and highly organized.  This is probably the most difficult task in engineering in general, which is how to be highly organized.

The other dimension along which you bring up a good point is whether to use functional/procedural programming paradigm or an object oriented approach.  I prefer the functional/procedural approach for the kinds of stuff you're describing, but this is a matter of opinion.

To begin you can try defining your lowest leaf node, the 2x4 stud.  A parameter you may take as input would be the length.

def two_by_four(length):
    ...
    return stud

Above you would create a paradigm of where the stud is centered (or not centered).  This is by your choice, but you would typically start to rigorously model your design not only in the code but also in API comments left immediately before the method declarations, as to the exact locations/orientations of objects returned by the methods.  Essentially you want to encapsulate everything and forget about the gory details, unless you're working on the gory details.

You could then start building the wall, but as a carpenter you'd know how far apart to space the two by four's.  Or maybe the spacing is configurable.  Maybe the wall could take a height, a length, and the spacing between two by fours.

def wall(height, length, spacing):
    ....
    return wall

Inside the code of wall() you would instantiate many two by fours.  Yes, the technical term for this in computer graphics jargon is "instantiation".

And so on.  It's like building things out of Lego blocks.

In my case I have such intricate parts, I have a differential, a top shaft, a chassis, a motor mount, a front differential, etc. and all of those parts are defined in a coordinate system which makes sense for that part.  Each of those assemblies is divided into node parts, which are the leaf modes.  Then a monster function combines all assemblies by transforming them properly into the chassis coordinate system.

One approach I take as well, which may not be suitable in your case, is I tend to define LOTS of various constants in an external file which contains JUST CONSTANTS.  Then that constants file is imported by all other files that define parts.  In this way I can quickly find and make a change, by only looking at a constants file and not through the entire multi-file code.  Code ends up always relying on the constants and the code NEVER hardcodes numerical values in logic, unless it is something harmless like an epsilon value to get overlaps.

##### GENERAL GEAR PROPERTIES #################################################

gear_pitch_48 = 1.66243 # The 'mm_per_tooth' value passed to spur_gear().
tooth_pressure = 25 # Pressure angle of gear tooth profile in degrees.

##### DIFF GEAR SECTION BELOW #################################################

n_diff_gear_teeth = 59 # 59t diff gear & 16t drive gear have been decided upon.
mm_diff_gear_width = 9 # Width of diff gear; change far-reaching effect.
n_diff_balls = 8 # Also number of rear belt pulley prongs.
mm_diff_ball = 3.175 # Diameter of rear diff ball, 1/8 inch.
mm_diff_ball_wiggle = 0.08 # Radial wiggle around the diff ball.  The holes in
                           # the diff gear where the diff balls ride will be
                           # larger in diameter than the diff ball by twice
                           # this amount.
mm_diff_ball_protrusion = 0.15 # The amount by which the diff balls protrude
                               # past the diff gear walls, to be better grabbed
                               # by the diff rings.  Multiply this value by two
                               # and subtract it from the diff ball diameter to
                               # arrive at the diff gear inner wall thickness.
mm_diff_gear_recess_diameter = 23.5 # Diameter of inner cylinder for rear
                                    # pulley prongs.  That cylinder aligns
                                    # perfectly with the cavity diameter of
                                    # diff gear.
z_max_diff_ring = 5.0/2

In my case the constants files end up being at least 500 lines of code, sometimes 1000.

Hope that helps.  Welcome to the world of computer graphics and CAD modeling.  I am sure that you will enjoy your stay.  You can use the coffee machine over there if you need some stimulation.  I hope you get inspired, and please bear in mind that there is not absolutely correct or absolutely wrong way of doing things; there is only better and worse, and usually it's a matter of opinion.

Sent with Proton Mail secure email.

--
cadquery home: https://github.com/CadQuery/cadquery
post issues at https://github.com/CadQuery/cadquery/issues
run it at home at : https://github.com/CadQuery/CQ-editor
---
You received this message because you are subscribed to the Google Groups "CadQuery" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cadquery/b6165da5-fcf9-466c-b5f7-04a56f949bdan%40googlegroups.com.

Adam Urbanczyk

unread,
Feb 17, 2024, 3:57:07 AM2/17/24
to CadQuery

Cameron White

unread,
Feb 17, 2024, 10:38:11 AM2/17/24
to CadQuery
Neri-Engineering, thank you for your very thoughtful and thorough response.
Defining functions to create each 'node' makes a lot of sense to me from a code organization perspective. 
In terms of the return values from these node creating functions, would you be creating an assembly for each non-leaf node. Just assemblies made of assemblies all the way up? 

For example, lets say that I want to ensure that a non-developer sees the following conceptual hierarchy when they open my cad model in any given off-the-shelf cad software.

                House
              /             \
     wall1.                 wall2
    /.        \                  |        \
stud1.   stud2.     stud1.    stud2

Would the appropriate pattern (or perhaps 'an' appropriate pattern) be to:
- instantiate each stud as a generic 'solid' ('part'? 'body'? not sure what the appropriate terminology would be here) 
- instantiate walls as assemblies with studs added to them?
- instantiate the house as an assembly with the walls added to it? 

Adam Urbanczyk, Thank you for linking to the assembly docs. I should have mentioned that I have looked over  them
but I'm still trying to confirm whether or not they are suitable for achieving the organization / structure that I want

Best,
Cam

Cameron White

unread,
Feb 17, 2024, 11:15:24 AM2/17/24
to CadQuery
To elaborate a little bit. I'm trying to figure out what the CadQuery concept is that best maps to each 'node' in the above example. 

In fusion360 you could accomplish this using components that are composed of other components. 
In SketchUP you could have 'groups' composed of 'groups' (or 'components') 

I could imagine the 'right' way to do this being just to make every 'node' an 'assembly'. 
Based on the fact that the assembly add method can accept another assembly as input, it seems like this might be the right way to do it 

Ideally if I would be able to export to a STEP file, open it in fusion 360 (or freecad/whatever), and see an expected component tree in the browser.

I was originally being thrown off by the fact that the convention in some cad software seems to be that assemblies are only 'root nodes' and all the other nodes are 'components' (my cad ignorance is likely showing here). I am beginning to think that maybe I can ignore this worry, just make everything out of nested assemblies, and expect to be able to open a STEP file and see nested components in something like fusion 360 

I'm also wondering if maybe 'compounds' are what maps most cleanly to these nodes? 

Thanks in advance for any input 
Cam

Jeremy Wright

unread,
Feb 17, 2024, 12:05:41 PM2/17/24
to Cameron White, CadQuery
CadQuery uses the concept of Workplanes, which can be considered as analogous to parts, depending on how you use them. An assembly is made up of multiple Workplanes placed together, and the Workplanes can be positioned via constraints. Assemblies can also be nested.

So in your diagram a Workplane could be a stud, a wall could be a nested Assembly, and the house could be the top level Assembly.



--
cadquery home: https://github.com/CadQuery/cadquery
post issues at https://github.com/CadQuery/cadquery/issues
run it at home at : https://github.com/CadQuery/CQ-editor
---
You received this message because you are subscribed to the Google Groups "CadQuery" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cadquery+u...@googlegroups.com.

Neri-Engineering

unread,
Feb 17, 2024, 12:50:57 PM2/17/24
to CadQuery
I think Jeremy answered you question and you did yourself to some degree.
I'm totally new to CadQuery as well.  I looked at 'Assembly' only because it allows you to specify a color to an object.  But of course it also has notion of transformation w.r.t. its parent.

I think some combination of Assembly and Workplane can be used, based on your taste.  A bit of experimentation will reveal the answer to you.  There is no absolute way to do things.
Reply all
Reply to author
Forward
0 new messages