From 1bb85de18db146636bb14d188eb9c2ac99af079b Mon Sep 17 00:00:00 2001 From: Bill Reese Date: Sat, 13 Jan 2024 12:31:33 -0500 Subject: [PATCH] Fix for missing letters when V-carving a string. Issue 8064 occurs when FreeCAD passes a Voronoi diagram to Boost that becomes self-intersecting when Boost truncates the diagram's coordinates to integers. This occurs when the discretizer slightly misses closing the polygon generated for the letter by less that FreeCAD's epsilon, then the wrapping Python code closes the polygon by adding the initial polygon point as the final point. This creates a short segment that, depending on the position of the letter in the coordinate system, may end up being moved one Boost coordinate delta away from the intended point, which can end up self-intersecting. Since the miss is very small, FreeCAD should treat it as it it were the initial point. There's no need for a duplicate copy of the initial point, so we remove this point close to the initial point and let insert_many_wires() close the polygon as usual. --- src/Mod/Path/Path/Op/Vcarve.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Mod/Path/Path/Op/Vcarve.py b/src/Mod/Path/Path/Op/Vcarve.py index d91600335d..a40523c9df 100644 --- a/src/Mod/Path/Path/Op/Vcarve.py +++ b/src/Mod/Path/Path/Op/Vcarve.py @@ -264,9 +264,24 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): Path.Log.debug("discretize value: {}".format(obj.Discretize)) pts = wire.discretize(QuasiDeflection=obj.Discretize) ptv = [FreeCAD.Vector(p.x, p.y) for p in pts] + # Check over the last point before just closing the polygon + # by adding the start again. If the discretizer was aiming + # for the last point and missed by a little bit, closing the + # polygon as is could result in OpenVoronoi truncating the + # coordinates to a self-intersecting polygon which is invalid. + # Instead, if the last point is close to the first, remove it + # and let the final append close the polygon. + # See issue 8064 + if len(ptv) > 0: + dist = ptv[-1].distanceToPoint(ptv[0]) + if dist < FreeCAD.Base.Precision.confusion(): + Path.Log.debug( + "Removing bad carve point: {} from polygon origin" + .format(dist)) + del ptv[-1] ptv.append(ptv[0]) - for i in range(len(pts)): + for i in range(len(ptv)-1): vd.addSegment(ptv[i], ptv[i + 1]) def cutWire(edges):