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

The relative position is inaccurate #60

Closed
huskier opened this issue Oct 10, 2015 · 17 comments
Closed

The relative position is inaccurate #60

huskier opened this issue Oct 10, 2015 · 17 comments

Comments

@huskier
Copy link
Contributor

huskier commented Oct 10, 2015

We're using CADQuery to create a panel with mounting holes, and we positioned the holes with coordinates. However, the relative positions of the holes are inaccurate. Here is an example.

# This example is meant to be used from within the CadQuery module of FreeCAD.
import cadquery
from Helpers import show

width = 100
height = 200
thickness = 2

# Create a plate with two polygons cut through it
result = cadquery.Workplane("front").box(width, height, thickness)

result = result.faces("<Z").workplane(offset=0).center(0,30).rect(10,10).cutThruAll()
result = result.faces("<Z").workplane(offset=0).center(0,-30).rect(10,10).cutThruAll()
result = result.faces("<Z").workplane(offset=0).center(0,-60).rect(10,10).cutThruAll()

# Render the solid
show(result)

I put the three rectangle holes at points (0,30), (0,-30) and (0, -60) respectively. The distance between the first rect and the second rect holes should be exactly 60, but I've got 60.1508. The distance between the second rect and the third rect holes should be exactly 30, but CADQuery gives 29.8485. I don't know what's wrong with my code. Very weired!

@huskier
Copy link
Contributor Author

huskier commented Oct 10, 2015

Our real application is like the following code. It is really help for this kind of applications if the position issue can be solved.

# This example is meant to be used from within the CadQuery module of FreeCAD.
import cadquery
from Helpers import show

# The dimensions of the model. These can be modified rather than changing the
# object's code directly.
width = 400
height = 500
thickness = 2

# Create a plate with two polygons cut through it
result = cadquery.Workplane("front").box(width, height, thickness)

h_sep = 60
for idx in range(4):
    result = result.workplane(offset=1).center(157,210-idx*h_sep).moveTo(-23.5,0).circle(1.6).moveTo(23.5,0).circle(1.6).moveTo(-17.038896,-5.7).threePointArc((-19.44306,-4.70416),(-20.438896,-2.3)).lineTo(-21.25,2.3).threePointArc((-20.25416,4.70416),(-17.85,5.7)).lineTo(17.85,5.7).threePointArc((20.25416,4.70416),(21.25,2.3)).lineTo(20.438896,-2.3).threePointArc((19.44306,-4.70416),(17.038896,-5.7)).close().cutThruAll()

for idx in range(4):
    result = result.workplane(offset=1).center(157,-30-idx*h_sep).moveTo(-16.65,0).circle(1.6).moveTo(16.65,0).circle(1.6).moveTo(-10.1889,-5.7).threePointArc((-12.59306,-4.70416),(-13.5889,-2.3)).lineTo(-14.4,2.3).threePointArc((-13.40416,4.70416),(-11,5.7)).lineTo(11,5.7).threePointArc((13.40416,4.70416),(14.4,2.3)).lineTo(13.5889,-2.3).threePointArc((12.59306,-4.70416),(10.1889,-5.7)).close().cutThruAll()

h_sep4DB9 = 30
for idx in range(8):
    result = result.workplane(offset=1).center(91,225-idx*h_sep4DB9).moveTo(-12.5,0).circle(1.6).moveTo(12.5,0).circle(1.6).moveTo(-6.038896,-5.7).threePointArc((-8.44306,-4.70416),(-9.438896,-2.3)).lineTo(-10.25,2.3).threePointArc((-9.25416,4.70416),(-6.85,5.7)).lineTo(6.85,5.7).threePointArc((9.25416,4.70416),(10.25,2.3)).lineTo(9.438896,-2.3).threePointArc((8.44306,-4.70416),(6.038896,-5.7)).close().cutThruAll()

for idx in range(4):
    result = result.workplane(offset=1).center(25,210-idx*h_sep).moveTo(-23.5,0).circle(1.6).moveTo(23.5,0).circle(1.6).moveTo(-17.038896,-5.7).threePointArc((-19.44306,-4.70416),(-20.438896,-2.3)).lineTo(-21.25,2.3).threePointArc((-20.25416,4.70416),(-17.85,5.7)).lineTo(17.85,5.7).threePointArc((20.25416,4.70416),(21.25,2.3)).lineTo(20.438896,-2.3).threePointArc((19.44306,-4.70416),(17.038896,-5.7)).close().cutThruAll()

for idx in range(4):
    result = result.workplane(offset=1).center(25,-30-idx*h_sep).moveTo(-16.65,0).circle(1.6).moveTo(16.65,0).circle(1.6).moveTo(-10.1889,-5.7).threePointArc((-12.59306,-4.70416),(-13.5889,-2.3)).lineTo(-14.4,2.3).threePointArc((-13.40416,4.70416),(-11,5.7)).lineTo(11,5.7).threePointArc((13.40416,4.70416),(14.4,2.3)).lineTo(13.5889,-2.3).threePointArc((12.59306,-4.70416),(10.1889,-5.7)).close().cutThruAll()

for idx in range(8):
    result = result.workplane(offset=1).center(-41,225-idx*h_sep4DB9).moveTo(-12.5,0).circle(1.6).moveTo(12.5,0).circle(1.6).moveTo(-6.038896,-5.7).threePointArc((-8.44306,-4.70416),(-9.438896,-2.3)).lineTo(-10.25,2.3).threePointArc((-9.25416,4.70416),(-6.85,5.7)).lineTo(6.85,5.7).threePointArc((9.25416,4.70416),(10.25,2.3)).lineTo(9.438896,-2.3).threePointArc((8.44306,-4.70416),(6.038896,-5.7)).close().cutThruAll()

for idx in range(4):
    result = result.workplane(offset=1).center(-107,210-idx*h_sep).moveTo(-23.5,0).circle(1.6).moveTo(23.5,0).circle(1.6).moveTo(-17.038896,-5.7).threePointArc((-19.44306,-4.70416),(-20.438896,-2.3)).lineTo(-21.25,2.3).threePointArc((-20.25416,4.70416),(-17.85,5.7)).lineTo(17.85,5.7).threePointArc((20.25416,4.70416),(21.25,2.3)).lineTo(20.438896,-2.3).threePointArc((19.44306,-4.70416),(17.038896,-5.7)).close().cutThruAll()

for idx in range(4):
    result = result.workplane(offset=1).center(-107,-30-idx*h_sep).circle(14).rect(24.7487,24.7487, forConstruction=True).vertices().hole(3.2).cutThruAll()

for idx in range(8):
    result = result.workplane(offset=1).center(-173,225-idx*h_sep4DB9).moveTo(-12.5,0).circle(1.6).moveTo(12.5,0).circle(1.6).moveTo(-6.038896,-5.7).threePointArc((-8.44306,-4.70416),(-9.438896,-2.3)).lineTo(-10.25,2.3).threePointArc((-9.25416,4.70416),(-6.85,5.7)).lineTo(6.85,5.7).threePointArc((9.25416,4.70416),(10.25,2.3)).lineTo(9.438896,-2.3).threePointArc((8.44306,-4.70416),(6.038896,-5.7)).close().cutThruAll()

for idx in range(4):
    result = result.workplane(offset=1).center(-173,-30-idx*h_sep).moveTo(-2.9176,-5.3).threePointArc((-6.05,0),(-2.9176,5.3)).lineTo(2.9176,5.3).threePointArc((6.05,0),(2.9176,-5.3)).close().cutThruAll()

# Render the solid
show(result)

@dcowden
Copy link
Collaborator

dcowden commented Oct 10, 2015

How did you measure the distance between the rectangular holes?
On Oct 10, 2015 1:42 AM, "huskier" notifications@github.com wrote:

I am using CADQuery to create a panel with mounting holes, and I
positioned the holes with coordinates. However, the relative positions of
the holes are not inaccurate. Here is an example.

This example is meant to be used from within the CadQuery module of FreeCAD.

import cadquery
from Helpers import show

width = 100
height = 200
thickness = 2

Create a plate with two polygons cut through it

result = cadquery.Workplane("front").box(width, height, thickness)

result = result.faces("<Z").workplane(offset=0).center(0,30).rect(10,10).cutThruAll()
result = result.faces("<Z").workplane(offset=0).center(0,-30).rect(10,10).cutThruAll()
result = result.faces("<Z").workplane(offset=0).center(0,-60).rect(10,10).cutThruAll()

Render the solid

show(result)

I put the three rectangle holes at points (0,30), (0,-30) and (0, -60)
respectively. The distance between the first rect and the second rect holes
should be exactly 60, but I've got 60.1508. The distance between the second
rect and the third rect holes should be exactly 30, but CADQuery gives
29.8485. I don't know what's wrong with my code. Very weired!


Reply to this email directly or view it on GitHub
#60.

@huskier
Copy link
Contributor Author

huskier commented Oct 12, 2015

Dear David,

Once the model is generated in FreeCAD, I export the model as a STEP file; then, I use Solidworks, NX UG, and special measure menu(measure linear) inside FreeCAD's Part workbench, respectively. They all give the same results, ie. 60.1508 and 29.8485. For rectangular holes, I measure the distance between the corresponding sides, which is equal to the distance between the centers.

Still don't know the reason.

@dcowden
Copy link
Collaborator

dcowden commented Oct 12, 2015

I see, thank you.

Hmm. Well that is indeed strange.

This is a stretch, but can you try a couple of things:

( 1 ) use floating point numbers instead of integers in your script,

(2) try the same example but with all coordinates in positive space

Let's see if that changes anything. It shouldn't. But who knows.
On Oct 12, 2015 2:35 AM, "huskier" notifications@github.com wrote:

Dear David,

Once the model is generated in FreeCAD, I export the model as a STEP file;
then, I use Solidworks, NX UG, and special measure menu(measure linear)
inside FreeCAD's Part workbench, respectively. They all give the same
results, ie. 60.1508 and 29.8485. For rectangular holes, I measure the
distance between the corresponding sides, which is equal to the distance
between the centers.

Still don't know the reason.


Reply to this email directly or view it on GitHub
#60 (comment)
.

@huskier
Copy link
Contributor Author

huskier commented Oct 13, 2015

Dear David,
Following your suggestion, we have the code like:

import cadquery
from Helpers import show

width = 100.0
height = 200.0
thickness = 2.0

# Create a plate with two polygons cut through it
#result = cadquery.Workplane("front").center(50.0,100.0).box(width, height, thickness)
result = cadquery.Workplane("front").center(50.0,100.0).rect(width, height).extrude(thickness)

result = result.faces("<Z").workplane(offset=0.0).center(0.0,0.0).rect(10.0,10.0).cutThruAll()
result = result.faces("<Z").workplane(offset=0.0).center(0.0,60.0).rect(10.0,10.0).cutThruAll()
result = result.faces("<Z").workplane(offset=0.0).center(0.0,90.0).rect(10.0,10.0).cutThruAll()

# Render the solid
show(result)

This time, the distance between the first two rect is correct, i.e. 60; however, the distance between the second and the third rect is still inaccurate, and it tells 29.697.

I guess that maybe once an extra object is created, the algorithm in the center function change slightly than what we expect. NOT SURE.

Any idea how to debug this issue? Thanks.

@dcowden
Copy link
Collaborator

dcowden commented Oct 13, 2015

OH! it just struck me what may be going on. It is not the center()
operation, its something much more subtle-- the workplane function.

When you create a workplane, the default center of the workplane is located
at the center of mass of the face you have selected. For a rectangular
face with no holes, that's the geometric center. or, put another way, the
center of the bounding box of the shape.

But when you add holes to a face, the location of a workplane will no
longer be the geometric center. In your example, the center of mass has
changed ( very slightly ) by the removal of your first rectangle cut, which
creates the shift you are seeing.

I think you'll find that your example works as expected if you first
create all three of the rectangles, and then do one cut, like this:

Create a plate with two polygons cut through it

#result = cadquery.Workplane("front").center(50.0,100.0).box(width,
height, thickness)
result = cadquery.Workplane("front").center(50.0,100.0).rect(width,
height).extrude(thickness)

result = result.faces("<Z").workplane(offset=0.0).center(0.0,0.0).rect(10.0,10.0).rect(-10.0,10.0).rect(20.0,10.0).cutThruAll()

with this syntax, you are defining all three rectangles on a workplane
that is based on the center of your first box, which does in fact
correspond with the center of the box itself.

On Tue, Oct 13, 2015 at 4:49 AM, huskier notifications@github.com wrote:

Dear David,
Following your suggestion, we have the code like:

import cadquery
from Helpers import show

width = 100.0
height = 200.0
thickness = 2.0

Create a plate with two polygons cut through it

#result = cadquery.Workplane("front").center(50.0,100.0).box(width, height, thickness)
result = cadquery.Workplane("front").center(50.0,100.0).rect(width, height).extrude(thickness)

result = result.faces("<Z").workplane(offset=0.0).center(0.0,0.0).rect(10.0,10.0).cutThruAll()
result = result.faces("<Z").workplane(offset=0.0).center(0.0,60.0).rect(10.0,10.0).cutThruAll()
result = result.faces("<Z").workplane(offset=0.0).center(0.0,90.0).rect(10.0,10.0).cutThruAll()

Render the solid

show(result)

This time, the distance between the first two rect is correct, i.e. 60;
however, the distance between the second and the third rect is still
inaccurate, and it tells 29.697.

I guess that maybe once an extra object is created, the algorithm in the
center function change slightly than what we expect. NOT SURE.

Any idea how to debug this issue? Thanks.


Reply to this email directly or view it on GitHub
#60 (comment)
.

@huskier
Copy link
Contributor Author

huskier commented Oct 14, 2015

YES, you are right. With the syntax:

result = result.faces("<Z").workplane(offset=0.0).center(0.0,0.0).rect(10.0,10.0).rect(-10.0,10.0).rect(20.0,10.0).cutThruAll()

#OR
result = result.faces("<Z").workplane(offset=0.0).center(0.0,0.0).pushPoints([(0.0,30.0),(0.0,60.0),(0.0,90.0)]).rect(10.0,10.0).cutThruAll()

I could get the right answer. But the problem is that what I created is not a simple rect, and it is a complex sketch, so I could not use the syntax like creating three rectangles, except that we have a function called draw2DSketch which do the complex sketch. However, the draw2DSketch function is more harder than polygon function, since polygon stores all the points, and draw2DSketch needs to store wires. I could not deal with so complex issue right now.

Could you please give some suggestion how to write function draw2DSketch, or sketch for simple and short? For the draw2DSketch function, I think the coordinates corresponding (the sketch and the targeting workplane) should be considered properly. And I think draw2DSketch, then extrude OR cut into 3D is a typical application. I am looking forward to your help.

@dcowden
Copy link
Collaborator

dcowden commented Oct 14, 2015

ok cool, so we have explained whats going on, that's a good first step.

Jeremy has recently made a change that allows polygon to add edges instead
of wires, so that it is interoperable with lineTo, moveTo, etc.

you have a couple of options from here:

(1) you can draw all of the 2d stuff before cutting/extruding. that's
probably the preferred approach. you could consider using polygon in
combination with moveTo to 'pick up the pencil' and move to a different
point, relative to the previous center, without defining a new workplane,
like:
Workplane("XY").rect(10,0).moveTo(20.0,10.0).rect(10,10). ..

(2) you can use your previous code, but instead of re-defining a new
workplane each time, save a reference to the old work plane and keep
re-using it. that should work fine as well. if you keep the workplan as it
was, it will not change, and you can cut-extrude each rectangle one at a
time as you did before....

On Tue, Oct 13, 2015 at 8:43 PM, huskier notifications@github.com wrote:

YES, you are right. With the syntax:

result = result.faces("<Z").workplane(offset=0.0).center(0.0,0.0).rect(10.0,10.0).rect(-10.0,10.0).rect(20.0,10.0).cutThruAll()

I could get the right answer. But the problem is that what I created is
not a simple rect, and it is a complex sketch, so I could not use the
syntax like creating three rectangles, except that we have a function
called draw2DSketch which do the complex sketch. However, the draw2DSketch
function is much harder than polygon function, since polygon stores all the
points, and draw2DSketch needs to store wires. I could not deal with so
complex issue right now.


Reply to this email directly or view it on GitHub
#60 (comment)
.

@huskier
Copy link
Contributor Author

huskier commented Oct 14, 2015

I prefer option 2. Following your option 2, we've the following code, and Only two rectangles are got, not as expected.

# This example is meant to be used from within the CadQuery module of FreeCAD.
import cadquery
from Helpers import show

width = 100.0
height = 200.0
thickness = 2.0

# Create a plate with two polygons cut through it
result = cadquery.Workplane("front").center(50.0,100.0).rect(width, height).extrude(thickness)

ref_wp = result.faces("<Z").workplane(offset=0.0)

result1 = ref_wp.center(0.0,0.0).rect(10.0,10.0).cutThruAll()
result2 = ref_wp.center(0.0,60.0).rect(10.0,10.0).cutThruAll()
result3 = ref_wp.center(0.0,90.0).rect(10.0,10.0).cutThruAll()

# Render the solid
show(result3)

For option 1, it is not realistic in my application, because my code is quite complex:

# This example is meant to be used from within the CadQuery module of FreeCAD.
import cadquery
from Helpers import show

# The dimensions of the model. These can be modified rather than changing the
# object's code directly.
width = 400
height = 500
thickness = 2

# Create a plate with two polygons cut through it
result = cadquery.Workplane("front").box(width, height, thickness)

h_sep = 60
for idx in range(4):
    result = result.workplane(offset=1).center(157,210-idx*h_sep).moveTo(-23.5,0).circle(1.6).moveTo(23.5,0).circle(1.6).moveTo(-17.038896,-5.7).threePointArc((-19.44306,-4.70416),(-20.438896,-2.3)).lineTo(-21.25,2.3).threePointArc((-20.25416,4.70416),(-17.85,5.7)).lineTo(17.85,5.7).threePointArc((20.25416,4.70416),(21.25,2.3)).lineTo(20.438896,-2.3).threePointArc((19.44306,-4.70416),(17.038896,-5.7)).close().cutThruAll()

for idx in range(4):
    result = result.workplane(offset=1).center(157,-30-idx*h_sep).moveTo(-16.65,0).circle(1.6).moveTo(16.65,0).circle(1.6).moveTo(-10.1889,-5.7).threePointArc((-12.59306,-4.70416),(-13.5889,-2.3)).lineTo(-14.4,2.3).threePointArc((-13.40416,4.70416),(-11,5.7)).lineTo(11,5.7).threePointArc((13.40416,4.70416),(14.4,2.3)).lineTo(13.5889,-2.3).threePointArc((12.59306,-4.70416),(10.1889,-5.7)).close().cutThruAll()

h_sep4DB9 = 30
for idx in range(8):
    result = result.workplane(offset=1).center(91,225-idx*h_sep4DB9).moveTo(-12.5,0).circle(1.6).moveTo(12.5,0).circle(1.6).moveTo(-6.038896,-5.7).threePointArc((-8.44306,-4.70416),(-9.438896,-2.3)).lineTo(-10.25,2.3).threePointArc((-9.25416,4.70416),(-6.85,5.7)).lineTo(6.85,5.7).threePointArc((9.25416,4.70416),(10.25,2.3)).lineTo(9.438896,-2.3).threePointArc((8.44306,-4.70416),(6.038896,-5.7)).close().cutThruAll()

for idx in range(4):
    result = result.workplane(offset=1).center(25,210-idx*h_sep).moveTo(-23.5,0).circle(1.6).moveTo(23.5,0).circle(1.6).moveTo(-17.038896,-5.7).threePointArc((-19.44306,-4.70416),(-20.438896,-2.3)).lineTo(-21.25,2.3).threePointArc((-20.25416,4.70416),(-17.85,5.7)).lineTo(17.85,5.7).threePointArc((20.25416,4.70416),(21.25,2.3)).lineTo(20.438896,-2.3).threePointArc((19.44306,-4.70416),(17.038896,-5.7)).close().cutThruAll()

for idx in range(4):
    result = result.workplane(offset=1).center(25,-30-idx*h_sep).moveTo(-16.65,0).circle(1.6).moveTo(16.65,0).circle(1.6).moveTo(-10.1889,-5.7).threePointArc((-12.59306,-4.70416),(-13.5889,-2.3)).lineTo(-14.4,2.3).threePointArc((-13.40416,4.70416),(-11,5.7)).lineTo(11,5.7).threePointArc((13.40416,4.70416),(14.4,2.3)).lineTo(13.5889,-2.3).threePointArc((12.59306,-4.70416),(10.1889,-5.7)).close().cutThruAll()

for idx in range(8):
    result = result.workplane(offset=1).center(-41,225-idx*h_sep4DB9).moveTo(-12.5,0).circle(1.6).moveTo(12.5,0).circle(1.6).moveTo(-6.038896,-5.7).threePointArc((-8.44306,-4.70416),(-9.438896,-2.3)).lineTo(-10.25,2.3).threePointArc((-9.25416,4.70416),(-6.85,5.7)).lineTo(6.85,5.7).threePointArc((9.25416,4.70416),(10.25,2.3)).lineTo(9.438896,-2.3).threePointArc((8.44306,-4.70416),(6.038896,-5.7)).close().cutThruAll()

for idx in range(4):
    result = result.workplane(offset=1).center(-107,210-idx*h_sep).moveTo(-23.5,0).circle(1.6).moveTo(23.5,0).circle(1.6).moveTo(-17.038896,-5.7).threePointArc((-19.44306,-4.70416),(-20.438896,-2.3)).lineTo(-21.25,2.3).threePointArc((-20.25416,4.70416),(-17.85,5.7)).lineTo(17.85,5.7).threePointArc((20.25416,4.70416),(21.25,2.3)).lineTo(20.438896,-2.3).threePointArc((19.44306,-4.70416),(17.038896,-5.7)).close().cutThruAll()

for idx in range(4):
    result = result.workplane(offset=1).center(-107,-30-idx*h_sep).circle(14).rect(24.7487,24.7487, forConstruction=True).vertices().hole(3.2).cutThruAll()

for idx in range(8):
    result = result.workplane(offset=1).center(-173,225-idx*h_sep4DB9).moveTo(-12.5,0).circle(1.6).moveTo(12.5,0).circle(1.6).moveTo(-6.038896,-5.7).threePointArc((-8.44306,-4.70416),(-9.438896,-2.3)).lineTo(-10.25,2.3).threePointArc((-9.25416,4.70416),(-6.85,5.7)).lineTo(6.85,5.7).threePointArc((9.25416,4.70416),(10.25,2.3)).lineTo(9.438896,-2.3).threePointArc((8.44306,-4.70416),(6.038896,-5.7)).close().cutThruAll()

for idx in range(4):
    result = result.workplane(offset=1).center(-173,-30-idx*h_sep).moveTo(-2.9176,-5.3).threePointArc((-6.05,0),(-2.9176,5.3)).lineTo(2.9176,5.3).threePointArc((6.05,0),(2.9176,-5.3)).close().cutThruAll()

# Render the solid
show(result)

@dcowden
Copy link
Collaborator

dcowden commented Oct 14, 2015

ok yeah i see what you mean-- for option 1 to work, you'd need to define a
function for that code. its doable-- to do that, you would actually add
your function onto the cq object.

the idea there would be to make your function, and then add it to the cq
object, like explained here: http://parametricparts.com/docs/extending.html

alternatively, you can make option 2 work if you do some old-fashioned
solid geometry, something like this ( not tested ):

This example is meant to be used from within the CadQuery module of FreeCAD.

import cadquery
from Helpers import show

width = 100.0
height = 200.0
thickness = 2.0

Create a plate with two polygons cut through it

result = cadquery.Workplane("front").center(50.0,100.0).rect(width,
height).extrude(thickness)

ref_wp = result.faces("<Z").workplane(offset=0.0)

result1 = ref_wp.center(0.0,0.0).rect(10.0,10.0).extrude()
result2 = ref_wp.center(0.0,60.0).rect(10.0,10.0).extrude()
result3 = ref_wp.center(0.0,90.0).rect(10.0,10.0).extrude()

result4 = result.cut(result1)

result4 = result4.cut(result2)

result4 = result4.cut(result3)

Render the solid

show(result4)

On Tue, Oct 13, 2015 at 9:18 PM, huskier notifications@github.com wrote:

I prefer option 2. Following your option 2, we've the following code, and
Only two rectangles are got, not as expected.

This example is meant to be used from within the CadQuery module of FreeCAD.

import cadquery
from Helpers import show

width = 100.0
height = 200.0
thickness = 2.0

Create a plate with two polygons cut through it

result = cadquery.Workplane("front").center(50.0,100.0).rect(width, height).extrude(thickness)

ref_wp = result.faces("<Z").workplane(offset=0.0)

result1 = ref_wp.center(0.0,0.0).rect(10.0,10.0).cutThruAll()
result2 = ref_wp.center(0.0,60.0).rect(10.0,10.0).cutThruAll()
result3 = ref_wp.center(0.0,90.0).rect(10.0,10.0).cutThruAll()

Render the solid

show(result3)

For option 1, it is not realistic, because my code is quite complex:

This example is meant to be used from within the CadQuery module of FreeCAD.

import cadquery
from Helpers import show

The dimensions of the model. These can be modified rather than changing the

object's code directly.

width = 400
height = 500
thickness = 2

Create a plate with two polygons cut through it

result = cadquery.Workplane("front").box(width, height, thickness)

h_sep = 60
for idx in range(4):
result = result.workplane(offset=1).center(157,210-idx*h_sep).moveTo(-23.5,0).circle(1.6).moveTo(23.5,0).circle(1.6).moveTo(-17.038896,-5.7).threePointArc((-19.44306,-4.70416),(-20.438896,-2.3)).lineTo(-21.25,2.3).threePointArc((-20.25416,4.70416),(-17.85,5.7)).lineTo(17.85,5.7).threePointArc((20.25416,4.70416),(21.25,2.3)).lineTo(20.438896,-2.3).threePointArc((19.44306,-4.70416),(17.038896,-5.7)).close().cutThruAll()

for idx in range(4):
result = result.workplane(offset=1).center(157,-30-idx*h_sep).moveTo(-16.65,0).circle(1.6).moveTo(16.65,0).circle(1.6).moveTo(-10.1889,-5.7).threePointArc((-12.59306,-4.70416),(-13.5889,-2.3)).lineTo(-14.4,2.3).threePointArc((-13.40416,4.70416),(-11,5.7)).lineTo(11,5.7).threePointArc((13.40416,4.70416),(14.4,2.3)).lineTo(13.5889,-2.3).threePointArc((12.59306,-4.70416),(10.1889,-5.7)).close().cutThruAll()

h_sep4DB9 = 30
for idx in range(8):
result = result.workplane(offset=1).center(91,225-idx*h_sep4DB9).moveTo(-12.5,0).circle(1.6).moveTo(12.5,0).circle(1.6).moveTo(-6.038896,-5.7).threePointArc((-8.44306,-4.70416),(-9.438896,-2.3)).lineTo(-10.25,2.3).threePointArc((-9.25416,4.70416),(-6.85,5.7)).lineTo(6.85,5.7).threePointArc((9.25416,4.70416),(10.25,2.3)).lineTo(9.438896,-2.3).threePointArc((8.44306,-4.70416),(6.038896,-5.7)).close().cutThruAll()

for idx in range(4):
result = result.workplane(offset=1).center(25,210-idx*h_sep).moveTo(-23.5,0).circle(1.6).moveTo(23.5,0).circle(1.6).moveTo(-17.038896,-5.7).threePointArc((-19.44306,-4.70416),(-20.438896,-2.3)).lineTo(-21.25,2.3).threePointArc((-20.25416,4.70416),(-17.85,5.7)).lineTo(17.85,5.7).threePointArc((20.25416,4.70416),(21.25,2.3)).lineTo(20.438896,-2.3).threePointArc((19.44306,-4.70416),(17.038896,-5.7)).close().cutThruAll()

for idx in range(4):
result = result.workplane(offset=1).center(25,-30-idx*h_sep).moveTo(-16.65,0).circle(1.6).moveTo(16.65,0).circle(1.6).moveTo(-10.1889,-5.7).threePointArc((-12.59306,-4.70416),(-13.5889,-2.3)).lineTo(-14.4,2.3).threePointArc((-13.40416,4.70416),(-11,5.7)).lineTo(11,5.7).threePointArc((13.40416,4.70416),(14.4,2.3)).lineTo(13.5889,-2.3).threePointArc((12.59306,-4.70416),(10.1889,-5.7)).close().cutThruAll()

for idx in range(8):
result = result.workplane(offset=1).center(-41,225-idx*h_sep4DB9).moveTo(-12.5,0).circle(1.6).moveTo(12.5,0).circle(1.6).moveTo(-6.038896,-5.7).threePointArc((-8.44306,-4.70416),(-9.438896,-2.3)).lineTo(-10.25,2.3).threePointArc((-9.25416,4.70416),(-6.85,5.7)).lineTo(6.85,5.7).threePointArc((9.25416,4.70416),(10.25,2.3)).lineTo(9.438896,-2.3).threePointArc((8.44306,-4.70416),(6.038896,-5.7)).close().cutThruAll()

for idx in range(4):
result = result.workplane(offset=1).center(-107,210-idx*h_sep).moveTo(-23.5,0).circle(1.6).moveTo(23.5,0).circle(1.6).moveTo(-17.038896,-5.7).threePointArc((-19.44306,-4.70416),(-20.438896,-2.3)).lineTo(-21.25,2.3).threePointArc((-20.25416,4.70416),(-17.85,5.7)).lineTo(17.85,5.7).threePointArc((20.25416,4.70416),(21.25,2.3)).lineTo(20.438896,-2.3).threePointArc((19.44306,-4.70416),(17.038896,-5.7)).close().cutThruAll()

for idx in range(4):
result = result.workplane(offset=1).center(-107,-30-idx*h_sep).circle(14).rect(24.7487,24.7487, forConstruction=True).vertices().hole(3.2).cutThruAll()

for idx in range(8):
result = result.workplane(offset=1).center(-173,225-idx*h_sep4DB9).moveTo(-12.5,0).circle(1.6).moveTo(12.5,0).circle(1.6).moveTo(-6.038896,-5.7).threePointArc((-8.44306,-4.70416),(-9.438896,-2.3)).lineTo(-10.25,2.3).threePointArc((-9.25416,4.70416),(-6.85,5.7)).lineTo(6.85,5.7).threePointArc((9.25416,4.70416),(10.25,2.3)).lineTo(9.438896,-2.3).threePointArc((8.44306,-4.70416),(6.038896,-5.7)).close().cutThruAll()

for idx in range(4):
result = result.workplane(offset=1).center(-173,-30-idx*h_sep).moveTo(-2.9176,-5.3).threePointArc((-6.05,0),(-2.9176,5.3)).lineTo(2.9176,5.3).threePointArc((6.05,0),(2.9176,-5.3)).close().cutThruAll()

Render the solid

show(result)


Reply to this email directly or view it on GitHub
#60 (comment)
.

@huskier
Copy link
Contributor Author

huskier commented Oct 14, 2015

Personally, I like option 1. But for option 1, there is still some problems. We have to do all the sketch first, and then do 3D operation; otherwise the "center of mass" problem is still there. If we could change the behavior of "workplane", that would be much better. And my previous code just works fine without any change.

I will see how to make a workable function like draw2DSketch.

Another option is that:
Could we use the absolute coordination instead of local coordination in my code?

@dcowden
Copy link
Collaborator

dcowden commented Oct 14, 2015

what would you like the behavior of workplane() to be?

the other popular option is to choose the center of the bounding box. This
proved problemmatic because FreeCAD ( actually underlying OCC) sometimes
doesnt compute the bounding box for the current solid accurately. it
becomes unreliable when the part is complex.

We could consider allowing you to specify the coordinates of the center--
but then we'd need establish the basis for those coordinates. the previous
workplane? absolute coordinates?

On Tue, Oct 13, 2015 at 9:48 PM, huskier notifications@github.com wrote:

Personally, I like option 1. But for option 1, there is still some
problems. We have to do all the sketch first, and then do 3D operation;
otherwise the "center of mass" problem is still there. If we could change
the behavior of "workplane", that would be much better. And my previous
code just works fine without any change.


Reply to this email directly or view it on GitHub
#60 (comment)
.

@huskier
Copy link
Contributor Author

huskier commented Oct 14, 2015

"what would you like the behavior of workplane() to be?"
I'd like it gives geometric center instead of center of mass.

Thanks David.

I will keep learning the CADQuery code, and I hope I could do more contribution to the project, and make CADQuery more powerful in scripting 3D model.

@dcowden
Copy link
Collaborator

dcowden commented Oct 14, 2015

Yeah the geometric center has been discussed a couple of time before.

Unfortunately, for several reasons it won't work well. In the general case,
we would more specifically need to use the geometric center of the bounding
box of the face. This would produce the results you are wanting, but in
other cases it produces results that ore odd. This is because the OCC
algorithm for the bounding box calculation sometimes uses approximations to
be faster. For some geometry, the bounding box (and thus the center)are
not what is expected.

I wouldn't have an issue adding ability to define a workplace using the
geometric center, but we can't replace what's there now, it will break too
many existing scripts.

We would be happy to accept a pull request for a patch that adds this.
Perhaps we could add an optional center mode argument to the workplane
function that allows choosing bounding box center or center of mass, and
default it to the current behavior?
On Oct 13, 2015 10:56 PM, "huskier" notifications@github.com wrote:

"what would you like the behavior of workplane() to be?"
I'd like it gives geometric center instead of center of mass.

Thanks David.

I will keep learning the CADQuery code, and I hope I could do more
contribution to the project, and make CADQuery more powerful in scripting
3D model.


Reply to this email directly or view it on GitHub
#60 (comment)
.

@huskier
Copy link
Contributor Author

huskier commented Oct 15, 2015

Thanks David. I am trying to do something useful.

@jmwright
Copy link
Owner

Hi @huskier I just wanted to check in to see how you are doing with this.

@huskier
Copy link
Contributor Author

huskier commented Nov 21, 2015

@jmwright , following Dave's suggestion(using CenterOfBoundBox instead of CenterOfMass), I could get the correct result now. I am considering submit a pull request to the project. Thanks all of you.

@huskier huskier closed this as completed Nov 21, 2015
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

No branches or pull requests

3 participants