Hi,
I want to get your suggestions. I have been struggling with looping a list in Python script.
Thanks to Mike Buttery’s help, I got a translation code that translates a contour’s points to revit xyz. but now I’m working on getting the all contour list to be translated into Revit xyz points while keeping the structured list.
My code works translating a list that has @L3 level. To be more precise, the code translates one contour line’s all point to revit xyz. You can see in the middle the list can be translated at the end. But I want it to translate the list on the left which consists of all contour lines and their points which was constructed with latitude and longitude points.
# Load the Python Standard and DesignScript Libraries
import clr
from math import cos, sin
clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *
# The inputs to this node will be stored as a list in the IN variables.
latlons = IN[0] # List of lat lon pairs in degrees
# Place your code below this line
doc = DocumentManager.Instance.CurrentDBDocument
def ll2cc(lat, lon, deg=True):
def rad(d):
return UnitUtils.Convert(d, UnitTypeId.Degrees, UnitTypeId.Radians)
R = 63710088 # Arithmetic mean radius of Earth in meters
if deg:
lat, lon = rad(lat), rad(lon)
return XYZ(R * cos(lat) * cos(lon), R * cos(lat) * sin(lon), 0)
loc = doc.SiteLocation # Site Location
lat = loc.Latitude
lon = loc.Longitude
# Translate site location lat, lon to 0, 0
translation = XYZ.Zero.Subtract(ll2cc(lat, lon, False))
transform = Transform.CreateTranslation(translation)
# Assign your output to the OUT variable.
OUT = [transform.OfPoint(ll2cc(*ll)) for ll in latlons]
I have been working on it for several days. Since, I do not fully understand list levels and looping. My changes don’t work. Could you guide me, please? I will connect my code to the “all contours” node.
my work
Summary
# Load the Python Standard and DesignScript Libraries
import clr
from math import cos, sin
clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *
# The inputs to this node will be stored as a list in the IN variables.
ptList = IN[0] # List of multi-point list that includes points constructed with lat lon pairs in degrees
# Place your code below this line
def ll2cc(lat, lon, deg=True): # latttude longitude to revit DB cartesian coordinates
def rad(d):
return UnitUtils.Convert(d, UnitTypeId.Degrees, UnitTypeId.Radians)
R = 63710088 # Arithmetic mean radius of Earth in meters
if deg:
lat, lon = rad(lat), rad(lon)
return XYZ(R * cos(lat) * cos(lon), R * cos(lat) * sin(lon), 0)
for points in ptList:
for latlons in points:
doc = DocumentManager.Instance.CurrentDBDocument
loc = doc.SiteLocation # Site Location
lat = loc.Latitude
lon = loc.Longitude
# Translate site location lat, lon to 0, 0
translation = XYZ.Zero.Subtract(ll2cc(lat, lon, False))
transform = Transform.CreateTranslation(translation)
transformed_points = []
transformed_points.append[transform.OfPoint(ll2cc(*ll)) for ll in latlons]
# Assign your output to the OUT variable.
OUT = transformed_points
Would help others who want to take a stab at it if you provided a sample geojson.
Also as this appears to assume the latitude has the same radius as the longitude, which may throw your values off by a bit as the earth is t actually a sphere. Not likely to matter much in the grand scheme of things (all conversions have a degree of lost precision), but you may want to double check the results with a 3rd party toolset.
Not 100% on the logic of the latlon function, but you can move some things outside your loop body as they are global as far as I can see (current doc, transform). You can retain your list structure by appending your outputs to a nested list structure.
Without the sample files I cannot test insitu, but I believe this might deliver the outcome you are after if your loop structure is correct. The code uses the * operator in the function which to me is a bit odd, so I’m guessing it’s an overly complex implementation which could use some simplifying.
# Load the Python Standard and DesignScript Libraries
import clr
from math import cos, sin
clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *
# You only need to declare these inputs once
doc = DocumentManager.Instance.CurrentDBDocument
loc = doc.SiteLocation
lat = loc.Latitude
lon = loc.Longitude
# The inputs to this node will be stored as a list in the IN variables.
ptList = IN[0] # List of multi-point list that includes points constructed with lat lon pairs in degrees
# Place your code below this line
def ll2cc(lat, lon, deg=True): # latttude longitude to revit DB cartesian coordinates
def rad(d):
return UnitUtils.Convert(d, UnitTypeId.Degrees, UnitTypeId.Radians)
R = 63710088 # Arithmetic mean radius of Earth in meters
if deg:
lat, lon = rad(lat), rad(lon)
return XYZ(R * cos(lat) * cos(lon), R * cos(lat) * sin(lon), 0)
# Global transform, declare once
translation = XYZ.Zero.Subtract(ll2cc(lat, lon, False))
transform = Transform.CreateTranslation(translation)
# One big list to append lists onto per point list
outPtlists = []
for points in ptList:
outPtlist = []
for latlons in points:
outPtlist.append[transform.OfPoint(ll2cc(*ll)) for ll in latlons]
outPtlists.append(outPtlist)
# Assign your output to the OUT variable.
OUT = transformed_points
You are correct - Original code is from here. Taking straight from Stack Overflow - it’s the x, y coordinates for a sphere with three dimensions not a mapping to the surface - oops
A bit more digging and I would update the function as follows
def ll2cc(lat, lon, altitude=0, deg=True):
def rad(d):
return UnitUtils.Convert(d, UnitTypeId.Degrees, UnitTypeId.Radians)
R = 63710088 # Arithmetic mean radius of Earth in meters
if deg:
lat, lon = rad(lat), rad(lon)
return XYZ(R * lon * cos(lat), R * lat, altitude)
Hi @Ecenurc, it could be worth you writing code in an external IDE with correction suggestions for debugging etc. Makes finding errors like this much more easy as they are flagged to you! My snipped is from Visual Studio Code
The second error you have shown is again a syntax error that could be avoided by using an external program (or by doing a basics in Python course to understand some of these more generic errors)
Thank you @haganjake2. I have downloaded VS and I am trying to get accustomed to it. Also, I followed only w3schools for Python and took some school courses but I should take more lessons.
Also, I haven’t add revit “clr” to VS yet.
I appreciate your help. Finally, I could create this. We can’t select multiple answers to a solution which is why I couldn’t select @GavinCrump’s solution. But now I have a better understanding of lists thanks to him and @Mike.Buttery. Thank you @jacob.small for pointing out the precision situation. Thank you @haganjake2 and @Alien for your suggestions, I hope I can learn them better.