cadquery icon indicating copy to clipboard operation
cadquery copied to clipboard

Create a closed loop with rectangular cross section - obtaining two extra unwanted faces

Open nfoppiani-pf opened this issue 1 year ago • 7 comments

Hello! I am relatively new to CadQuery, and I have a question for which I have not found any good example. I am trying to create a CAD model of a loop with rectangular cross section. Here is a minimal example for a single ring using a sweep operation. In general the shapes I am interested in are more complex, but the topology is the same.

import os
import cadquery as cq
import numpy as np

RADIUS = 10
if __name__ == "__main__":

    # let's generate a ring with a sweep command

    # Create a circle profile for the ring on the xy plane
    thetas = np.linspace(0, 2 * np.pi, 100)
    x = RADIUS*np.cos(thetas)
    y = RADIUS*np.sin(thetas)
    z = np.zeros_like(thetas)

    xyz = np.stack([x, y, z], axis=1).tolist()
    assert len(xyz) == len(thetas)

    circle_profile = cq.Workplane("XY").spline(xyz, includeCurrent=False).close()

    # Create a rectangle profile for the ring
    rectangle_edges = [(9, 0, -1), (9, 0, 1), (11, 0, 1), (11, 0, -1)]
    rectangle_profile = cq.Workplane("XY").polyline(rectangle_edges, includeCurrent=False).close()

    # let's run a sweep
    sweep = rectangle_profile.sweep(path=circle_profile)
    assert sweep.solids().size() == 1

    # export the file as STEP
    cq.exporters.export(sweep.solids().val(), "ring.step")

However, the output is not a fully closed loop, but I get two overlapping rectangular faces at the beginning and end of the process. Basically, the solid now has 4 faces rather than 6. Here is an example of the file I created opened in FreeCad. Screenshot from 2024-01-04 11-47-42

How can I make it a fully closed loop, with only 4 faces?

Thanks!

nfoppiani-pf avatar Jan 04 '24 11:01 nfoppiani-pf

Try increasing the number of points for the spline profile from 100 to a larger value. (I find >= 109 points results in 4 faces and valid shape).

In this case it is simpler to use revolve to create the ring:

import cadquery as cq

# Create a rectangle profile for the ring
rectangle_edges = [(9, 0, -1), (9, 0, 1), (11, 0, 1), (11, 0, -1)]
rectangle_profile = cq.Workplane("XY").polyline(rectangle_edges, includeCurrent=False).close()

ring = rectangle_profile.revolve(360, (0, 0, 0), (0, 0, 1))

lorenzncode avatar Jan 05 '24 04:01 lorenzncode

Thank you for your answer. Unfortunately, even with >= 109 points I still see the same problem when opening in FreeCAD. How did you perform your check on the number of faces and valid shape?

Moreover, when running with a revolve of 360 degrees, when opening in FreeCad I still see an edge (and one on the outer cylindrical surface). image

nfoppiani-pf avatar Jan 08 '24 16:01 nfoppiani-pf

I've seen something like this before when revolving 360 degrees. It came up a while back on this issue https://github.com/CadQuery/cadquery/issues/259

I remember trying the clean argument that is part of the revolve method but it didn't help at the time, might be worth trying again.

I've see this extra faces happen again recently and in the end we made two revolutions and used a union to combine them. https://github.com/fusion-energy/model_benchmark_zoo/blob/2b8f991065e81873f6f6a50ca0cee50bdfadfacb/src/model_benchmark_zoo/ellipticaltorus.py#L28-L29

Noting that OCP 7.7.2 is just out so it might also be worth trying the latest version

shimwell avatar Jan 08 '24 16:01 shimwell

Thank you! I think I tried something like this hack before but it did not solve the issue in my case. I will try to see if perhaps there is a problem with using too few points for the spline. I have got the latest CadQuery and OCP, although I am not calling OCP directly here.

I have seen you had a command on this issue https://github.com/CadQuery/cadquery/issues/449#issuecomment-997309152 to remove faces using OCP and Brep files. I tried to do something like that but it did not work though.

nfoppiani-pf avatar Jan 09 '24 08:01 nfoppiani-pf

How did you perform your check on the number of faces and valid shape?

To count faces: len(sweep.faces().vals()) isValid check: sweep.val().isValid()

Moreover, when running with a revolve of 360 degrees, when opening in FreeCad I still see an edge (and one on the outer cylindrical surface).

These are seam edges. Seam edges are expected when working with cadquery and OCCT.

For example, the seam when creating a cylinder:

cyl = cq.Workplane().circle(10).extrude(20)

seam_cyl_cq-editor

lorenzncode avatar Jan 10 '24 01:01 lorenzncode

Thank you so much, that's really helpful! Is there a way to remove seam edges?

nfoppiani-pf avatar Jan 10 '24 23:01 nfoppiani-pf

Nope, that is how B-Rep works.

adam-urbanczyk avatar Jan 12 '24 19:01 adam-urbanczyk