3

Background

Looking to project a 2D texture map onto a 3D surface.

Texture & Globe

The SVG source for the texture map is online:

The crack data without gradients, simplified:

The SVG source for the sphere is also online:

Problem

When the texture map is placed on top of the globe, the result is flat because no UV mapping is performed:

Problem Constraints

Consider the following constraints:

  • An SVG-based texture map as input (such as that given)
  • An input spherical radius (no oblate transformation needed)
  • An SVG file is produced as output

Question

What approach would you take to map a 2D texture (comprised of lines, Bezier curves, or other data) onto a sphere to produce an SVG of the projection (without rasterization)?

Resources

D3's Geo with an orthographic projection appears to meet the requirements of loading a texture map, performing a projection based on some topology, and can export the result as SVG:


The reference-only rasterized versions:

Texture Map Rasterized

Globe

1

2 Answers 2

2

Import the SVG paths into JOSM to create a geocoded file format as follows:

  1. Install Java
  2. Download JOSM (Java OpenStreetMap Editor)
  3. Run JOSM: java -jar josm-latest.jar
  4. Click Edit > Preferences
  5. Click Plugins icon (socket and plug)
  6. Click Available
  7. Search for importvec
  8. Check importvec
  9. Click Download
  10. Click OK
  11. Click Restart when prompted
  12. Click File > New Layer
  13. Click File > Open
  14. Browse to and select the SVG file
  15. Set the Scale units to: 620,000 metres (found by trial and error)
  16. Set the Curve steps to: 24
  17. Click OK to confirm import of vector graphics
  18. Zoom out (press - several times)

The vector is imported:

JOSM Screenshot

Export the JOSM layer to a GeoJSON file as follows:

  1. Click File > Save As
  2. Set Files of Type to: GeoJSON Files
  3. Set the File Name to: cracks.geojson

The file is exported. Next, create a web page such as:

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Tellus Collision Cracks</title>
  <meta charset="utf-8"/>
  <script crossorigin="anonymous" src="d3.v5.min.js"></script>
  <script crossorigin="anonymous" src="d3-geo.v1.min.js"></script>
  <script crossorigin="anonymous" src="versor.js"></script>
  <style>
  .cracks {
    fill: none;
    stroke: red;
    stroke-width: 1px;
  }

  .graticule {
    fill: none;
    stroke: blue;
    stroke-width: 1px;
  }
  </style>
</head>
<body>
  <div id="container"></div>
  <script type="text/javascript">
    var w = 750,
        h = 750,
        scale = h / 4,
        lastX = 0,
        lastY = 0;
    var origin = { x: 0, y: 0 };

    var projection = d3.geoOrthographic()
        .scale(scale)
        .translate([w/2, h/2])
        .rotate([origin.x, origin.y])
        .center([0, 0]);

    var geoPath = d3.geoPath().projection( projection );

    var svg = d3
      .select( '#container' )
      .append( 'svg' )
      .attr( 'width', w )
      .attr( 'height', h );

    svg.call( d3.drag()
      .on( "start", dragstart )
      .on( "drag", dragging )
    );

    d3.json('cracks.geojson').then( function( lines ) {
      svg.append( "path" )
         .datum( lines )
         .attr( "class", "cracks" )
         .attr( "d", geoPath );
    });

    var v0, r0, q0;

    function dragstart() {
      v0 = versor.cartesian(projection.invert(d3.mouse(this)));
      r0 = projection.rotate();
      q0 = versor(r0);
    }

    function dragging() {
      var v1 = versor.cartesian(projection.rotate(r0).invert(d3.mouse(this))),
          q1 = versor.multiply(q0, versor.delta(v0, v1)),
          r1 = versor.rotation(q1);

      projection.rotate(r1);

      svg.selectAll(".cracks").attr("d", geoPath);
    };
  </script>
</body>
</html>

Browse to the web page (e.g., http://localhost/d3/index.html).

The browser shows:

Spherically Projected Fissures

The data is loaded into D3 and the lines are curved. Extract the data as follows:

  1. Right-click on the sphere.
  2. Select Inspect Element (or equivalent for your browser).
  3. Right-click on the div container.
  4. Select Copy > Inner HTML.
  5. Open a new file.
  6. Paste the HTML.
  7. Save the file as cracks-curved.svg.

Open cracks-curved.svg in Inkscape, which reveals two objects, both black:

Circle and Lines

  1. Select the large black outer circle.
  2. Delete the circle to reveal the curved paths.
  3. Press Ctrl+Shift+F to bring up the fill panel.
  4. Remove the Fill settings.
  5. Click the Stroke paint tab.
  6. Set the fill colour to black.

The curved lines are shown:

Spherically Projected Lines

0

The task can be performed with 3D software which allows vector object mappings to surfaces. I tried it in an entry level 3D modeller named MoI3D. It somehow resembles a premium package named Rhinoceros. MoI3D has radically different user interface, poor coloring options and no photorealistic rendering. But it can make the wanted curve projection in the same way as Rhinoceros:

enter image description here

The curves to be mapped are placed onto a square surface. The square presents which area should be placed onto the sphere. The mapping function is named Deform > Flow. Only the curve on the square is selected as the object to be flown and the square is selected to be the base surface. I clicked the matching points so that the midpoint is on the visible side.

The projected 2D scene can be saved as Adobe Illustrator file or PDF. I opened the PDF in Inkscape and recolored the strokes:

enter image description here

There's a couple of minor disadvantages:

  • the outline of the sphere is an incredibly dense polyline
  • everything is grouped, the groupings can be very complex with complex objects

The sphere outline is easy to redraw and one can get rid of unwanted too complex groupings with Extension > Arrange > Deep Ungroup

There's no numeric control for the mapping in MoI3D, the only controlling method is to change the sizes and forms of the objects.

In the next image the sphere is the same, but the curve is smaller. The square is even smaller, so the result is bigger on the sphere:

enter image description here

There's perspective, but it can be turned OFF in MoI3D. Inkscape saves as SVG. The original plane curves can be imported to MoI3D as PDF if one doesn't want to draw them in MoI3D.

As well as to Inkscape you can take the image to Illustrator which offers more coloring possibilities. For example there's no gradient along a path in Inkscape. But if the final result must be SVG, you must stick with things supported by the SVG format.

The presented method needs some carefully drawn guide lines if one wants to apply exactly the same transformation to different shapes. There's another answer which is based on advanced math scripting. I recommend to use it if perfect repeatability with different patterns is a must. My method can be useful if one wants to adjust shapes and the view purely visually

3
  • Svg can support gradients along path. If only the end applications supott meshes.
    – joojaa
    Sep 9, 2019 at 9:33
  • Fantastic answer! Do you know if there is an open-source version of Mol3D (or equivalent) that runs on Linux (i.e., platform independent)? Sep 9, 2019 at 17:16
  • @DaveJarvis Check Blender. It seems to have everything imagineable. Unfortunately I cannot use properly programs that complex. I recommend you to check if your problem is already solved or can be solved in our sister site for Blender. I guess you can run a demo of MoI3D or Rhinoceros in Linux with windows emulators if you can accept sluggish operation.
    – user82991
    Sep 9, 2019 at 18:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.