Hello, code ninjas. I was wondering if someone here may have a better approach what I am doing (that sometimes produces errors as well).
Task is getting rid of incisions of an object outline. Basically making the lines smooth from a certain size.
This is my current approach - applying an outside contour, breaking it apart and then applying same size inside contour and thus getting a clean path. But it seems a little inefficient and sometimes produces errors (when small details are too close to one another). May there be some other, more efficient way to do this?
Thanks in advance!
Edit: The sample is a rectangle just for clarity, in reality we are dealing with all sorts of random shapes, so it cannot just be replaced.
Edit 2: Looks like I am using the same method that Shelby came up with here: https://forum.oberonplace.com/showpost.php?p=6874&postcount=3 so chances of there being something better do not seem that great. But, perhaps, something has changed over time. Aiming at 2018 at the moment, but this may justify a later version if it offers something new.
How about examining the curve and identifying the cusp nodes that are the "sharp points" of those incisions? Perhaps by using the angles of the control points of the two segments that involve that node?
Here's something you could look at:
Sub test_it() Dim s As Shape Dim noderangeThis As New NodeRange Set s = ActiveShape examine_curve_and_identify_sharp_point_nodes s.Curve, 5, noderangeThis noderangeThis.Delete Refresh End Sub Function examine_curve_and_identify_sharp_point_nodes(ByVal SourceCurve As Curve, ByVal CPAngleTolerance As Double, ByRef SharpPointNodeRange As NodeRange) As Boolean Dim nodeThis As Node Dim lngNodeIndex_subpath_getting As Long Dim subPathThis As SubPath On Error GoTo ErrHandler For Each subPathThis In SourceCurve.SubPaths If subPathThis.Closed Then For lngNodeIndex_subpath_getting = 1 To subPathThis.Nodes.Count Set nodeThis = subPathThis.Nodes(lngNodeIndex_subpath_getting) If nodeThis.Type = cdrCuspNode Then If nodeThis.Segment.Type = cdrLineSegment And nodeThis.NextSegment.Type = cdrLineSegment Then If AnglesAreClose(nodeThis.Segment.EndingControlPointAngle, nodeThis.NextSegment.StartingControlPointAngle, CPAngleTolerance) Then SharpPointNodeRange.Add nodeThis End If End If End If Next lngNodeIndex_subpath_getting End If Next subPathThis ExitFunc: Exit Function ErrHandler: MsgBox "Error occurred: " & Err.Description & vbCrLf & vbCrLf & "examine_curve_and_identify_sharp_point_nodes()", vbExclamation Resume ExitFunc End Function Public Function AnglesAreClose(ByRef Angle_A As Double, ByRef Angle_B As Double, ByRef Tolerance As Double) As Boolean If Abs(Angle_A - Angle_B) < Tolerance Then AnglesAreClose = True Else If (Angle_A >= 0 And Angle_A <= Tolerance) And (Angle_B <= 360 And Angle_B >= 360 - Tolerance) Then If Angle_A + (360 - Angle_B) < Tolerance Then AnglesAreClose = True End If Else If (Angle_A <= 360 And Angle_A >= 360 - Tolerance) And (Angle_B >= 0 And Angle_B <= Tolerance) Then If (360 - Angle_A) + Angle_B < Tolerance Then AnglesAreClose = True End If End If End If End If End Function
One demonstration:
WOW. This in incredible. An interesting approach and seems to work really, really well. It is also about 5 times faster than the method I used so far.
Will need to modify it just a little to remove inside shapes, but so far it is really impressive.
Thanks!
Edit: Forgot to say that the code is a beauty as well.