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

Radius selector #501

Closed
marcus7070 opened this issue Nov 10, 2020 · 7 comments · Fixed by #504
Closed

Radius selector #501

marcus7070 opened this issue Nov 10, 2020 · 7 comments · Fixed by #504

Comments

@marcus7070
Copy link
Member

I think there is a need for a radius selector. All of CQ's current selectors work of the centre of an object or the bounding box. So if you have the following shape for example:

part = (
    cq
    .Workplane()
    .circle(10)
    .extrude(10)
    .faces(">Z")
    .workplane()
    .hole(10)
)

screenshot2020-11-10-201029
and you want to fillet just the outer edges and not the inner, the only selector that you can use is some ugly combination of bounding boxes.

A radius selector in the style of DirectionNthSelector would be a good addition IMHO.

@marcus7070
Copy link
Member Author

I think there is a potential method to extract radii.

I can get the radius of the circles from the above code with:

objs = part.faces(">Z").edges("%CIRCLE").vals()
for obj in objs:
    print(obj._geomAdaptor().Circle().Radius())

I don't know enough about OCCT to know if this is the appropriate method, but ignorance is bliss so I'm happy to plow ahead and write a selector (and a bunch of tests for it) based off this method.

@jmwright
Copy link
Member

I've run into the same thing before when selecting circles and just ended up using a box selector. It would be nice to have a shortcut for it.

This is tangentially related to a discussion on Discord last week on selecting a circular edge by edge length. It seems like that would be complementary to this for when you're not dealing with a whole circle. You can calculate the edge length, and then select using a length tolerance.

Below is the code that I put together, but as Adam rightly pointed out at the time, I went the long way around to get the length of the edge.

import cadquery as cq
from OCP.GCPnts import GCPnts_AbscissaPoint
from OCP.BRepAdaptor import BRepAdaptor_Curve

# All based on existing source code until next comment
class LengthSelector(cq.Selector):
    new_obj_list = []

    def __init__(self, length):
        self.length = length

    def filter(self, objectList):
        for obj in objectList:
            curve = BRepAdaptor_Curve(obj.wrapped)
            edge_len = GCPnts_AbscissaPoint.Length_s(curve)
            
            # Only return edges that meet our requirements
            tol = 0.2
            if edge_len > self.length - tol and edge_len < self.length + tol: 
                log(edge_len)
                self.new_obj_list.append(obj)
        
        return self.new_obj_list

pts = [(0, 0, 0), (10, 10, 0), (10, 0, 0)]
result = cq.Workplane().polyline(pts).close().extrude(10)
result = result.edges(LengthSelector(14.0)).fillet(1.0)

show_object(result)

And here's what @shimwell ended up with after cleaning up my code.
cleaned code

@michaelgale
Copy link

My cqkit library has a RadiusSelector and a DiameterSelector. I love the selector functionality and how easily it is extended. Alternative selectors are the biggest part of the cqkit package for good reason!
Example:

    r = (
        cq.Workplane("XY")
        .circle(2)
        .workplane(offset=3, centerOption="ProjectedOrigin")
        .circle(3)
        .loft()
    )
    rs = RadiusSelector(2)
    assert r.edges(rs).size() == 1
    rs = RadiusSelector(3)
    assert r.edges(rs).size() == 1

@shimwell
Copy link
Contributor

Planning to make good use of that length selector and made an area selector in the same way that you taught me @jmwright . Thanks for your help. A radius selector sounds like a great idea.

@adam-urbanczyk
Copy link
Member

@marcus7070 do you want to backport the selector from cqkit then?

@marcus7070
Copy link
Member Author

Yes, I'll do that in the next few days. I see @michaelgale also used the _geomAdaptor, so that gives me a lot more confidence.

@adam-urbanczyk
Copy link
Member

OK, _geomAdaptor is indeed the way to go.

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 a pull request may close this issue.

5 participants