8

In a great answer to another question of mine about asymptote, @Paolo Brasolin managed to draw the hidden portion of a path with dashed lines.

enter image description here

But, as far as I understand, it is not automated and not available with all kinds of perspective.

I don't know how asymptote renders the scene but is there any way to tell the renderer that portions of paths in the "background" (ie behind an opaque surface) should be rendered with dashed lines (maybe drawn again when the scene is rendered) ?

1 Answer 1

9
+100

First of all, there is no "layering" mechanism in the rendering engine; see this feature request. So if you want to simulate one (e.g., to make visible a path that is behind an opaque object), you have two options:

  1. Give up hidden object removal by setting settings.render = 0;. This doesn't help your cause unless you use something like the surfacepaths module from this answer or this answer to actually compute the parts of the path in front of and behind the object. (This module is incomplete and may or may not work for your actual use case. It also draws hidden paths as faded, which I have found typically looks better than dashed. Perhaps later I'll see if I can add something to this answer showing a modified version that allows for dashed paths.)
  2. Simulate layering by moving some objects closer to (or farther away from) the camera. This is generally the preferred solution, but it is harder to make it work for a perspective projection than for an orthographic projection.

Paolo's solution is a clever variant of 2 based on the observation that a dashed curve drawn over a solid curve looks exactly like a solid curve. The mathematical estimates are unnecessary; for orthographic projections, shift(n * unit(currentprojection.camera)) is precisely the transformation required to move an object n units toward the camera. Making n too big is unlikely to be a problem, so you can just use something like n=1000 (or start with n=1 and double it until the picture looks right).

Dealing with perspective projections is, unavoidably, an issue--especially since lines closer to the camera will actually appear thicker. Here's the best I can do at the moment:

import graph3;
size(6cm,0);
settings.render = 4;
currentprojection=perspective(5*(4, 1, 1), showtarget=true, autoadjust=false, center=true);

// UTILITY FUNCTIONS
triple cameradirection(triple pt, projection P=currentprojection) {
  if (P.infinity) {
    return unit(P.camera);
  } else {
    return unit(P.camera - pt);
  }
}
triple towardcamera(triple pt, real distance=1, projection P=currentprojection) {
  return pt + distance * cameradirection(pt, P);
}
path3 towardcamera(path3 g, real distance=1, projection P=currentprojection) {
  triple f(real t) {
    return towardcamera(point(g,t), distance, P);
  }
  return graph(f, 0, length(g), operator..);
}
pen shortdashed = linetype(new real[] {4, 4});

// SURFACE
triple S(pair uv) {
  real x = cos(uv.x)*sin(uv.y);
  real y = sin(uv.x)*sin(uv.y);
  real z =           cos(uv.y);
  return (x-(1-z**2-y**2), y-0.3*sin(z*pi), z);
}

// BOUNDARY
triple dS(real u) {
  return S((u, pi/2));
}

// GRAPHICAL ELEMENTS
surface s = surface(S, (0, 0), (2pi, pi/2), 64, 64, Spline);
path3 ds = graph(dS, 0, 2pi);

draw(s, surfacepen=material(diffusepen=gray(0.6),
                            emissivepen=gray(0.3),
                            specularpen=gray(0.1)));
                            
// Draw boundary.
draw(ds);

// Draw dashed version of boundary out in front. As long as it's exactly the
// same color and width as the solid path, the dashing pattern will only show up
// when the solid path isn't behind it.
//draw(shift(4*unit(currentprojection.camera))*ds, dashed);
draw(towardcamera(ds, 4), linetype(new real[] {4, 4}));

The result: enter image description here

It's not ideal in a couple ways. First, there is gratuitous whitespace in the edge of the picture. (This can be fixed by removing the parameter autoadjust=false, but that also messes up the dashed path.) Second, the dashed lines, being closer to the camera, are thicker than the solid lines. This can be mitigated by moving the camera farther away--but if you're going to do that, you're basically just trying to get the perspective projection to behave like an orthographic projection; why not just use orthographic projection in the first place?

1
  • 1
    Thanks for your time (+1) and for the links to your previous answers (already upvoted but totally forgotten on my side). So my best bet here is to hope that your feature request will be heard by asymptote developers. btw, I love the fact that asymptote produces perspective projection so that's the reason why I was asking.
    – cjorssen
    Commented Jan 17, 2016 at 19:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .