cadquery icon indicating copy to clipboard operation
cadquery copied to clipboard

Cut operation doesn't work

Open RubenRubens opened this issue 4 years ago • 8 comments

Tested with the latest CQ version provided on conda

I'm working on a nut and the last cut operation fails, this is, there is no thread. The thing is that when using union instead of cut the operation is successfully performed. I cannot tell if it's my fault or a bug.

The code

import cadquery as cq
from math import sin, cos, tan, pi

# Parameters
d = 10
p = 1.50
da = 10.40
dw = 14.60
e = 17.77
m = 8.10
s = 16
angle = 30 * pi / 180

# Constant
H = 0.866 * p

# Gemetry
def cutting_hexagon():
	points = [
		(s/2, 0),
		(e, 0),
		(e, e * sin(angle))
	]

	a = (
		cq.Workplane('YZ')
		.polyline(points).close()
		.revolve()
	)

	b = a.mirror('XY', (0, 0, m/2))

	return a.union(b)

def internal_iso_thread():
	# Helix
	helix = cq.Workplane('XY').parametricCurve(
	lambda t : (
			d/2 * cos(t * 2 * pi),
			d/2 * sin(t * 2 * pi),
			p * t
		),
		start = 0,
		stop = m/p
	)

	# Face
	A = H/8 / tan(pi/3)
	B = A * tan(pi/6)
	C = A / cos(pi/6)
	face = (
		cq.Workplane('XZ')
		.center(d/2, 0)
		.moveTo(0, A)
		.threePointArc((C-B, 0), (0, -A))
		.lineTo(-7/8 * H, -H/2)
		.lineTo(-7/8 * H, H/2)
		.lineTo(0, A)
		.close()
	)

	return face.sweep(helix, isFrenet=True)

def core():
	def circumscribed(nSides, inscribedDiameter):
		angle = 1/(nSides * 2) * 2 * pi
		return inscribedDiameter / cos(angle)

	return (
		cq.Workplane('XY')
		.polygon(6, circumscribed(6, s))
		.circle(d / 2 - 3/8 * H)
		.extrude(m)
	)

result = (
	core()
	.cut(cutting_hexagon())
	.cut(internal_iso_thread())
)

result.val().exportStep('bug.step')

The result

result

The issue

cq_nut

RubenRubens avatar Dec 02 '20 21:12 RubenRubens

We have run into kernel bugs fairly often with threads. For example: #407

I can confirm that the thread isn't cut in CQ-editor, so it's not an export issue. You could try a couple of things to see if they help, and then we can try to figure out how to work around whatever is going on.

  1. Increase the diameter of the thread coil so that more (or all) of the thread solid intersects with the nut core.
  2. Shorten the height of the coil so that it does not extend above (or below) the nut core.

jmwright avatar Dec 03 '20 14:12 jmwright

For what it's worth, boundary conditions with cutting and more generally with coincident faces are common with all BREP kernels, even professional ones like Parasolid. It feels dirty, but the old 'make one part slightly bigger by some trivial amount' trick works wonders.

On Thu, Dec 3, 2020 at 9:05 AM Jeremy Wright [email protected] wrote:

We have run into kernel bugs fairly often with threads. For example: #407 https://github.com/CadQuery/cadquery/issues/407

I can confirm that the thread isn't cut in CQ-editor, so it's not an export issue. You could try a couple of things to see if they help, and then we can try to figure out how to work around whatever is going on.

  1. Increase the diameter of the thread coil so that more (or all) of the thread solid intersects with the nut core.
  2. Shorten the height of the coil so that it does not extend above (or below) the nut core.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/CadQuery/cadquery/issues/529#issuecomment-738014719, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJ44AYNLUSGQYSJYKVYBVDSS6LK3ANCNFSM4ULC576A .

dcowden avatar Dec 03 '20 14:12 dcowden

Here is how you can make it work: image

import cadquery as cq
from math import sin, cos, tan, pi

# Parameters
d = 10
p = 1.50
da = 10.40
dw = 14.60
e = 17.77
m = 8.10
s = 16
angle = 30 * pi / 180

# Constant
H = 0.866 * p

# Gemetry
def cutting_hexagon():
	points = [
		(s/2, 0),
		(e, 0),
		(e, e * sin(angle))
	]

	a = (
		cq.Workplane('YZ')
		.polyline(points).close()
		.revolve()
	)

	b = a.mirror('XY', (0, 0, m/2))

	return a.union(b)

def internal_iso_thread():
	# Helix
	helix = cq.Workplane('XY',origin=(0,0,-1)).parametricCurve(
	lambda t : (
			d/2 * cos(t * 2 * pi),
			d/2 * sin(t * 2 * pi),
			p * t
		),
		start = 0,
		stop = 2*m/p
	)

	# Face
	A = H/8 / tan(pi/3)
	B = A * tan(pi/6)
	C = A / cos(pi/6)
	face = (
		cq.Workplane('XZ')
		.center(d/2, 0)
		.moveTo(0, A)
		.threePointArc((C-B, 0), (0, -A))
		.lineTo(-7/8 * H, -H/2)
		.lineTo(-7/8 * H, H/2)
		.lineTo(0, A)
		.close()
	)

	return face.sweep(helix, isFrenet=True)

def core():
	def circumscribed(nSides, inscribedDiameter):
		angle = 1/(nSides * 2) * 2 * pi
		return inscribedDiameter / cos(angle)

	return (
		cq.Workplane('XY')
		.polygon(6, circumscribed(6, s))
		.circle(d / 2 - 3/8 * H)
		.extrude(m)
	)

thread = (
    internal_iso_thread()
    .transformed((-90,0,0))
    .split(True)
    .transformed((0,0,0),(0,0,m))
    .split(False, True)
    )

result = (
	core()
	.cut(cutting_hexagon())
	.cut(thread,clean=False)
)

adam-urbanczyk avatar Dec 03 '20 16:12 adam-urbanczyk

wow @adam-urbanczyk nice!

@RubenRubens would you consider the idea of promoting this code to a core operation available as a convenience operation, similar to counterbores?

It wouldn't take much at all to convert the code above to automatically apply this code to a selected cylindrical face to create an internal or external thread, which would be immensely helpful when you need threads!

dcowden avatar Dec 03 '20 18:12 dcowden

Cool! @dcowden you can do whatever makes you happy with the code above. I might consider to do a PR myself...

RubenRubens avatar Dec 29 '20 19:12 RubenRubens

Getting some very strange results using this with the latest version to try and make internal threads. Had similar results with twisted threads when using another example I found (when using specific sets of params for height and pitch in particular). Not sure what might be causing this:

image

jpoles1 avatar Aug 05 '22 21:08 jpoles1

It looks like there were changes to parametricCurve since these examples were created, see issue #682.

lorenzncode avatar Aug 07 '22 19:08 lorenzncode

Had similar results with twisted threads when using another example I found (when using specific sets of params for height and pitch in particular).

@jpoles1 In my testing, specifying parametricCurve(..., smoothing=None) resolves the problem.

lorenzncode avatar Aug 07 '22 22:08 lorenzncode