ladybug-tools / ladybug-legacy

:beetle: Ladybug is an environmental plugin for Grasshopper.
http://ladybug.tools
Other
194 stars 82 forks source link

Add Stereographic Option For SunPath, Sky Dome, Shading Mask, Cala-Dome, and Sky Visualizer #339

Closed chriswmackey closed 7 years ago

chriswmackey commented 7 years ago

I now have a few people asking for this as it makes it easy to trace shade patterns onto the sunpath and other sky-dome visualizations. I was originally thinking that I might be able to write the projection function with Rhino Transforms but it involves a non-uniform scaling from the center of the dome, which doesn't seem possible with these commands. If this involves a ground-up re-creation of these graphics, it may be better to hold off the capability until the new Ladybug.

mostaphaRoudsari commented 7 years ago

@Vyrwn should have some inputs on this. I think he has already done it in Rhino/Grasshopper.

Vyrwn commented 7 years ago

Hi Chris,

I had a small grasshopper file to do the Stereographic SunPath ( I dont know if you remember) https://github.com/Vyrwn/byron-master/blob/master/StereoGraphic_SunPath/StereoGraphic_SunPath.ghuser

Just before the break I was trying to make it in Python. https://github.com/Vyrwn/byron-master/blob/master/StereoGraphic_SunPath/StereoGraphic_Python.ghuser

I don't know if this is helpful in any way. I had also created a component for shading mask. https://github.com/Vyrwn/byron-master/blob/master/StereoGraphic_SunPath/StereoGraphic_ShadowMask.ghuser

The clusters are quite old, but updated on the latest ladybug. I hope this is helpful somehow.

Vyrwn commented 7 years ago

I would not recommend running the Python script yet as it is not finished and will probably take too long to work. Also it is not commented at all. I hope I will remember what I did after the holidays

chriswmackey commented 7 years ago

@Vyrwn , I knew that you had been working on it but I didn't realize how far you had gotten. I haven't been able to get the non-python ghuser object to run yet but it looks complete and I trust that it's probably the result of mis-matches of Ladybug versions.

My main question at this point is about how you plan to implement it in python. I see that the python component is standalone and, ideally, it would be nice to have a function in LadybugLadybug that is able to translate any geometry from a dome shape to a stereographic projection so that we can have stereoProj it as an option on all dome-like components. Let me know what you are planning. If you implement is at standalone, I can help you translate it to a multi-purpose function in Ladybug_Ladybug.

-Chris

Vyrwn commented 7 years ago

@chriswmackey. it is as @mostaphaRoudsari showed in his presentation. Old clusters that tend to get outdated and something might go wrong down the road. In this case, yesterday, when I did an update on the components in a rush to send it to you, I plugged the "location" wire into "-----------".

I am sending a working (hopefuly) gh file. https://github.com/Vyrwn/byron-master/blob/master/StereoGraphic_SunPath/Stereographic.gh

At this moment I have set up the python code, to read the sunPositions of an annual sunPath (~4,5k points), and project those points in a stereographic way. Then I am grouping all the hours together (ex. all 9am of the year) and I create a curve through them, so I get the hourly curves of the sunPath. I grabbed the code for the base of the sunPath directly from the original Ladybug component.

I am not happy at all with the method because its very dirty. Ideally I would like to understand the way the SunPath is created out of Longitude and Latitude. Breaking up the SunPath, projecting the points and then reconnecting it, is not the proper way to do it I am sure. I went through the original Ladybug code to understand the way it is done but I cannot say its 100% clear to me. I also had a look at Michalsky (1988) and anything I could find through google within a day's search.

I will have a go also in creating the generic projection that you are suggesting. My stereographic shadingMask projection is also working on point projections, but I will try to make that more clean and more generic.

-Byron

chriswmackey commented 7 years ago

@Vyrwn , I was able to get your GH file to run correctly on my system. There will definitely be a lot of gains in efficiency with converting this over to Python as it took quite some time to run on my system. I can see that the math to do the projection is relatively simple both in your component and in the wikipedia page: https://en.wikipedia.org/wiki/Stereographic_projection

Directly engaging the code to generate the sunpath is one way to accomplish this and this would be the fastest computationally. However, I know that the code is difficult to understand now and I think that a more generalizable function that can project any geometry to a stereographic view will be more useful and will be applicable to all of the different types of sky visualizations that Ladybug has.

Writing this function for points is straightforward and you have already done this. To project curves, we will need a function that subdivides the curve into points, projects the points and does an interpolated curve between the new points. To project meshes, we just need to take the vertices of the mesh and run them through the projection function.

Let me know if you would be able to tackle this in the next couple of weeks as it would be good to have this capability for the next stable release. I am also happy to help. -Chris

Vyrwn commented 7 years ago

@chriswmackey , I will start looking into it tomorrow. Let me see how far I can go this week.

If I run into any major problems I will let you know.

-Byron

Vyrwn commented 7 years ago

@chriswmackey,

I managed to do a component that creates a stereographic sunpath out of the Ladybug_SunPath component.

https://github.com/Vyrwn/byron-master/blob/master/StereoGraphic_SunPath/stereo.gh

It runs in less than a second now that I am testing it. I hope it works fine. I will add all the necessary checks now to work well with Ladybug.

There are two issues that I am trying to resolve though. There is something weird going on when creating the curve through the hour marks, I hope I will be able to resolve this. The other is that I cannot, for the life of me, get it to change object colours.

You can have a go and see if it works fine for you as well.

-Byron

Vyrwn commented 7 years ago

Tomorrow if I get some time I will try to make the generic component for curves and meshes as you suggested.

I just thought it was easier to start with the sunPath version.

-Byron

Vyrwn commented 7 years ago

@chriswmackey,

https://github.com/Vyrwn/byron-master/blob/master/StereoGraphic_SunPath/StereoGraphic_SunPath.ghuser

Some updates on the component, now I resolved the issue that was creating a weird curve on the hours marks. I've tested it with several different locations and it seems to be responding with no problems.

I also added the angle curves and the origin. I played arround with different coloring methods but I realised this has been a big issue with Python for GH over the years. I worked with custom display but of course that ended up messing everything, so I removed it.

Not having colors is not a big problem, but I would have liked to get something already colored and nice instead of relying on custom previews from the output.

let me know what you think of the component this far.

-Byron

chriswmackey commented 7 years ago

@Vyrwn , Glad that you have been making progress on this. The new component is looking nice and I'm glad that everything is python now. The next steps now are to write a generic function to project any geometry and to replace all of your instances of rhinoscript with rhinocommon. Let me know if you get stuck with this and I can help.

Assigning colors to rhinocommon objects is difficult and meshes are the only objects that actually have color properties. If you bake (or Add) objects to the Rhino scene, you can assign colors but, in GH, you have to use the preview component if you want to change the color of any object that is not a mesh.

Vyrwn commented 7 years ago

@chriswmackey, I worked a bit on the generic component to project any mesh in stereographic way.

can you please have a look at the file. https://github.com/Vyrwn/byron-master/blob/master/StereoGraphic_SunPath/stereoMesh.gh

I have two problems.

  1. For some reason until line 38 where I generate the polyline with the 3 or 4 mesh vertices it works fine. when I generate the surface though, or the mesh, there are extra faces. image

  2. I cannot find a way to join the meshes in the end without using RhinoScriptSyntax.

One last thing. Since I have the faces and I generate the relative vertices that are projected on the plane, is there a way to use rhinocommon to do what the constructMesh component does? I could not find anything after some searches that I did.

let me know of your thoughts so far.

-Byron

chriswmackey commented 7 years ago

@Vyrwn ,

Great job and thanks for the hustle on this. I have taken a look at your file, red your questions, and I have a number of suggestions. Notably, you have produced an excellent example of why people should use Rhinocommon instead of Rhinoscript, which is summarized in the image and GH file below:

speedofcode

https://www.dropbox.com/s/cgr19824dj8vvee/stereoMesh_CWM.gh?dl=0

All three components successfully perform the operation of projecting the mesh to a stereoscopic view but, as you can see, the run times of the components are very different. The top component is the original one that you uploaded here, which takes 10 seconds to project the mesh on my (admittedly slow) machine. The second component from the top replaces the rhinoscript portions of your original component with rhinocommon code, cutting the run time by almost a half. However, this component is still using the same general method of the component above it by finding an intersection between the XY plane and a line for each mesh vertex and completely rebuilding a new mesh from the result. On the contrary, the last component performs no intersections and generates no new meshes. It simply moves each vertex of the input mesh using the formula on this wikipedia page. image As a result, this last component can do the job in a fraction of a second and is something that we can scale up to all of the sky dome components.

So the moral of the story is Rhinocommon is wonderful not just because it is intrinsically faster than Rhinoscript but because you can leverage it in new ways to do things even faster than a pure translation (at 1/20th the speed in this case).

Finally, I have a note about your use of tuples and yield commands at the end of your definitions. For most cases, you should just use arrays (or lists) instead of the tuples and simply return the lists from the function. You will see examples of this in the GH file. The number of cases where you want to use tuples and yield commands is very low and you really only have to consider them when performing calculations with large datasets that take up a lot of memory.

Hope this helps and thanks for the useful example. I may use this in some tutorials int he future. -Chris

Vyrwn commented 7 years ago

@chriswmackey, thank you very much for looking into this and for finding the time to prepare the improved component. This will be very helpful for me as a reference to improve my Rhinocommon workflow. This was a good example because I knew exactly what I wanted, a command to move the vertices without deconstructing and reconstructing a mesh, but didn't know what that command was.

I know yield is not the way to go but it always seems easier to me to grasp. I guess there is still a lot to learn.

I hope this didn't take too much out of your time. Let me try and implement a generic curve projection in the component.

-Byron

chriswmackey commented 7 years ago

@vyrwn , It was not much time to make the alternates of the component and, in the long run, I see an example like this helping people save a lot of time. I know that every new developer (including myself some time ago) goes through a time where they don't understand how much better it is to use rhinocommon and I know that I just had to trust Mostapha. Now that we have an example like this, it doesn't just have to be a matter of trust.

I'm looking forward to the next implementation. For curves, I think that we may have to do some rebuilding of geometry (rather than just projecting it directly) but this is much faster than rebuilding a mesh. Also, now you see how you can get the porojected points just using a mathematical formula instead of a geometric intersection and this is applicable to all of the work that you are doing.

-Chris

mostaphaRoudsari commented 7 years ago

Finally, I have a note about your use of tuples and yield commands at the end of your definitions. For most cases, you should just use arrays (or lists) instead of the tuples and simply return the lists from the function. You will see examples of this in the GH file. The number of cases where you want to use tuples and yield commands is very low and you really only have to consider them when performing calculations with large datasets that take up a lot of memory.

I haven't see this specific case but if you use tuples and generators wisely they are both more efficient than lists memory-wise.

chriswmackey commented 7 years ago

@mostaphaRoudsari , I know that is definitely true. The issue here was that @Vyrwn was using tuples and generators just to convert them to a list after he yielded them. But I definitely know that they are great if you have a list that you are certain you will only iterate through once. Generally, I prefer to put them in after I have finished writing the code and I'm more sure that I won't be calling a given array again in the script.

chriswmackey commented 7 years ago

I'm happy to say that this is finally all implemented. Thanks, again, @vyrwn , for making this a reality!