Find angle of current view

I’ve been creating a family that contains several parts that need to be placed seperately, I managed to streamline a lot of that using Sastrugi’s pick points on worklplane (thanks a ton for that one @Ewan_Opie) as well as using this great python script which creates pop up window from which you can get data (I’m still having projects in Revit 2017 so making use of a more advanced Dynamo Player isn’t really an option).

Anyway, with placing the parts I’ve ran into one problem: the angle of the family. I’ve already tested it with angles I put in manually and it has worked out just fine using ‘FamilyInstance.SetRotation’ and some other calculations. It would however be a whole lot easier if I could just find the angle of the current view. If it’s even possible, it would help me out quite a lot.

Thanks in advance!

1 Like

Would something like doc.ActiveView.ViewDirection work?

Seems like a good idea. But I have no idea how I get these bits of code working for Dynamo.

This python will give you an XYZ that can be used for vectors. Basically it is a vector from the target of the active view to ‘you’, so in a plan view, it would be a vector (0,0,1), and in a 3d view it will be based on the angle you are looking at.

# Enable Python support and load DesignScript library
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

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

doc = DocumentManager.Instance.CurrentDBDocument

# The inputs to this node will be stored as a list in the IN variables.
direct = doc.ActiveView.ViewDirection
pt = Point.ByCoordinates(direct.X, direct.Y, direct.Z)

OUT = pt

Not sure how helpful this will be though.

2 Likes

Well, just to clarify. It does not concern 3D views, simply turned cropped views, so that might make things easier, thanks for the effort nonetheless.

You can get the cropbox lines/boundaries if that would help more. From there you can get the line direction and angle.

1 Like

I think that would actually solve everything…

First time trying this and using the iterators but this seemed to work:

# Enable Python support and load DesignScript library
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

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

doc = DocumentManager.Instance.CurrentDBDocument

# The inputs to this node will be stored as a list in the IN variables.
activeview = doc.ActiveView
cropmanager = activeview.GetCropRegionShapeManager()
shape = cropmanager.GetCropShape()[0]
iter = shape.GetCurveLoopIterator()
lines = []
while iter.MoveNext():
	curve = iter.Current
	ept = curve.GetEndPoint(0)
	spt = curve.GetEndPoint(1)
	dynEPT = Point.ByCoordinates(ept.X, ept.Y, ept.Z)
	dynSPT = Point.ByCoordinates(spt.X, spt.Y, spt.Z)
	newline = Line.ByStartPointEndPoint(dynEPT, dynSPT)
	lines.append(newline)


OUT = lines

I am leaving the office for the night so I can’t help any more until tomorrow.

3 Likes

Thanks a ton!

I think this will do the job.

I made some slight alterations and additions but it worked out anyway.

I changed the Python Ouput from ‘Out = lines’ to ‘Out=lines[0]’ because I only really need one line.

After that I added a couple of other nodes to “deconstruct” the line and find the angle:

It can now accurately find the angle.

Thanks a lot!

2 Likes

Hey,

If you’ll humour me, I think that if only need 1 line, you can simplify the Python, then you can reasonably easily do the other bits and pieces…

Hopefully I didn’t make any mistakes!

#Thanks Kenny!
# Enable Python support and load DesignScript library
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

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

import math


doc = DocumentManager.Instance.CurrentDBDocument

# The inputs to this node will be stored as a list in the IN variables.
activeview = doc.ActiveView
cropmanager = activeview.GetCropRegionShapeManager()
shape = cropmanager.GetCropShape()[0]
iter = shape.GetCurveLoopIterator()
curve = iter.Current
ept = curve.GetEndPoint(0)
spt = curve.GetEndPoint(1)
dynEPT = Point.ByCoordinates(ept.X, ept.Y)
dynSPT = Point.ByCoordinates(spt.X, spt.Y)
newLine = Line.ByStartPointEndPoint(dynEPT, dynSPT)
nLdirection = newLine.Direction
xDir = nLdirection.X
yDir = nLdirection.Y
angle = math.degrees(math.atan(xDir/yDir))


OUT = angle #newLine, nLdirection, xDir, yDir, 

image

Cheers,

Mark

4 Likes

That does work indeed!

1 Like

Looks good. If you wanted to simplify it further, instead of creating points, then lines, then vectors, and finally an X and y value, just take ept.X - spt.X and ept.Y - spt.Y to get the X and y values.

3 Likes

It works just fine now but I have a continueing question still.
The python scripts picks out the cropbox very effectively, but there will also be cases where the cropbox won’t be there, in which case I get a null output.
Changing the null output into 0 works fine in all those cases and I can easily do that via Dynamo (angle==null?0:angle). I do however still get a warning in that case. Is there a good way to get that done within the python node to avoid a warning?

Thanks in advance!

Try this? I think it’s what you’re asking but not sure :slight_smile:
The properties we have to work with are here…
http://www.revitapidocs.com/2018/be253fe5-777b-11b6-02be-64106cbb713f.htm

 #Thanks Kenny!
# Enable Python support and load DesignScript library
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

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

import math


doc = DocumentManager.Instance.CurrentDBDocument

if IN[0]:

    # The inputs to this node will be stored as a list in the IN variables.
    activeview = doc.ActiveView
    cropmanager = activeview.GetCropRegionShapeManager()
    if activeview.CropBoxActive:
        shape = cropmanager.GetCropShape()[0]
        iter = shape.GetCurveLoopIterator()
        curve = iter.Current
        ept = curve.GetEndPoint(0)
        spt = curve.GetEndPoint(1)
        dynEPT = Point.ByCoordinates(ept.X, ept.Y)
        dynSPT = Point.ByCoordinates(spt.X, spt.Y)
        newLine = Line.ByStartPointEndPoint(dynEPT, dynSPT)
        nLdirection = newLine.Direction
        xDir = nLdirection.X
        yDir = nLdirection.Y
        angle = math.degrees(math.atan(xDir/yDir))

    else:
        angle = 0
else: 
    angle = 'set runit to true'

OUT = angle #newLine, nLdirection, xDir, yDir,
2 Likes

It looks like it should work but I’m afraid it doesn’t.
Thanks for the effort anyway.

Hmm… the other thing I just noticed is that if your view is set to project north it returns an angle…

But it seems to be working for me… I’ll update the above code to include a ‘refresh’… maybe that will help?

1 Like

I’m not sure why, but running it via the player made it work.
So your idea worked. :wink:

1 Like