Looping a geoJSON

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.

working translation code
# 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

Are you aware that if you put your code into a custom node you then have levels at your disposal.

I’ve not looked at your code but that may help you.

1 Like

No, I’m not aware of it, Thank you!

1 Like

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.

1 Like

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
1 Like

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)
2 Likes

Thank you very much, I appreciate your help. @jacob.small @GavinCrump @Mike.Buttery @Alien

after trying to change the lines you provided me, I got an invalid syntax error.

I get this error for these lines

for latlons in points:
        
        outPtlist.append[transform.OfPoint(ll2cc(*ll)) for ll in latlons]

image

here is the link to the files.

Needs to be in brackets
outPtlist.append([transform.OfPoint(ll2cc(*ll)) for ll in latlons])

1 Like

I got this error.
image

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)

2 Likes

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.

The issue is that there is too much iterating of lists by a level
Data input is List of lists with geographic coordinates [lat deg, lon deg, alt m]

you can do it all at once if you’re just after Dynamo points

for points in ptList:
    outPtlists.append(
        [transform.OfPoint(ll2cc(*latlon)).ToPoint() for latlon in points]
    )
1 Like

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.

4 Likes