Clash panel
Clear Clash
Point at two faces and type the gap to leave; the selected object slides the exact difference, clash or no clash, and you read off how far it moved.
What it does#
Objects clash, and the usual next step is to drag one with Item Tools until it clears, read the offset and type it into the authoring tool. This does the dragging. Select the object that should move, point at the face of it that is in the way and the face it must clear, and a prompt shows the gap as it is now and asks for the gap to leave. The object slides along those faces' normal by exactly the difference, then a dialog tells you how far, ready to type into Revit.
The same button handles the cases that are not clashes: a run of services that should sit tighter to free a corridor, or a tray that needs another 100 mm of air for a duct to pass. It moves the object towards the other face or away from it, whichever the gap needs.
How to use it#
- Select the object that should move, say the pipe.
- Click Clear Clash. The native Point to Point measure opens and the banner along the bottom of the window asks for the face of the pipe that must move.
- Click the underside of the pipe. The banner now asks for the face it must clear.
- Click the top of the beam. A prompt reads "Pipe 1234 is 152.4 mm into Beam 7. Gap to leave between the two faces, in millimeters, or with a unit like 2" or 0.1m:", opening on the gap you used last time.
- Press Enter to keep that gap, or type another. The pipe slides up and a dialog reads "Moved Pipe 1234 by 152.4 mm".
- Click Copy in the dialog and paste the bare distance into the authoring tool. Ctrl+Z puts the pipe back in Navisworks.
A clash review stays at two clicks and Enter: set the gap once, and every later clash opens on it.
Pipes and conduits#
Navisworks draws a pipe as a ring of narrow flat strips, and none of them is parallel to anything, so a round object is measured differently. Against a flat face, such as a wall, a beam or the underside of a duct, the flat face sets the direction and the pipe is measured to its real surface, only where it is in front of that face. It does not matter where on the pipe you click, and a sloped pipe under a beam clears at the crossing, not at its high end. Two straight pipes or conduits are measured axis to axis, less both radii, and the mover slides along the line where they come closest: straight down for two level pipes that cross. The gap between two parallel pipes on a rack is the air between them.
Limitations#
- Only the two faces are considered. A part of the object that sticks out past the face you clicked is not checked against the obstacle, and pulling an object tighter can push another part of it into something else.
- Two flat faces must be parallel. Skewed faces are refused on the banner before the prompt opens, so you never type a number that cannot be used.
- Two round objects work only as straight runs. An elbow, a tee or a rounded fixture against another round object is refused; click a flat face on one of them instead.
- The gap cannot be negative. To bury one object in another on purpose, use Item Tools.
- The move is a Navisworks transform, the same one Item Tools makes. It changes the review model only, never the source file; the number is what goes back to the author.
Other uses#
- A quick "what if": move the pipe, see whether it now hits the ceiling, undo.
- Checking whether a tighter arrangement fits: set the gap, look, undo.
- Sloping soffits and rotated walls work as well as floors, because the faces come from the objects' own triangles rather than the world axes.
Good to know#
The prompt reads a length the way Revit does. In a feet-and-inches document that means
1' 6", 1'-6 1/2", 6 1/2", 3/4",
1.5', 18in or the space form 1 6 (feet, then inches);
a bare number is in the document's own unit, and a metric value with its unit, such as
25mm, works in any document. Anything it cannot read, it asks for again, saying
what it could not read.
Esc, a right-click, choosing another tool or cancelling the prompt leaves everything as it
was, quietly. The last gap you gave is stored with its unit in resolve_clash.json,
so 25 mm stays 25 mm in a feet-and-inches document and the next prompt opens on it. If you
set a clearance with Shift+Click in an earlier version, the first prompt opens on that. There
is no Shift+Click: the prompt is where the gap is set.
Source#
The tool's own files, word for word as shipped in Clash.panel/Clear_Clash.pushbutton. Every pyNavis tool is an ordinary bundle: copy these into your own extension and change what you like.
script.py Runs on a click. View on GitHub"""Moves the selected object so the face you point at sits exactly a chosen
gap from the face it must clear, and tells you how far, so the fix can be
typed straight into the authoring tool.
Select the object that should move and click. The native Point to Point
measure opens and the banner along the bottom of the window asks for two
faces: one on the object, then the one it must clear. Both faces are found
from the items' own triangles (pynavis.faces); two flat faces must be
parallel, a pipe or conduit is measured to its real surface from a flat
face, and two straight pipes outside to outside (see facemove). Anything
that cannot be measured is refused on the banner before a number is asked
for. A prompt then shows the gap as it is now ("Pipe 1 is 3in into Beam 7",
"Tray 42 is 350 mm from Duct 7") and asks for the gap to leave, prefilled
with the one used last, so Enter accepts it and a clash review stays at two
clicks and Enter. Before any gap has been given, the clearance older
versions set with Shift+Click is the starting value. The prompt reads
lengths the way Revit does (1' 6 1/2", 3/4", 1 6, 25mm; forms.ask_length)
and asks again on anything it cannot read. The object slides by exactly the
difference, tighter or apart, clash or no clash. The move is the same
permanent transform Item Tools > Transform makes; Ctrl+Z reverses it. The
distance goes in a dialog that stays until dismissed, ready to copy;
refusals and "already there" stay on the banner. Nothing is drawn in the
view. There is no Shift+Click: the prompt is where the gap is set, every
time.
Everything above the guard at the bottom is importable without Navisworks;
see lib/facemove.py for the maths and the words.
"""
import facemove
from pynavis import app, banner, faces, forms, geometry, pick, script, selection, settings
from pynavis.clash import units_to_meters
def names_of(items):
return facemove.label([str(item.DisplayName or item.ClassDisplayName or '')
for item in items])
def triangles_of(items, log):
"""Every triangle of what moves: the whole selection, which is what must
end up clear. Every item is read; what fails is logged."""
triangles = []
for item in items:
notes = []
triangles.extend(geometry.world_triangles(item, note=notes.append))
if notes:
log.info('mover "%s": %s' % (item.DisplayName, notes[0]))
return triangles
def run():
from pynavis._api import Api
doc = app.get_doc()
log = script.get_logger()
mover = selection.get_items()
if not mover:
banner.info('Nothing selected', 'Select the object that should move, then click.')
return
mover_name = names_of(mover)
banner.clear()
measured = pick.measure_points('Click the face of %s that must move' % mover_name,
'Now click the face it must clear',
notify=banner.prompt, keep=False)
if measured is None:
banner.clear()
return # Esc, right-click or another tool: say nothing
p1, p2 = measured
values = settings.load(facemove.TOOL, facemove.DEFAULTS)
units = str(doc.Units)
last_gap = facemove.starting_gap(values, units)
view = doc.ActiveView
first, end = Api.Point3D(p1[0], p1[1], p1[2]), Api.Point3D(p2[0], p2[1], p2[2])
log.info('measurement %s -> %s, units %s, last gap %s' % (p1, p2, units, last_gap))
meters = units_to_meters(doc)
tol = faces.tolerance_for((p1, p2), meters)
floor = faces.tolerance_for((), meters)
mover_side = faces.surface_under(view, first, tol, log, 'mover', floor=floor)
obstacle_side = faces.surface_under(view, end, tol, log, 'obstacle', floor=floor)
mover_item, obstacle_item = mover_side['item'], obstacle_side['item']
obstacle_name = (str(obstacle_item.DisplayName or obstacle_item.ClassDisplayName or '')
if obstacle_item is not None else 'the obstacle')
if mover_item is not None and not any(mover_item.Equals(m) for m in mover):
log.warning('first point is on "%s", which is not in the selection'
% mover_item.DisplayName)
body = triangles_of(mover, log)
shapes = {'mover_triangles': mover_side['triangles'],
'obstacle_triangles': obstacle_side['triangles'],
'mover_body': body, 'tol': max(mover_side['tol'], obstacle_side['tol'])}
def plan(target):
return facemove.plan(p1, mover_side['faces'], p2, obstacle_side['faces'],
[tri[0] for tri in body], target, **shapes)
# Find the faces before asking for the number, so a refusal (no face,
# not parallel, nothing in front) never makes the user type a gap that
# cannot be used.
situation = plan(last_gap)
log.info('situation %s' % situation)
if situation['status'] in facemove.REFUSALS:
level, title, detail = facemove.describe(situation, units, mover_name, obstacle_name)
banner.show(level, title, detail)
return
banner.clear()
state = facemove.gap_state(situation['gap'], units, mover_name, obstacle_name)
target = forms.ask_length(facemove.gap_prompt(state, units), units,
default=last_gap, title='Clear Clash')
if target is None:
return # cancelled: say nothing
# The gap just given is the one the next prompt opens on.
settings.save(facemove.TOOL, facemove.remember(target, units))
result = plan(float(target))
log.info('plan %s' % result)
if result['status'] == 'moved':
moved = geometry.translate(mover, result['vector'], doc, name='Resolve clash')
log.info('moved %d item(s) by %s' % (moved, result['vector']))
selection.set_items(mover, doc)
level, title, detail = facemove.describe(result, units, mover_name, obstacle_name)
if result['status'] == 'moved':
# The number is what the user came for and will type elsewhere: it
# must outlive a glance, so it waits to be dismissed.
forms.alert(title + chr(10) + chr(10) + detail, title='Clear Clash',
copy=facemove.format_length(abs(result['move']), units))
else:
banner.show(level, title, detail)
if '__commandpath__' in globals():
run()bundle.yaml The bundle contract: the keys pyNavis reads for this tool. View on GitHubtitle: Clear\nClash
tooltip: Two clicks and Enter. Select the object that should move and click, then click the face of it that is in the way and the face it must clear. A prompt shows the gap as it is now and asks for the gap to leave, opening on the one you used last; type it the way you would in Revit, like 3", 1' 6 1/2" or 25mm. The object slides the exact difference, tighter or apart, clash or no clash, pipes and conduits measured to their real surface, and a dialog says how far, ready to type into the authoring tool. Ctrl+Z puts it back.
context: doc