andydandy74 / ClockworkForDynamo

A collection of 450+ custom nodes for the Dynamo visual programming environment
MIT License
222 stars 96 forks source link

Wall.Orientation #79

Closed ksobon closed 8 years ago

ksobon commented 9 years ago

Hey Andy,

I was doing some stuff with Wall.Orientation and realized that it doesn't work well for curved walls. It returns some strange results instead of what I was expecting a line that is perpendicular to curve at it's mid point. Here's what i was able to dig out on Jeremy's blog and turn into a definition in Python:

# Copyright(c) 2015, Konrad K Sobon
# @arch_laboratory, http://archi-lab.net

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

# Import Element wrapper extension methods
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

# Import geometry conversion extension methods
clr.ImportExtensions(Revit.GeometryConversion)

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

import System
from System import Array
from System.Collections.Generic import *

import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)

#The inputs to this node will be stored as a list in the IN variable.
dataEnteringNode = IN

def ProcessList(_func, _list):
    return map( lambda x: ProcessList(_func, x) if type(x)==list else _func(x), _list )

def Unwrap(item):
    return UnwrapElement(item)

def GetExteriorWallDirection(wall):
    locationCurve = wall.Location
    if locationCurve != None:
        curve = locationCurve.Curve
        direction = XYZ.BasisX
        if type(curve) == Autodesk.Revit.DB.Line:
            direction = curve.ComputeDerivatives(0, True).BasisX.Normalize()
        else:
            direction = (curve.GetEndPoint(1) - curve.GetEndPoint(0)).Normalize()
        exteriorDirection = XYZ.BasisZ.CrossProduct(direction)

        if wall.Flipped:
            exteriorDirection = -exteriorDirection
        return exteriorDirection.ToVector()

if isinstance(IN[0], list):
    walls = ProcessList(Unwrap, IN[0])
else:
    walls = [UnwrapElement(IN[0])]

try:
    errorReport = None
    output = ProcessList(GetExteriorWallDirection, walls)
except:
    # if error accurs anywhere in the process catch it
    import traceback
    errorReport = traceback.format_exc()

#Assign your output to the OUT variable
if errorReport == None:
    OUT = output
else:
    OUT = errorReport

let me know if you want to incorporate that into your node or since your node returns exactly what Revit gives you when asked for wall.Orientation you would rather prefer to make this into a new node.

andydandy74 commented 9 years ago

@ksobon - this looks like a worthwhile improvement. I'll include this in the next version. I think that for straight (line-based) walls I will keep relying on the output of the Revit API, though. Thanks!

andydandy74 commented 8 years ago

This will be in Clockwork 1.0.2