dcowden / cadquery

CadQuery-- a parametric cad script framework
Other
432 stars 56 forks source link

dimension inputs for box requires separate variables rather than a vector #141

Closed burdickjp closed 5 years ago

burdickjp commented 8 years ago

I would like to feed box a vector for x,y,z dimensions rather than having to explicitly state x,y,z variables. Something like: dim = [2, 1, 1] result = cadquery.Workplane("XY").box(dim)

rather than having to do this: result = cadquery.Workplane("XY").box(dim[0], dim[1], dim[2])

dcowden commented 8 years ago

hmm that's interesting. Very do-able. Are you adventurous enough to make the change and do a pull request? We'd happily accept that.

Otherwise, we've a completely new version ( CQ 2.0) on the drawing board, and we'll integrate this into that effort.

On Fri, Apr 15, 2016 at 9:07 AM, Jeffrey Burdick notifications@github.com wrote:

I would like to feed box a vector for x,y,z dimensions rather than having to explicitly state x,y,z variables. Something like: dim = [2, 1, 1] result = cadquery.Workplane("XY").box(dim)

rather than having to do this: result = cadquery.Workplane("XY").box(dim[0], dim[1], dim[2])

— You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub https://github.com/dcowden/cadquery/issues/141

burdickjp commented 8 years ago

I tried a pull request, but I'm not very good at these things :(

CQ 2.0 sounds exciting. I'll be honest, I don't find CQ as it currently sits very human legible in comparison to OpenSCAD. I hope CQ 2.0 is a bit easier to read and write.

I HATE that OpenSCAD can't make STEP files. How am I supposed to CNC my parts if round features aren't actually round?!

dcowden commented 8 years ago

yes, i see the PR, thanks! I wont be able to merge it tonight but i'll get to it soon.

The 2.0 re-write is really about two things:

  1. removing the FreeCAD dependency and thus getting ability to get away from its constraints
  2. adding a proper feature tree, so that you can filter and select features base on the operation that added them

Unfortunately, it will very likely not change the syntax of scripts themselves, since that's not the plan.

I'd love to hear what things you find are difficult about cQ syntax. I personally think it is MUCH better than OpenSCAD, due primarily to the fact that it is actually python, vs some custom language, and due to the ability to chain methods together. Of course i'm biased obviously. OpenSCAD scripts are very long and hard to write because of its CSG heratage. cQ scripts are nearly always much shorter than their equivalent OS scripts.

All that said, i'd be happy to integrate suggestions to make it better, if they make sense. I liked your suggestion to allow an array instead of passing the dimensions themselves. Thanks for contributing!

On Fri, Apr 15, 2016 at 9:34 PM, Jeffrey Burdick notifications@github.com wrote:

I tried a pull request, but I'm not very good at these things :(

CQ 2.0 sounds exciting. I'll be honest, I don't find CQ as it currently sits very human legible in comparison to OpenSCAD. I hope CQ 2.0 is a bit easier to read and write.

I HATE that OpenSCAD can't make STEP files. How am I supposed to CNC my parts if round features aren't actually round?!

— You are receiving this because you commented. Reply to this email directly or view it on GitHub https://github.com/dcowden/cadquery/issues/141#issuecomment-210705817

burdickjp commented 8 years ago

Feature trees are exciting!

I agree that Python makes things much, much more powerful, but in the case of CQ I don't think it makes it more human readable than OpenSCAD. There are many, many disadvantages to OpenSCAD, but I don't think syntax is one. In this case I find the additional space useful. It may not be a fault of the syntax of CQ, though. I may be getting lost in the coding conventions used in the examples. Here's one of the examples from parametric parts (http://www.parametricparts.com/docs/examples.html#id15):

result = Workplane("front").box(4.0,4.0,0.25).faces(">Z").workplane()  \
     .transformed(offset=cad.Vector(0,-1.5,1.0),rotate=cad.Vector(60,0,0)) \
     .rect(1.5,1.5,forConstruction=True).vertices().hole(0.25)

Even after seeing what it's supposed to be I'm having trouble following it. Here's my best guess:

result =  Workplane("front").box(4.0,4.0,0.25) \ #constructs a box on the YZ plane in the Positive Y direction
.faces(">Z").workplane() \ #selects the face parallel to XY with the largest Z value and makes a workplane
.transformed(offset=cad.Vector(0,-1.5,1.0),rotate=cad.Vector(60,0,0)) \  #offsets and rotates that workplane. What's with Vector? Why not use a conventional python list [0,-1.5,1.0]?
.rect(1.5,1.5,forConstruction=True).vertices().hole(0.25) \ use the points of a construction rectangle as the center points of holes.
dcowden commented 8 years ago

Yeah, the compactness is a matter of convention rather than necessity. You can split the cq code into more separate lines with more descriptive variable names if that's your preference.

Compactness vs readability is usually aatter of comfort with the API, and to what extent you care about readability for those who may read the code later on. For enterprise coding, u would definitely use a much less compact style thN in some of the samples, I agree.

But, all that said it think the cq functions do a good job of minimizing the amount of code you have to write to achieve a result.

I'm open to suggestions! On Apr 16, 2016 9:24 AM, "Jeffrey Burdick" notifications@github.com wrote:

Feature trees are exciting!

I agree that Python makes things much, much more powerful, but in the case of CQ I don't think it makes it more human readable than OpenSCAD. There are many, many disadvantages to OpenSCAD, but I don't think syntax is one. In this case I find the additional space useful. It may not be a fault of the syntax of CQ, though. I may be getting lost in the coding conventions used in the examples. Here's one of the examples from parametric parts ( http://www.parametricparts.com/docs/examples.html#id15):

result = Workplane("front").box(4.0,4.0,0.25).faces(">Z").workplane() \ .transformed(offset=cad.Vector(0,-1.5,1.0),rotate=cad.Vector(60,0,0)) \ .rect(1.5,1.5,forConstruction=True).vertices().hole(0.25)

Even after seeing what it's supposed to be I'm having trouble following it. Here's my best guess:

result = Workplane("front").box(4.0,4.0,0.25) \ #constructs a box on the YZ plane in the Positive Y direction .faces(">Z").workplane() \ #selects the face parallel to XY with the largest Z value and makes a workplane .transformed(offset=cad.Vector(0,-1.5,1.0),rotate=cad.Vector(60,0,0)) \ #offsets and rotates that workplane. What's with Vector? Why not use a conventional python list [0,-1.5,1.0]? .rect(1.5,1.5,forConstruction=True).vertices().hole(0.25) \ use the points of a construction rectangle as the center points of holes.

— You are receiving this because you commented. Reply to this email directly or view it on GitHub https://github.com/dcowden/cadquery/issues/141#issuecomment-210814493

dcowden commented 8 years ago

I wanted to respond to your code example question when i had a full keyboard :)

You are pretty much exactly right with your analysis of the CQ code. Here's a version that is much less compact, and uses variable names to convey intent. this is more appropriate for someone less familiar with the CQ api:

Compact Version:

result = Workplane("front").box(4.0,4.0,0.25).faces(">Z").workplane() \

 .transformed(offset=cad.Vector(0,-1.5,1.0),rotate=cad.Vector(60,0,0)) \

 .rect(1.5,1.5,forConstruction=True).vertices().hole(0.25)

Longer Version:

workplane = Workplane("front")

baseBox = workplane.box(4.0,4.0,0.25)

topMostFace = baseBox.faces(">Z")

workplaneOnTopFace = topMostFace.workplane()

rotatedWorkplane = workplaneOnTopFace.transformed(offset=cad.Vector(0,-1.5,1.0), rotate=cad.Vector(60,0,0) )

cornerPoints = rotatedWorkplane.rect(1.5,1.5,forConstruction=True).vertices()

baseWithHoles = cornerPoints.hole(0.25 )

I have also noticed that sometimes people are more comfortable with boolean operations. This is because you need to know less background about CQ to get going.

For example, in the above, one thing you have to 'know' is that the hole() operation will automatically create cylinders and then subtract them. The form hole(...) is definitely more compact than creating cylinders and subtracting them, but also requires more background knowledge. CQ allows you to do it the more obvious way if you want:

workplane = Workplane("front")

baseBox = workplane.box(4.0,4.0,0.25)

topMostFace = baseBox.faces(">Z")

workplaneOnTopFace = topMostFace.workplane()

rotatedWorkplane = workplaneOnTopFace.transformed(offset=cad.Vector(0,-1.5,1.0), rotate=cad.Vector(60,0,0) )

cornerPoints = rotatedWorkplane.rect(1.5,1.5,forConstruction=True).vertices()

holesToCut = cornerPoints.circle(0.25 ).extrude(-4.0)

baseWithHoles = baseBox.subtract(holesToCut)

It is a very 'CQ' thing to offer hole(), which prevents the need to make a cylinder, subtract it, and then compute how long it has to be in order to clear all of the material. The syntax is more compact, but initially harder to understand i agree.

On Sat, Apr 16, 2016 at 9:24 AM, Jeffrey Burdick notifications@github.com wrote:

Feature trees are exciting!

I agree that Python makes things much, much more powerful, but in the case of CQ I don't think it makes it more human readable than OpenSCAD. There are many, many disadvantages to OpenSCAD, but I don't think syntax is one. In this case I find the additional space useful. It may not be a fault of the syntax of CQ, though. I may be getting lost in the coding conventions used in the examples. Here's one of the examples from parametric parts ( http://www.parametricparts.com/docs/examples.html#id15):

result = Workplane("front").box(4.0,4.0,0.25).faces(">Z").workplane() \ .transformed(offset=cad.Vector(0,-1.5,1.0),rotate=cad.Vector(60,0,0)) \ .rect(1.5,1.5,forConstruction=True).vertices().hole(0.25)

Even after seeing what it's supposed to be I'm having trouble following it. Here's my best guess:

result = Workplane("front").box(4.0,4.0,0.25) \ #constructs a box on the YZ plane in the Positive Y direction .faces(">Z").workplane() \ #selects the face parallel to XY with the largest Z value and makes a workplane .transformed(offset=cad.Vector(0,-1.5,1.0),rotate=cad.Vector(60,0,0)) \ #offsets and rotates that workplane. What's with Vector? Why not use a conventional python list [0,-1.5,1.0]? .rect(1.5,1.5,forConstruction=True).vertices().hole(0.25) \ use the points of a construction rectangle as the center points of holes.

— You are receiving this because you commented. Reply to this email directly or view it on GitHub https://github.com/dcowden/cadquery/issues/141#issuecomment-210814493

jmwright commented 8 years ago

I tried a pull request, but I'm not very good at these things :(

@burdickjp No worries, we're glad to have the contribution. We're happy to work with contributors to get pull requests ready to merge.

burdickjp commented 8 years ago

@dcowden Your long-form example helps a lot! Maybe, more than anything, the examples need effort more than the CQ codebase. Something I don't like about the long-form example is that you end up with a string of unnecessarily named variables at the end. Here's yet another way to look at it, which may be some kind of (unnecessary) compromise between the two, using comments to describe the function of a line of code rather than having variables, but still having things spread out.

p = Workplane("front") \ #workplane
    .box(4.0,4.0,0.25) \ #baseBox
    .faces(">Z").workplane() \ #workplaneOnTopFace
    .transformed(offset=cad.Vector(0,-1.5,1.0), rotate=cad.Vector(60,0,0) ) \ #rotatedWorkplane
    .rect(1.5,1.5,forConstruction=True).vertices() \ #cornerPoints
    .hole(0.25 ) \ #baseWithHoles
burdickjp commented 8 years ago

@jmwright I just put in another pull request. Hopefully a much better one.

dcowden commented 8 years ago

Yep, I think you have the hang of it now...

Please let me know of further language improvements you would suggest. I will try to merge your PR tonight.

If you are interested and willing, we would love help on cq 2.0.... On Apr 16, 2016 3:09 PM, "Jeffrey Burdick" notifications@github.com wrote:

@dcowden https://github.com/dcowden Your long-form example helps a lot! Maybe, more than anything, the examples need effort more than the CQ codebase. Something I don't like about the long-form example is that you end up with a string of unnecessarily named variables at the end. Here's yet another way to look at it, which may be some kind of (unnecessary) compromise between the two, using comments to describe the function of a line of code rather than having variables, but still having things spread out.

p = Workplane("front") \ #workplane .box(4.0,4.0,0.25) \ #baseBox .faces(">Z").workplane() \ #workplaneOnTopFace .transformed(offset=cad.Vector(0,-1.5,1.0), rotate=cad.Vector(60,0,0) ) \ #rotatedWorkplane .rect(1.5,1.5,forConstruction=True).vertices() \ #cornerPoints .hole(0.25 ) \ #baseWithHoles

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/dcowden/cadquery/issues/141#issuecomment-210875883

jmwright commented 8 years ago

@burdickjp I like the inline comments after the line escapes, and I can't think of a reason why they would cause problems.

@dcowden What do you think about making a task to reformat the examples this way? Anything we can do to help new users is a win.

burdickjp commented 8 years ago

@dcowden I'm willing to help.

@jmwright If you make a task to reformat the examples I am willing to go through them. This sounds like a great way to both familiarize myself with CQ and contribute.

dcowden commented 8 years ago

Sure it sounds like a great idea to me.... On Apr 16, 2016 4:13 PM, "Jeremy Wright" notifications@github.com wrote:

@burdickjp https://github.com/burdickjp I like the inline comments after the line escapes, and I can't think of a reason why they would cause problems.

@dcowden https://github.com/dcowden What do you think about making a task to reformat the examples this way? Anything we can do to help new users is a win.

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/dcowden/cadquery/issues/141#issuecomment-210887635

burdickjp commented 8 years ago

@dcowden Are those ellipses of confidence or ellipses of hesitation? Where should I try to get started?

jmwright commented 8 years ago

@burdickjp In about 20 minutes I'm planning to sit down and create an issue for this. I'll outline some thoughts on how to get started.

jmwright commented 8 years ago

@burdickjp I started writing up an issue, but the comments after the line continuations keep throwing errors for me. Is there a trick to it?

burdickjp commented 8 years ago

I will have to admit I hadn't tried it in a Python environment. But I'm seeing the error. It seems Python doesn't want anything after a \

jmwright commented 8 years ago

It seemed like a plausible thing to work. It seems like we're back to having extra intermediate variables, correct?

burdickjp commented 8 years ago

Probably. I'm going to think about it a bit more and try a few more things.

bweissinger commented 5 years ago

I think this can be done using python's argument unpacking feature. You just have to place an asterick (*) in front of the array when passing it. For example


box1 = [1, 1, 1]

# Argument unpacking
result = cq.Workplane("XY").box(*box1)

seems to work. I think argument unpacking works on both python 2 and 3.

If I run the following code in the FreeCAD cadquery workbench:

import cadquery as cq

box2 = (2, 2, 1)
box3 = (3, 1)
box4 = (4, 4)

# Inline unpacking
result = cq.Workplane("XY").box(*[1, 1, 1])

# Also works with tuples
result = result.moveTo(2.5, .5).box(*box2)

# Can unpack list after other arguments
result = result.moveTo(3, -3).box(3, *box3)

# Arguments passed after unpacked list must be a named keyword argument
result = result.moveTo(-1.5, -3.5).box(*box4, height=1)

show_object(result)

I get this as the output:

2018-11-24_16 35 48

jmwright commented 5 years ago

@bweissinger Very cool! This is a nice way to solve this issue. We need to figure out where to capture this solution before this issue is closed though. I'll have to think about that a little.

fragmuffin commented 5 years ago

@jmwright is this in scope of cadquery? I would argue it's a lesson in python. Not that I'd be against having this as an example :+1:

jmwright commented 5 years ago

@fragmuffin I am kind of leaning towards an example. It is a lesson in Python, but one that was never obvious to me, and might be useful to others in the future.

Once the contrib repo is moved to the CadQuery organization, I want to reorganize our examples a little bit and then add a few, including one for this.

dcowden commented 5 years ago

This has been closed in favor of the CQ 2.0 implemention at https://github.com/cadquery/cadquery