<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Auto Tagging without overlap in Revit API Forum</title>
    <link>https://forums.autodesk.com/t5/revit-api-forum/auto-tagging-without-overlap/m-p/10036648#M29131</link>
    <description>&lt;P&gt;&amp;gt;&amp;nbsp;&lt;SPAN&gt;It might work better with smaller tags.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;LOL. If you make the tags small enough, the problem will disappear entirely, along with the tags.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thank you very much for the explanation. Brute force and effective, given time. I love that straightforward approach!&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Wed, 27 Jan 2021 20:45:22 GMT</pubDate>
    <dc:creator>jeremy_tammik</dc:creator>
    <dc:date>2021-01-27T20:45:22Z</dc:date>
    <item>
      <title>Auto Tagging without overlap</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/auto-tagging-without-overlap/m-p/9996808#M29126</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I'm trying to make a python script to auto-tag all doors and place them without clashing with other tags or doors . I'm using a custom smart tag which is much bigger than typical door tag. I hope to use this concept with other types of tagging.&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;&lt;P&gt;Issue i'm having is that I cannot get the tag location to verify against list of points to avoid. and also to add the new tag location to the list so that the next tag does not clash with the previous.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I think the problem is the list of location to avoid is not properly updating and it's not correctly checking against it.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Any help would be appreciated.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thanks&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;doorFiltered = list of doors&lt;/PRE&gt;&lt;PRE&gt;TagSymbols = custom smart tag&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="general"&gt;import clr
clr.AddReference('System')
clr.AddReference("System.Drawing")
clr.AddReference("System.Windows.Forms")
clr.AddReference("RevitAPI")
clr.AddReference('RevitAPIUI')
clr.AddReference("System.Collections")
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit import DB
from pyrevit import forms, revit, DB, script
from itertools import compress
from operator import itemgetter, attrgetter

app = __revit__.Application
doc = __revit__.ActiveUIDocument.Document

scaleFactor = 5

def move_right(x,y,z):
    n = scaleFactor
    return x+n, y, z

def move_down(x,y,z):
    n = scaleFactor
    return x,y-n,z

def move_left(x,y,z):
    n = scaleFactor
    return x-n,y,z

def move_up(x,y,z):
    n = scaleFactor
    return x,y+n,z

moves = [move_right, move_down, move_left, move_up]

def shift(end, point):
    from itertools import cycle
    _moves = cycle(moves)
    n = 1
    pos = point
    times_to_move = 1

    yield pos

    while True:
        for _ in range(2):
            move = next(_moves)
            for _ in range(times_to_move):
                if n &amp;gt;= end:
                    return
                pos = move(*pos)
                n+=1
                yield pos

        times_to_move+=1

avoidLoc = []
for l in doorFiltered:
    avoidLoc.append(l.Location.Point)

for d in doorFiltered:
    LP = d.Location
    levelPoint = LP.Point

    startpoint = (levelPoint.X, levelPoint.Y, levelPoint.Z)
    shiftPoint = DB.XYZ(levelPoint.X, levelPoint.Y, levelPoint.Z)
    R = Reference(d)
    #create door tags
    t = Transaction(doc)
    t.Start('tag doors')
    IT = IndependentTag.Create(doc, v.Id, R, False, TagMode.TM_ADDBY_CATEGORY, TagOrientation.Horizontal, shiftPoint)
    IT.ChangeTypeId(TagSymbols)
    #get location of tag
    tagBB = IT.get_BoundingBox(doc.GetElement(IT.OwnerViewId))
    globalMax = tagBB.Max
    globalMin = tagBB.Min
    BBloc = XYZ((globalMax.X + globalMin.X)/2, (globalMax.Y + globalMin.Y)/2, globalMax.Z)
    tagSize = globalMax.DistanceTo(globalMin)
    originalPoint = (BBloc.X, BBloc.Y, BBloc.Z)

    #find overlap
    requireDist = tagSize*2

    overlap = True
    counter = 1

    while overlap:
        spiralPoints = list(shift(counter, startpoint))
        newPoint = spiralPoints[-1]
        counter += 1
        testPoint = DB.XYZ(newPoint[0], newPoint[1], newPoint[2])

        for i in avoidLoc:
            OriginalPoint = DB.XYZ(newPoint[0], newPoint[1], newPoint[2])
            tagDist = OriginalPoint.DistanceTo(i)
            movePoint = DB.XYZ((BBloc.X-newPoint[0]), (BBloc.Y-newPoint[1]), (BBloc.Z-newPoint[2]))
            #print(tagDist)
            if tagDist &amp;lt; requireDist:
                overlap = True
                #print("overlap")
            else:
                overlap = False
                IT.Location.Move(movePoint)
                NtagBB = IT.get_BoundingBox(doc.GetElement(IT.OwnerViewId))
                if NtagBB == None:
                    break
                NglobalMax = NtagBB.Max
                NglobalMin = NtagBB.Min
                NBBloc = XYZ((NglobalMax.X + NglobalMin.X) / 2, (NglobalMax.Y + NglobalMin.Y) / 2, NglobalMax.Z)
                avoidLoc.append(NBBloc)
                #print(NBBloc)
                break
    IT.HasLeader = True
    #IT.LeaderElbow = DB.XYZ(shiftPoint.X + 10, shiftPoint.Y, shiftPoint.Z)
    t.Commit()&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 12 Jan 2021 20:40:36 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/auto-tagging-without-overlap/m-p/9996808#M29126</guid>
      <dc:creator>ckepner</dc:creator>
      <dc:date>2021-01-12T20:40:36Z</dc:date>
    </item>
    <item>
      <title>Re: Auto Tagging without overlap</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/auto-tagging-without-overlap/m-p/9997053#M29127</link>
      <description>&lt;P&gt;Thank you for sharing this interesting and simple approach.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You need to regenerate the model after each adjustment to be able to query the correct updated locations, cf., the&amp;nbsp;Need to Regenerate:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://thebuildingcoder.typepad.com/blog/about-the-author.html#5.33" target="_blank"&gt;https://thebuildingcoder.typepad.com/blog/about-the-author.html#5.33&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If you are interested in other more complex ways to approach this task, you might want to explore various&amp;nbsp;map labelling algorithms to find the optimal placements for your tags:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://duckduckgo.com/?q=map+labelling+algorithm" target="_blank" rel="nofollow noopener noreferrer"&gt;https://duckduckgo.com/?q=map+labelling+algorithm&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I look forward to hearing how you end up solving this!&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 12 Jan 2021 22:11:01 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/auto-tagging-without-overlap/m-p/9997053#M29127</guid>
      <dc:creator>jeremytammik</dc:creator>
      <dc:date>2021-01-12T22:11:01Z</dc:date>
    </item>
    <item>
      <title>Re: Auto Tagging without overlap</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/auto-tagging-without-overlap/m-p/10000143#M29128</link>
      <description>&lt;P&gt;I've found a solution that seems to work.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="markup"&gt;avoidLoc = []
for l in doorFiltered:
    f = l.Location.Point
    fxs = DB.XYZ(f.X, f.Y, f.Z)
    avoidLoc.append(fxs)
# print(elemLoc)

for d in doorFiltered:
    LP = d.Location
    levelPoint = LP.Point
    # avoidLoc.append(levelPoint)
    startpoint = (levelPoint.X, levelPoint.Y, levelPoint.Z)
    shiftPoint = DB.XYZ(levelPoint.X, levelPoint.Y, levelPoint.Z)
    R = Reference(d)
    # create door tags
    tx = Transaction(doc)
    tx.Start('tag doors')
    IT = IndependentTag.Create(doc, v.Id, R, False, TagMode.TM_ADDBY_CATEGORY, TagOrientation.Horizontal, shiftPoint)
    IT.ChangeTypeId(TagSymbols)
    tx.Commit()

    # get location of tag
    tagBB = IT.get_BoundingBox(doc.GetElement(IT.OwnerViewId))
    globalMax = tagBB.Max
    globalMin = tagBB.Min
    BBloc = XYZ((globalMax.X + globalMin.X) / 2, (globalMax.Y + globalMin.Y) / 2, globalMax.Z)
    tagSize = globalMax.DistanceTo(globalMin)
    originalPoint = (BBloc.X, BBloc.Y, BBloc.Z)

    # find overlap
    requireDist = tagSize

    overlap = True
    counter = 1
    avoidLoc1 = avoidLoc
    while overlap:

        spiralPoints = list(shift(counter, originalPoint))
        newPoint = spiralPoints[-1]
        counter += 1

        testPoint = DB.XYZ(newPoint[0], newPoint[1], newPoint[2])
        tagDistx = []
        for s in avoidLoc1:
            tDist = testPoint.DistanceTo(s)
            # print(tDist)
            tagDistx.append(tDist)

        movePoint = DB.XYZ((newPoint[0] - levelPoint.X), (newPoint[1] - levelPoint.Y), (newPoint[2] - levelPoint.Z))

        if any(x &amp;lt; requireDist for x in tagDistx):

            continue
        if movePoint == None:

            print('NtagBB - empty')
            continue
        if all(x &amp;gt; requireDist for x in tagDistx):

            tx = Transaction(doc)
            tx.Start('move tag')
            IT.Location.Move(movePoint)

            NtagBB = IT.get_BoundingBox(doc.GetElement(IT.OwnerViewId))
            NglobalMax = NtagBB.Max
            NglobalMin = NtagBB.Min
            NBBloc = XYZ((NglobalMax.X + NglobalMin.X) / 2, (NglobalMax.Y + NglobalMin.Y) / 2, NglobalMax.Z)
            tx.Commit()
            avoidLoc.append(NBBloc)
            avoidLoc1.append(NBBloc)
            print("location found")
            overlap = False
            break
        else:
            print('no match')
            break

    tx = Transaction(doc)
    tx.Start('add leader')
    IT.HasLeader = True
    IT.LeaderElbow = DB.XYZ(shiftPoint.X + 10, shiftPoint.Y, shiftPoint.Z)
    tx.Commit()&lt;/LI-CODE&gt;</description>
      <pubDate>Thu, 14 Jan 2021 02:25:12 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/auto-tagging-without-overlap/m-p/10000143#M29128</guid>
      <dc:creator>ckepner</dc:creator>
      <dc:date>2021-01-14T02:25:12Z</dc:date>
    </item>
    <item>
      <title>Re: Auto Tagging without overlap</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/auto-tagging-without-overlap/m-p/10002222#M29129</link>
      <description>&lt;P&gt;Dear Christopher,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Congratulations on solving this tricky task and thank you for sharing it.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Would you care to describe briefly in words how your algorithm works?&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;It is not obvious from me just looking at it, and seems a bit challenging to work out by reverse engineering your code.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thank you!&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Cheers,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Jeremy&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 14 Jan 2021 19:18:39 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/auto-tagging-without-overlap/m-p/10002222#M29129</guid>
      <dc:creator>jeremytammik</dc:creator>
      <dc:date>2021-01-14T19:18:39Z</dc:date>
    </item>
    <item>
      <title>Re: Auto Tagging without overlap</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/auto-tagging-without-overlap/m-p/10036344#M29130</link>
      <description>&lt;P&gt;Sure,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;It starts with a list of doors in the variable doorFiltered.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;1. Location point of the first door in the list is fed into the function below to provide a test point to see if it overlaps any location points in the list of doors.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="markup"&gt;def move_right(x,y,z):
    n = scaleFactor
    return x+n, y, z

def move_down(x,y,z):
    n = scaleFactor
    return x,y-n,z

def move_left(x,y,z):
    n = scaleFactor
    return x-n,y,z

def move_up(x,y,z):
    n = scaleFactor
    return x,y+n,z

moves = [move_right, move_down, move_left, move_up]

def shift(end, point):
    from itertools import cycle
    _moves = cycle(moves)
    n = 1
    pos = point
    times_to_move = 1

    yield pos

    while True:
        for _ in range(2):
            move = next(_moves)
            for _ in range(times_to_move):
                if n &amp;gt;= end:
                    return
                pos = move(*pos)
                n+=1
                yield pos

        times_to_move+=1&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;2. If the point lands too close to any door locations in the list, the code adds a integer to the function and runs again to provide the next test point. Each time the function is re-run, the next point follows a spiral pattern from the origin (location point of the first door)&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-left" image-alt="download.jfif" style="width: 200px;"&gt;&lt;img src="https://forums.autodesk.com/t5/image/serverpage/image-id/872999i03CF8E1C300F3DE0/image-size/small?v=v2&amp;amp;px=200" role="button" title="download.jfif" alt="download.jfif" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;3. Once a point is found thats far enough from the list of door locations, a tag is placed and the tag location is added to the list of door locations.&lt;/P&gt;&lt;P&gt;4. The process loops to the next door, checking against the list of door location plus the new tag location.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Its a working concept but the output is inconsistant. Issues include:&lt;/P&gt;&lt;P&gt;Tags occasionally overlap with eachother.&lt;/P&gt;&lt;P&gt;The process takes a while. there's tons of points it tests that fail.&lt;/P&gt;&lt;P&gt;Tag location it finds does not work well with leaders. the tags land in every direction from the door creating overlap of leaders. It might work better with smaller tags.&lt;/P&gt;</description>
      <pubDate>Wed, 27 Jan 2021 18:58:06 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/auto-tagging-without-overlap/m-p/10036344#M29130</guid>
      <dc:creator>ckepner</dc:creator>
      <dc:date>2021-01-27T18:58:06Z</dc:date>
    </item>
    <item>
      <title>Re: Auto Tagging without overlap</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/auto-tagging-without-overlap/m-p/10036648#M29131</link>
      <description>&lt;P&gt;&amp;gt;&amp;nbsp;&lt;SPAN&gt;It might work better with smaller tags.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;LOL. If you make the tags small enough, the problem will disappear entirely, along with the tags.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thank you very much for the explanation. Brute force and effective, given time. I love that straightforward approach!&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 27 Jan 2021 20:45:22 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/auto-tagging-without-overlap/m-p/10036648#M29131</guid>
      <dc:creator>jeremy_tammik</dc:creator>
      <dc:date>2021-01-27T20:45:22Z</dc:date>
    </item>
    <item>
      <title>Re: Auto Tagging without overlap</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/auto-tagging-without-overlap/m-p/10041106#M29132</link>
      <description>&lt;P&gt;This other tagging conversation also mentions a couple of useful possibilities:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://forums.autodesk.com/t5/revit-api-forum/tags-without-overlapping/m-p/7750631" target="_blank"&gt;https://forums.autodesk.com/t5/revit-api-forum/tags-without-overlapping/m-p/7750631&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 29 Jan 2021 08:47:25 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/auto-tagging-without-overlap/m-p/10041106#M29132</guid>
      <dc:creator>jeremy_tammik</dc:creator>
      <dc:date>2021-01-29T08:47:25Z</dc:date>
    </item>
    <item>
      <title>Re: Auto Tagging without overlap</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/auto-tagging-without-overlap/m-p/11274278#M29133</link>
      <description>&lt;P&gt;As suggested by&amp;nbsp;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/413917"&gt;@jeremytammik&lt;/a&gt;&amp;nbsp;it's not a trivial problem.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;We have developed a solution to this problem using machine learning and AI. Our algorithms leverage fast and parallelizable techniques that we developed for calculating overlaps between rectangles (for tag/tag and tag/object collision detection) and overlaps between lines and rectangles (for leader line/tag/objection collision detection).&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Using these algorithms and cloud computing, we calculate the best location for each tag and its leader line to avoid collision with other tags, objects, and their leader lines.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The solution also considers tag alignment as an objective to reach a nice outcome. You can try our method here: &lt;A href="https://bimlogiq.com/products/smart-annotataion" target="_blank"&gt;https://bimlogiq.com/products/smart-annotataion&lt;/A&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Feel free to reach out if you would like to discuss it any further.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thanks&amp;nbsp;&lt;/P&gt;&lt;P&gt;Ali&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 03 Jul 2022 12:00:09 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/auto-tagging-without-overlap/m-p/11274278#M29133</guid>
      <dc:creator>aliAANV4</dc:creator>
      <dc:date>2022-07-03T12:00:09Z</dc:date>
    </item>
  </channel>
</rss>

