diff --git a/ahb_cmd_view_annotate.py b/ahb_cmd_view_annotate.py index a206935..a34d33e 100644 --- a/ahb_cmd_view_annotate.py +++ b/ahb_cmd_view_annotate.py @@ -1,3 +1,4 @@ +import math import FreeCADGui as Gui import FreeCAD as App @@ -73,5 +74,67 @@ class AHB_View_Annotate: workbench.techDrawExtensions.refreshOverlays(page) + regroupedBalloons = self.RegroupNearestSimilarBalloons(balloonsCreated) + self.PlaceBalloonsInCircle(regroupedBalloons) + + def CalculatePointsCenter(self, balloons): + totalX = 0 + totalY = 0 + for balloon in balloons: + realBalloon = balloon[0] if type(balloon) is list else balloon + totalX = totalX + int(realBalloon.OriginX) + totalY = totalY + int(realBalloon.OriginY) + return App.Base.Vector2d(totalX / len(balloons), totalY / len(balloons)) + + def IsSimilarBalloonNear(self, balloonA, balloonB): + MAX_DISTANCE_BETWEEN_REGROUPED_BALLOONS = 50 + if balloonA.Text == balloonB.Text: + pos = App.Base.Vector2d(balloonA.OriginX, balloonA.OriginY) + dist = pos.distance(App.Base.Vector2d(balloonB.OriginX, balloonB.OriginY)) + return dist < MAX_DISTANCE_BETWEEN_REGROUPED_BALLOONS + else: + return False + + def RegroupNearestSimilarBalloons(self, balloons): + regroupedBalloons = [] + for balloon in balloons: + nearestBalloons = [] + for otherBalloon in balloons: + if otherBalloon != balloon and self.IsSimilarBalloonNear(balloon, otherBalloon): + nearestBalloons.append(otherBalloon) + balloons.remove(otherBalloon) + if len(nearestBalloons) == 0: + regroupedBalloons.append(balloon) + else: + nearestBalloons.append(balloon) + regroupedBalloons.append(nearestBalloons) + return regroupedBalloons + + def PlaceBalloonsInCircle(self, balloons): + center = self.CalculatePointsCenter(balloons) + nbBalloons = len(balloons) + balloonPosStep = (math.pi * 2) / nbBalloons + for i in range(nbBalloons): + balloonPos = App.Base.Vector2d(center.x + 600 * math.cos(balloonPosStep * i), center.y + 600 * math.sin(balloonPosStep * i)) + # Find nearest arrow to avoid arrow crossing each other + smallestDistance = 0 + balloonToUse = None + for balloon in balloons: + realBalloon = balloon[0] if type(balloon) is list else balloon + dist = balloonPos.distance(App.Base.Vector2d(realBalloon.OriginX, realBalloon.OriginY)) + if smallestDistance == 0 or dist < smallestDistance: + smallestDistance = dist + balloonToUse = balloon + + if balloonToUse is not None: + balloons.remove(balloonToUse) + if type(balloonToUse) is list: + for realBalloon in balloonToUse: + realBalloon.X = balloonPos.x + realBalloon.Y = balloonPos.y + else: + balloonToUse.X = balloonPos.x + balloonToUse.Y = balloonPos.y + from ahb_command import AHB_CommandWrapper AHB_CommandWrapper.addGuiCommand('AHB_view_annotate', AHB_View_Annotate()) diff --git a/ahb_techdraw_extensions.py b/ahb_techdraw_extensions.py index c57e86d..1d7a0d3 100644 --- a/ahb_techdraw_extensions.py +++ b/ahb_techdraw_extensions.py @@ -457,6 +457,7 @@ class TechDrawExtensions: self.updating_balloon = False def add_or_update_balloon(self, view, part, parent_path): + balloonsCreated = [] page = self.getViewPage(view) overlay_view = self.getOverlayView(view) doc = page.Document @@ -498,8 +499,7 @@ class TechDrawExtensions: self.updateBalloon(balloon) - balloon.X = int(balloon.OriginX) + 20 - balloon.Y = int(balloon.OriginY) + 20 + balloonsCreated.append(balloon) if not self.isNewPartInView(view, part): balloon.ViewObject.Visibility = False