Update
If there is no equivalent to silhouette
could you comment on my following ideas:
I can get the projection of my surface using the planeproject
transformation. This is still a three dimension surface but maybe it is easier to extract the outline path or paths from this simpler surface? If this isn't possible neither maybe the following algorithm could work:
planeproject
the surface- extract a dense mesh of points lying on this transformed surface (these points should ly within the same plane); or maybe it is even possible to extract the border points of the flat surface somehow (maybe via their slope being different from the other points on flat part of the surface)
- use some concave hull algorithm (that would have to be implemented first, of course) to find the concave hull of the aforementioned points.
- use the path along the concave hull as outline
Here I'm particularly uncertain if there is an easy way to do step 2. And I will have to think about what to do when the concave hull consists of several paths, e.g. like for a torus where you get the outer outline and the hole in the middle. Do you think this would be possible?
Original Question
The solids
package defines revolution
objects whose outlines can be accessed via silhouette
. Example:
size(200);
import solids;
settings.render=0;
settings.prc=false;
currentprojection=perspective(4,4,3);
revolution hyperboloid=revolution(new real(real x) {return sqrt(1+x*x);},
-2,2,20,operator..,X);
draw(hyperboloid.silhouette(64),blue);
Is there an equivalent way to get the outline path of a surface
? For example the outline of such a surface
(I know that the object in this example is spherically symmetric and so I could define a revolution
that describes it but I would like to know if there is a general way to get the outline of a surface
):
import graph3;
import palette;
size(200);
currentprojection=orthographic(6,8,2);
viewportmargin=(1cm,0);
real c0=0.1;
real f(real r) {return r*(1-r/6)*exp(-r/3);}
triple f(pair t) {
real r=t.x;
real phi=t.y;
real f=f(r);
real s=max(min(c0/f,1),-1);
real R=r*sqrt(1-s^2);
return (R*cos(phi),R*sin(phi),r*s);
}
bool cond(pair t) {return f(t.x) != 0;}
real R=abs((20,20,20));
surface s=surface(f,(0,0),(R,2pi),100,8,Spline,cond);
s.colors(palette(s.map(abs),Gradient(palegreen,heavyblue)));
render render=render(compression=Low,merge=true);
draw(s,render);
draw(zscale3(-1)*s);
Best Answer
Okay, I think I've more or less got a solution.
The silhouette function is defined by the following code:
After saving the code above in a file called
silhouette.asy
, here's how you draw a silhouette of your surface:Here's the result: