Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added cone 3D primitive to Workplane. #859

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

martinbudden
Copy link
Contributor

@martinbudden martinbudden commented Aug 25, 2021

I've added a cone 3D primitive to the Workplane, as per item on the roadmap, https://github.com/CadQuery/cadquery/blob/master/doc/roadmap.rst

This follows the OpenSCAD style, so if a single radius is specified a normal cone is created, whereas if radius1 and radius2 is specified then a truncated cone is created.

So cq.Workplane("XY").cone(40, 10) creates a cone with height 40 and radius 10
whereas cq.Workplane("XY").cone(40, radius1=10, radius2=5) creates a truncated cone with bottom radius 10 and top radius 5.

@martinbudden
Copy link
Contributor Author

Tests now only failing on

cadquery\occ_impl\exporters\dxf.py:86: error: Module has no attribute "BSplineClosed"

Which was a pre-existing error.

Copy link
Member

@jmwright jmwright left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @martinbudden

@codecov
Copy link

codecov bot commented Sep 2, 2021

Codecov Report

Merging #859 (724af40) into master (ba1dfe4) will increase coverage by 0.01%.
The diff coverage is 100.00%.

❗ Current head 724af40 differs from pull request most recent head 57f0809. Consider uploading reports for the commit 57f0809 to get more accurate results
Impacted file tree graph

@@            Coverage Diff             @@
##           master     #859      +/-   ##
==========================================
+ Coverage   95.88%   95.90%   +0.01%     
==========================================
  Files          32       32              
  Lines        7663     7693      +30     
  Branches      815      817       +2     
==========================================
+ Hits         7348     7378      +30     
  Misses        186      186              
  Partials      129      129              
Impacted Files Coverage Δ
cadquery/cq.py 91.42% <100.00%> (+0.07%) ⬆️
tests/test_cadquery.py 99.22% <100.00%> (+<0.01%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update ba1dfe4...57f0809. Read the comment docs.

cadquery/cq.py Outdated
def cone(
self: T,
height: float,
radius: float = 0,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the redundancy (at most two radius params needed) and defaulting of radius/radius1 :

        radius1: float,
        radius2: Optional[float] =None

If combine is false, the result will be a list of the cones produced.
"""

r1 = radius if radius1 is None or radius1 == 0 else radius1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
r1 = radius if radius1 is None or radius1 == 0 else radius1
r1 = radius1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a reason for this, it to allow the user to specify cone(height=40, radius=10) for a simple cone and cone(height=40, radius1=10, radius2=5) for a truncated cone. This is akin to how OpenSCAD handles things.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only convenient if argument names are always specified. But what about cone(40,10) for simple cone and cone(40,10,5) for truncated cone? cone(40,10,5) will give surprising results with three radius arguments.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. I could solve that problem by ordering the aguments: cone(height, radius1, radius2, radius). Then

cone(40,10)
cone(40,10,5)
cone(height=40,radius=10)
cone(height=40,radius1=10,radius2=5)

All behave as expected.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API of OpenSCAD is not really relevant here (different language; no intended relation with CQ). What is very relevant on the other hand is consistence with existing functions. Taking this into account, I'd propose:

def cone(
        self: T,
        radius1: float,
        height: float,
        radius2: float = 0.0,
       ...

The same holds for the recently merged cylinder (radius and height should be interchanged to be similar to e.g. the hole signature). It would be really great, if you could amend it in this PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API of OpenSCAD is not really relevant here (different language; no intended relation with CQ).

While I agree that there is no need to be the same as OpenSCAD, I don't believe other languages are not relevant - taking cues from how other established systems work can often suggest a pattern to use.

What is very relevant on the other hand is consistence with existing functions

Agreed. The reason for consistency is not for its own sake, it is because consistency helps avoid errors. The parameter ordering cone(radius1, height, radius2) is horrible and error-inducing, thus defeating the reason for being consistent. And if we really want to follow other functions, eg cboreHole and cskHole then we should use diameter rather than radius. But we already have sphere, fillet, ellipse and circle which use radius. So orthogonality is already broken.

Having said all that, I suggest:

def cone(
    self: T,
    height: float,
    radius1: float,
    radius2: float = 0.0,
...

This:

  1. Uses radius and so is consistent with the other geometric primitives.
  2. Allows a natural parameter ordering for truncated cone.
  3. Does not have the contentious radius parameter.

@adam-urbanczyk
Copy link
Member

adam-urbanczyk commented Sep 8, 2021 via email

@martinbudden
Copy link
Contributor Author

It is not perfect so let's make it even worse with regard to consistent param ordering?

No, that's not what I am saying at all.

What I am saying is that there are a number of factors that determine function signature, consistency is one of them and usability is another. Consistency is in fact a subset of usability, and so making something consistent but less usable makes no sense. (I also had a side argument that defining what is consistent is somewhat subjective when the set is already inconsistent.)

@adam-urbanczyk
Copy link
Member

adam-urbanczyk commented Sep 9, 2021 via email

@fedorkotov
Copy link
Contributor

@adam-urbanczyk please reconsider radius1, height, radius2 argument order. IMHO it is really non-obvious and surprising.
Look at GUIs and APIs of other somewhat similar software
https://docs.blender.org/api/current/bpy.ops.mesh.html#bpy.ops.mesh.primitive_cone_add
https://docs.salome-platform.org/latest/gui/GEOM/create_cone_page.html

Of course CadQuery does not have to follow traditions and conventions of other products but look at

def makeCone(
and BRepPrimAPI_MakeCone
https://github.com/CadQuery/OCP/blob/e1df3469a39228ce2553aacc3a0238e334d4dd9a/opencascade/BRepPrimAPI_MakeCone.hxx#L49
Both of them have radii close together not and not separated by height.

@adam-urbanczyk
Copy link
Member

adam-urbanczyk commented Sep 9, 2021 via email

@fedorkotov
Copy link
Contributor

@martinbudden I think that having a cone primitive creation method in Workplane is better than not having one. And so suggest you follow @adam-urbanczyk recommendations even if you do not agree so that this can be merged sooner rather than later (or never). If you have very strong opinion on this matter, there is also https://github.com/CadQuery/cadquery-plugins repo. Plugins don't have to conform to the same standards as "built in" features of CadQuery.

@adam-urbanczyk
Copy link
Member

Another option would be to wait for sketch branch being merged (and implicitly multimethods) and implement two overloads r,h and r1,r2,h. It will take some time though.

@martinbudden
Copy link
Contributor Author

Another option would be to wait for sketch branch being merged (and implicitly multimethods) and implement two overloads r,h and r1,r2,h. It will take some time though.

I think I'd rather wait for the implementation of multimethods than add the legacy of a method with the parameter ordering of r1, h, r2.

@Konubinix
Copy link

Hi. I'm not fluent in cadQuery and just wanted to make a cone the same way I make other primitives, with Workpkane().cone(...). IIUC, this PR enables this, right ?

@adam-urbanczyk
Copy link
Member

Indeed, it is waiting to be reworked so that it provides two overloads cone(r, h) and cone(r1, r2, h). Seems though that the OP lost interest in the meantime, so if you want to pick this up you are more than welcome.

@Konubinix
Copy link

Konubinix commented Aug 12, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants