It has been noted/discussed in at least two other threads that shaping operations (Weld, Trim, Boundary, etc.) can sometime produce content that will initially have correct geometry, but that can unexpectedly become distorted when some types of node editing operations are performed.
Annoying bug when working with curvers!
Nodes convert on weld, objects distort when nodes moved
My observations are that this has to do with nodes that were Symmetrical nodes before the shaping operation, but should have been changed to Smooth nodes as a result of the shaping operation. These nodes cannot be Symmetrical and produce the correct geometry, but they are still identified as being Symmetrical. Note in this screenshot that the node is identified as being Symmetrical, but the control points are not equal distances away from the node (as they should be if a node is Symmetrical).
If certain node editing operations are performed, such nodes appear to "wake up" and assert their Symmetrical identity - which distorts the geometry.One way to work around this is to perform the shaping operation, then manually find every such node and change it from Symmetrical to Smooth. Depending on the complexity of the shape, that might be very tedious.As a less-tedious workaround, here is a VBA macro I wrote that checks each node in a Curve that is identified as Symmetrical. If the control points are not equal distances from the node, then that node is considered to be a "bogus" Symmetrical node, and is changed to Smooth.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
Option Explicit Sub fix_bogus_symmetrical_nodes() Dim sr As ShapeRange Dim s As Shape Dim nodeThis As Node Const dblLengthToleranceTenthMicrons As Double = 50 Dim lngNodesChangedCounter As Long Const strMacroName As String = "Fix Bogus Symmetrical Nodes" On Error GoTo ErrHandler EventsEnabled = False Optimization = True ActiveDocument.BeginCommandGroup "Fix Bogus Symmetrical Nodes" Set sr = ActiveSelectionRange If sr.Count = 1 Then If sr(1).Type = cdrCurveShape Then Set s = sr(1) For Each nodeThis In s.Curve.Nodes If nodeThis.Type = cdrSymmetricalNode Then If Abs(nodeThis.PrevSegment.EndingControlPointLength - nodeThis.NextSegment.StartingControlPointLength) > ActiveDocument.ToUnits(dblLengthToleranceTenthMicrons, cdrTenthMicron) Then nodeThis.Type = cdrSmoothNode lngNodesChangedCounter = lngNodesChangedCounter + 1 End If End If Next nodeThis MsgBox "Number of nodes changed: " & lngNodesChangedCounter, vbInformation, strMacroName Else MsgBox "Selection is not a Curve.", vbInformation, strMacroName End If Else MsgBox "Exactly one Curve shape must be selected.", vbInformation, strMacroName End If ExitSub: ActiveDocument.EndCommandGroup Optimization = False EventsEnabled = True Exit Sub ErrHandler: MsgBox "Error occured: " & Err.Description Resume ExitSub End Sub
That same code is in the .GMS file in this.ZIP archive:
JQ_Fix_Bogus_Symmetrical_Nodes - GMS in ZIP
Here is a short video showing an example of a situation where this bug shows up, and how changing those "bogus" Symmetrical nodes to Smooth can be used to correct the problem:
VIDEO: Fix Bogus Symmetrical Nodes
.
Thing two: my earlier approach to this does not work if the Curve contains two or more consecutive "bogus" Symmetrical nodes.
It plays out something like this:
So, a different, "two-pass" approach can be used:
The code looks like this now:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
Sub fix_bogus_symmetrical_nodes() Dim sr As ShapeRange Dim s As Shape Dim nodeThis As Node Const dblAngleTolerance As Double = 0.001 Const dblLengthToleranceTenthMicrons As Double = 50 Dim action_arr() As String Dim controlpoints_arr() As Double Dim lngNodeIndex_getting As Long Dim lngNodeIndex_setting As Long Dim lngNodesChangedToCuspCount As Long Dim lngNodesChangedToSmoothCount As Long Const strMacroName As String = "Fix Bogus Symmetrical Nodes" On Error GoTo ErrHandler EventsEnabled = False Optimization = True ActiveDocument.BeginCommandGroup "Fix Bogus Symmetrical Nodes" Set sr = ActiveSelectionRange If sr.Count = 1 Then If sr(1).Type = cdrCurveShape Then Set s = sr(1) ReDim action_arr(s.Curve.Nodes.Count + 1) ReDim controlpoints_arr(s.Curve.Nodes.Count + 1, 4) For lngNodeIndex_getting = 1 To s.Curve.Nodes.Count Set nodeThis = s.Curve.Nodes(lngNodeIndex_getting) If nodeThis.Type = cdrSymmetricalNode Then If Abs(Abs(nodeThis.Segment.EndingControlPointAngle - nodeThis.NextSegment.StartingControlPointAngle) - 180) > dblAngleTolerance Then action_arr(lngNodeIndex_getting) = "C" If nodeThis.Segment.Type = cdrCurveSegment Then controlpoints_arr(lngNodeIndex_getting, 1) = nodeThis.Segment.EndingControlPointX controlpoints_arr(lngNodeIndex_getting, 2) = nodeThis.Segment.EndingControlPointY End If If nodeThis.NextSegment.Type = cdrCurveSegment Then controlpoints_arr(lngNodeIndex_getting, 3) = nodeThis.NextSegment.StartingControlPointX controlpoints_arr(lngNodeIndex_getting, 4) = nodeThis.NextSegment.StartingControlPointY End If Else If Abs(nodeThis.Segment.EndingControlPointLength - nodeThis.NextSegment.StartingControlPointLength) > ActiveDocument.ToUnits(dblLengthToleranceTenthMicrons, cdrTenthMicron) Then action_arr(lngNodeIndex_getting) = "S" controlpoints_arr(lngNodeIndex_getting, 1) = nodeThis.Segment.EndingControlPointX controlpoints_arr(lngNodeIndex_getting, 2) = nodeThis.Segment.EndingControlPointY controlpoints_arr(lngNodeIndex_getting, 3) = nodeThis.NextSegment.StartingControlPointX controlpoints_arr(lngNodeIndex_getting, 4) = nodeThis.NextSegment.StartingControlPointY End If End If End If Next lngNodeIndex_getting For lngNodeIndex_setting = 1 To s.Curve.Nodes.Count Set nodeThis = s.Curve.Nodes(lngNodeIndex_setting) If action_arr(lngNodeIndex_setting) = "C" Then nodeThis.Type = cdrCuspNode If nodeThis.Segment.Type = cdrCurveSegment Then nodeThis.Segment.EndingControlPointX = controlpoints_arr(lngNodeIndex_setting, 1) nodeThis.Segment.EndingControlPointY = controlpoints_arr(lngNodeIndex_setting, 2) End If If nodeThis.NextSegment.Type = cdrCurveSegment Then nodeThis.NextSegment.StartingControlPointX = controlpoints_arr(lngNodeIndex_setting, 3) nodeThis.NextSegment.StartingControlPointY = controlpoints_arr(lngNodeIndex_setting, 4) End If lngNodesChangedToCuspCount = lngNodesChangedToCuspCount + 1 Else If action_arr(lngNodeIndex_setting) = "S" Then nodeThis.Type = cdrSmoothNode nodeThis.Segment.EndingControlPointX = controlpoints_arr(lngNodeIndex_setting, 1) nodeThis.Segment.EndingControlPointY = controlpoints_arr(lngNodeIndex_setting, 2) nodeThis.NextSegment.StartingControlPointX = controlpoints_arr(lngNodeIndex_setting, 3) nodeThis.NextSegment.StartingControlPointY = controlpoints_arr(lngNodeIndex_setting, 4) lngNodesChangedToSmoothCount = lngNodesChangedToSmoothCount + 1 End If End If Next lngNodeIndex_setting MsgBox "Number of nodes changed to Smooth: " & lngNodesChangedToSmoothCount & vbCrLf & vbCrLf & "Number of nodes changed to Cusp: " & lngNodesChangedToCuspCount, vbInformation, strMacroName Else MsgBox "Selection is not a Curve.", vbInformation, strMacroName End If Else MsgBox "Exactly one Curve shape must be selected.", vbInformation, strMacroName End If ExitSub: ActiveDocument.EndCommandGroup Optimization = False EventsEnabled = True Exit Sub ErrHandler: MsgBox "Error occured: " & Err.Description Resume ExitSub End Sub
Here is a new .GMS file:
JQ_Fix_Bogus_Symmetrical_Nodes _2018_07_03_0808.zip.
Here is a short video showing it working on consecutive bogus Symmetrical nodes. It's a simple but fairly dramatic example of how badly geometry can be distorted by these bogus nodes:
VIDEO: Fix Bogus Symmetrical Nodes 2.
Thanks Eskimo. Nice work. Works with X7 too.
Myron said:Thanks Eskimo. Nice work. Works with X7 too.
Thanks, Myron.
That .GMS file came from X7.
The oldest version of CorelDRAW that I have installed at this time is X3, and the the same "bogus Symmetrical nodes" problem is present in that version.
Pasting the same code into an X3 project, it seems to work just fine there.