Move Model Line (Curve Start Point) to Reference Point

Move Model Line (Curve Start Point) to Reference Point

Tom_Bionda
Enthusiast Enthusiast
193 Views
4 Replies
Message 1 of 5

Move Model Line (Curve Start Point) to Reference Point

Tom_Bionda
Enthusiast
Enthusiast

Hi All, 

 

Topic Title

Model Line Fails to Move to Floor Corner Reference Point in Dynamo + Revit — Vector Correct, Result Wrong.

 

Idea/Goal:

I want to move selected Revit model lines so that their start points align exactly with a known reference point (corner of a floor slab). The goal is precise geometric alignment using Dynamo and Python scripting within Dynamo.

I want to move selected Revit model lines so that their start points align exactly with a known reference point (corner of a floor slab). The goal is precise geometric alignment using Dynamo.

 

The Problem
Although I’m selecting Revit model lines using “Select Model Element” and calculating the correct displacement vector (confirmed via Watch nodes), the lines move inside Dynamo’s environment correctly but end up in completely unexpected places in the Revit model. Their new location is far from the intended reference point, sometimes even in the millions of units off in Y and Z direction.

 

Steps Taken:

 

  • Selected model lines via “Select Model Element.”

  • Retrieved Curve.StartPoint

  • Selected a floor corner as a reference point.

  • Calculated displacement vector using: (Code Block)

          dx = X_floor - X_line
           dy = Y_floor - Y_line
           dz = Z_floor - Z_line
           Vector.ByCoordinates(dx, dy, dz)

  • Verified that:

    • Vector length matches expected. (Measured in Revit direct distance, Calculated displecment vector length)

    • Vector was not nested (flattened properly).

  •   Used both:
  • 1ElementTransformUtils.MoveElement in Python script (custom node - to move in revit environment)

  • 2Element.MoveByVector (custom node) - because its moving line in dynamo environment but not revit,

  • Outcome in Dynamo is visually correct.

  • Outcome in Revit is incorrect — model line lands far from the floor point.

     

Debug Checks: 

 

  • Verified vector math is correct.

  • Confirmed curve and floor points are both in internal coordinates.

  • Measured displacement length manually — matches calculated vector.

  • Retrieved model line location via .GetLocation() and Curve.StartPoint — both confirm starting values match input.

Persistent Issue:

 

  • Despite correct vector and visible movement in Dynamo, the element ends up far off in Revit.

  • Moving lines via geometry only affects Dynamo preview, not Revit 3D view.

  • There seems to be a mismatch between geometry-based transformation and element-based transformation.

  • Z and Y coordinates appear to exaggerate by large magnitudes, even though vector math is simple and values are realistic.

Any suggestions what am I doing wrong in structure of nodes, any help would appreceate:

 

 

  • Why does this displacement vector fail in Revit while appearing correct in Dynamo?

  • How to confirm coordinate system (internal vs shared) of points in use?

  • Is ElementTransformUtils.MoveElement reliable in this context?

  • Would using a different transformation approach (e.g., Geometry.Transform) be better?

Thank you 

 

Please find dynamo graph attached

 

Edit: 15.08.2025

 

import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import ElementTransformUtils, XYZ

clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument

# Inputs
elements = IN[0]
vector_mm = IN[1]

# Convert to flat list
def flatten(input):
if isinstance(input, list):
result = []
for i in input:
result.extend(flatten(i))
return result
else:
return [input]

elements = flatten(elements)
elements = [UnwrapElement(e) for e in elements]

# Convert mm to feet
mm_to_ft = 1.0 / 304.8
try:
vector_ft = XYZ(
vector_mm.X * mm_to_ft,
vector_mm.Y * mm_to_ft,
vector_mm.Z * mm_to_ft
)
except:
vector_ft = vector_mm # fallback (if already XYZ in ft)

# Move elements
TransactionManager.Instance.EnsureInTransaction(doc)

moved = []
errors = []

for el in elements:
try:
ElementTransformUtils.MoveElement(doc, el.Id, vector_ft)
moved.append(el)
except Exception as e:
errors.append((el.Id, str(e)))

TransactionManager.Instance.TransactionTaskDone()

# Output
if errors:
OUT = ("Some elements failed to move", errors)
else:
OUT = ("All elements moved", moved)

 

I'm using Dynamo to move a Model Line (ModelCurve) in Revit via a displacement vector. The operation works correctly for the Y and Z directions, but fails silently for the X direction — the element does not move along X, and there is no error or warning.

After investigating, I’ve determined that this is due to the Model Line being associated with a Sketch Plane, which restricts its movement to the plane itself. Since ModelCurve.SketchPlane is a read-only property, it seems there is no way to detach the line or change its plane after creation.

 

Question:

 

Is there a way to detach or override the sketch plane of an existing Model Line so it becomes a free-floating element (i.e., can move in all directions)?

 

Thank you

 

 

 

 

 

0 Likes
Accepted solutions (1)
194 Views
4 Replies
Replies (4)
Message 2 of 5

ctm_mka
Collaborator
Collaborator

First, have you tried without the unit conversions? sometimes Revit is weird about that. Second regarding your vector calc, instead try importing, and using the transform class, like so: 

vector_ft = Transform.CreateTranslation(StartPt - targetPt)

  

0 Likes
Message 3 of 5

Tom_Bionda
Enthusiast
Enthusiast

Hi @ctm_mka

Apologies for the delayed response — I was away on a three-week holiday. I'm now back and continuing work on the code I previously shared and asked for your assistance with.

I've implemented your suggestions, but I'm still encountering issues with the X-axis movement — it's not behaving as expected. I'd appreciate it if you could take another look or offer further guidance.

Also, just to clarify, I do need to perform unit conversion. Without it, the model line is being positioned far from the reference point.

 

For ElementTransformUtils.TransformElements(...) - transform class i get error message: 

Move failed for element ID 2396418: type object 'ElementTransformUtils' has no attribute 'TransformElements'

 

And for ElementTransformUtils.MoveElement(...) i get error message:

X movement ignored for element ID 2396418

 

Updated Code - move class, not with transform class like you suggested, but i did try that too:

 

 import clr

# Revit API references
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import ElementTransformUtils, XYZ, LocationCurveTransform

# Revit Services references
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

# Dynamo geometry extensions
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)

doc = DocumentManager.Instance.CurrentDBDocument

def flatten(input):
    if isinstance(input, list):
        result = []
        for i in input:
            result.extend(flatten(i))
        return result
    else:
        return [input]

def to_xyz(pt):
    try:
        return pt.ToXyz()
    except:
        return pt

def get_start_point(element):
    location = element.Location
    if isinstance(location, LocationCurve😞
        return location.Curve.GetEndPoint(0)
    else:
        return None

# --- Inputs ---
elements_input = IN[0]
start_point_input = IN[1]
target_point_input = IN[2]

elements = [UnwrapElement(e) for e in flatten(elements_input)]
start_pt = to_xyz(flatten(start_point_input)[0])
target_pt = to_xyz(flatten(target_point_input)[0])

# Calculate vector per Autodesk suggestion (StartPt - TargetPt)
# This will move in the opposite direction (from start to target requires TargetPt - StartPt)
vector = XYZ(
    target_pt.X - start_pt.X,
    target_pt.Y - start_pt.Y,
    target_pt.Z - start_pt.Z
)

# For demonstration, create the Transform (not used in MoveElement)
translation_transform = Transform.CreateTranslation(vector)

TransactionManager.Instance.EnsureInTransaction(doc)

moved = []
warnings = []
tolerance = 0.001  # ~0.3 mm in feet

for el in elements:
    initial_pt = get_start_point(el)
    if initial_pt is None:
        warnings.append(f"⚠ Element ID {el.Id} has no valid LocationCurve.")
        continue

    try:
        # Use MoveElement with XYZ vector (not the Transform)
        ElementTransformUtils.MoveElement(doc, el.Id, vector)
        moved.append(el)

        final_pt = get_start_point(el)
        if final_pt:
            dx = abs(final_pt.X - initial_pt.X)
            dy = abs(final_pt.Y - initial_pt.Y)
            dz = abs(final_pt.Z - initial_pt.Z)

            if abs(vector.X) > tolerance and dx < tolerance:
                warnings.append(f"⚠ X movement ignored for element ID {el.Id}")
            if abs(vector.Y) > tolerance and dy < tolerance:
                warnings.append(f"⚠ Y movement ignored for element ID {el.Id}")
            if abs(vector.Z) > tolerance and dz < tolerance:
                warnings.append(f"⚠ Z movement ignored for element ID {el.Id}")
        else:
            warnings.append(f"⚠ End point not found after move for element ID {el.Id}")

    except Exception as e:
        warnings.append(f" Move failed for element ID {el.Id}: {str(e)}")

TransactionManager.Instance.TransactionTaskDone()

if warnings:
    OUT = ("Moved with warnings", warnings)
else:
    OUT = ("All elements moved successfully", moved)

0 Likes
Message 4 of 5

ctm_mka
Collaborator
Collaborator
Accepted solution

hrmm. so the issue is because you need to detach it from its ref plane, but move elements wont work. Perhaps trying "ElementTransformUtils.CopyElement" and deleting the original would do the trick? something like:

ElementTransformUtils.CopyElement(doc, el.id, vector) 
doc.delete(el.id)
0 Likes
Message 5 of 5

Tom_Bionda
Enthusiast
Enthusiast

Hi @ctm_mka 

 

I just wanted to sincerely thank you for your help with the issue I was facing in Dynamo/Revit.

Your suggestion to use ElementTransformUtils.CopyElement(...) combined with doc.Delete(...) was exactly what I needed. It completely solved the problem with model lines not moving due to reference plane constraints. I also now understand that the original elements couldn't be moved directly because of how Revit constrains them — and copying them with a translation vector effectively detaches them from those constraints.

I ended up building a Python script that:

  • Calculates the movement vector between a reference point and the element,

  • Copies the element using that vector,

  • Deletes the original,

  • And then safely validates the new position.

Your input really helped me get to the bottom of the issue — not only technically, but also conceptually. Thanks again for your time and guidance!

Best regards,

0 Likes