Hello Dynamo Friends
I made a little dynamo tool that connects model lines and another one that rounds the corner.
How can I manipulate the extents of the model line to trim it to the arc so I don´t have to do it manually?
I don´t want to create a new mode line, the extents of the existing one should be modified.
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
clr.AddReference('System.Windows.Forms')
clr.AddReference('System.Drawing')
import System
from System.Windows.Forms import Form, Label, TextBox, Button
from System.Drawing import Size
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
import math
import traceback
class InputForm(Form):
def __init__(self):
self.InitializeComponent()
def InitializeComponent(self):
self.Text = 'Enter Number'
self.Size = Size(400,400)
self.label = Label()
self.label.Text = 'Enter a number:'
self.label.Location = System.Drawing.Point(10, 20)
self.label.Size = Size(180, 20)
self.Controls.Add(self.label)
self.textBox = TextBox()
self.textBox.Location = System.Drawing.Point(10, 50)
self.textBox.Size = Size(180, 20)
# Set a default value for the textBox here
self.textBox.Text = '1'
self.Controls.Add(self.textBox)
self.button = Button()
self.button.Text = 'OK'
self.button.Location = System.Drawing.Point(60, 80)
self.button.Click += self.button_click
self.Controls.Add(self.button)
def button_click(self, sender, e):
self.DialogResult = System.Windows.Forms.DialogResult.OK
self.Close()
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
# Function to get the line style of a Revit model curve
def get_line_style(curve_element):
try:
# Adjust this method according to your Revit API version and element type
line_style_id = curve_element.LineStyle.Id
return doc.GetElement(line_style_id)
except Exception as e:
raise Exception(f"Error in get_line_style: {e}\n{traceback.format_exc()}")
# Function to apply a line style to a Revit model curve
def apply_line_style(dynamo_model_curve, graphics_style):
try:
if dynamo_model_curve and graphics_style:
# Retrieve the underlying Revit element
revit_model_curve = dynamo_model_curve.InternalElement
# Start a transaction
TransactionManager.Instance.EnsureInTransaction(doc)
# Access and set the line style parameter using the ElementId of the GraphicsStyle
line_style_parameter = revit_model_curve.LookupParameter("Line Style") # Revit parameter name
if line_style_parameter and not line_style_parameter.IsReadOnly:
# Use the ElementId of the GraphicsStyle object
line_style_parameter.Set(graphics_style.Id)
else:
raise Exception("Line style parameter is not available or read-only.")
TransactionManager.Instance.TransactionTaskDone()
else:
raise Exception("Model curve or graphics style is None")
except Exception as e:
raise Exception(f"Error in apply_line_style: {e}\n{traceback.format_exc()}")
# Function to find the common endpoint and distinct endpoints of two lines
def find_endpoints(line1, line2):
try:
endpoints1 = [line1.StartPoint, line1.EndPoint]
endpoints2 = [line2.StartPoint, line2.EndPoint]
for pt1 in endpoints1:
for pt2 in endpoints2:
if pt1.IsAlmostEqualTo(pt2):
distinct1 = line1.StartPoint if pt1.IsAlmostEqualTo(line1.EndPoint) else line1.EndPoint
distinct2 = line2.StartPoint if pt2.IsAlmostEqualTo(line2.EndPoint) else line2.EndPoint
return (pt1, distinct1, distinct2)
raise Exception("No common endpoint found")
except Exception as e:
raise Exception(f"Error in find_endpoints: {e}\n{traceback.format_exc()}")
# Function to calculate the bisector of two vectors
def calculate_bisector(vec1, vec2):
try:
vec1 = vec1.Normalized()
vec2 = vec2.Normalized()
return vec1.Add(vec2).Normalized()
except Exception as e:
raise Exception(f"Error in calculate_bisector: {e}\n{traceback.format_exc()}")
# Function to find endpoints and calculate bisector and target point
def process_lines(line1, line2, radius):
try:
common, distinct1, distinct2 = find_endpoints(line1, line2)
vector1 = Vector.ByTwoPoints(common, distinct1)
vector2 = Vector.ByTwoPoints(common, distinct2)
bisector = calculate_bisector(vector1, vector2)
angle_between_curves = vector1.AngleWithVector(vector2)
angle_rad = math.radians((180 - angle_between_curves) / 2)
target_distance = radius / math.cos(angle_rad)
target_point = common.Translate(bisector.Scale(target_distance))
return common, distinct1, distinct2, target_point
except Exception as e:
raise Exception(f"Error in process_lines: {e}\n{traceback.format_exc()}")
# Function to create an arc from two lines and a radius
def create_arc_from_lines(line1, line2, radius, center):
try:
tangent1 = line1.PointAtParameter(line1.ParameterAtPoint(center))
tangent2 = line2.PointAtParameter(line2.ParameterAtPoint(center))
direction1 = Vector.ByTwoPoints(center, tangent1)
direction2 = Vector.ByTwoPoints(center, tangent2)
cross_product = direction1.Cross(direction2)
if cross_product.Z < 0: # Assuming Z-up orientation
tangent1, tangent2 = tangent2, tangent1
return Arc.ByCenterPointStartPointEndPoint(center, tangent1, tangent2)
except Exception as e:
raise Exception(f"Error in create_arc_from_lines: {e}\n{traceback.format_exc()}")
def get_model_curves():
try:
selection_ids = uidoc.Selection.GetElementIds()
selection = []
for id in selection_ids:
element = doc.GetElement(id)
selection.append(element)
if selection:
return selection
else:
return 'No elements selected'
except Exception as e:
return f"Error in get_model_curves: {e}\n{traceback.format_exc()}"
# Get the input model curves and radius
model_curves = get_model_curves()
if isinstance(model_curves, str):
OUT = model_curves
else:
try:
curve1 = model_curves[0].GeometryCurve.ToProtoType()
curve2 = model_curves[1].GeometryCurve.ToProtoType()
# Get the line style of the first selected curve
first_curve_element = model_curves[0]
line_style = get_line_style(first_curve_element)
form = InputForm()
if form.ShowDialog() == System.Windows.Forms.DialogResult.OK:
input_number = form.textBox.Text
else:
input_number = None
if input_number:
radius = float(input_number)
common, distinct1, distinct2, arc_center = process_lines(curve1, curve2, radius)
arc = create_arc_from_lines(curve1, curve2, radius, arc_center)
TransactionManager.Instance.EnsureInTransaction(doc)
model_curve = Revit.Elements.ModelCurve.ByCurve(arc)
apply_line_style(model_curve, line_style)
TransactionManager.Instance.TransactionTaskDone()
OUT = model_curve
else:
OUT = "No input number provided"
except Exception as e:
OUT = f"Error during processing: {e}\n{traceback.format_exc()}"
# Output the result or the error message
OUT