0

Following my previous question:Load json map into aframe by aframe-geo-projection-component created by earthlinginteractive

Now, I am trying to find a way to show different geometries (country or city) in AFrame each with a different color, looking for something like this.

I do not mind which library or approach are used, Found this but not sure how to convert this D3.js to Aframe. However as the community bot asked me to provide more details, I have put the code that I am working on below. Not sure which part I need to modify to have such a color coded map but I am working on that. Again, any working example works for me even if someone can show what I need to modify in the below code.

<!--  https://github.com/EarthlingInteractive/aframe-geo-projection-component 
  https://earthlinginteractive.github.io/aframe-geo-projection-component/  -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>A-Frame Geo Projection Component - U.S. Population 2017 (est.)</title>
    <meta name="description" content="Visualization of estimated U.S. population by state in 2017"></meta>
    <script src="https://aframe.io/releases/0.7.1/aframe.min.js"></script>
    <script src="//cdn.rawgit.com/donmccurdy/aframe-extras/v3.12.4/dist/aframe-extras.min.js"></script>
    <script src="https://unpkg.com/super-hands@2.1.0/dist/super-hands.min.js"></script>
    <script src="https://d3js.org/d3.v4.js"></script>
    <script src="https://d3js.org/d3-queue.v3.js"></script>
    <script src="https://earthlinginteractive.github.io/aframe-geo-projection-component/dist/aframe-geo-projection-component.min.js"></script>
</head>
<body>
<script>
  AFRAME.registerComponent('geo-extrude-population-renderer', {
    dependencies: ['geo-projection'],
    schema: {
      maxExtrudeHeight: {
        default: 2
      }
    },
    init: function () {
      this.system = this.el.sceneEl.systems['geo-projection'];
      this.geoProjectionComponent = this.el.components['geo-projection'];
      this.geoJsonReady = this.geoJsonReady.bind(this);
      // Wait for geoJson to finish loading to avoid race conditions
      this.el.addEventListener('geo-src-loaded', this.geoJsonReady);
    },
    update: function (oldData) {
      if (!this.geoProjectionComponent.geoJson) {
        return;
      }
      if (this.data.maxExtrudeHeight !== oldData.maxExtrudeHeight) {
        this.geoJsonReady();
      }
    },
    geoJsonReady: function () {
      // Now kick off loading the data
      d3.queue()
        .defer(d3.csv, 'https://cdn.glitch.global/c153e3cf-7430-444d-9897-4e97f1ef8d35/us-population-2017.csv?v=1657704183925', function (d) {
          return {
            state: d.state,
            population: +d.population
          }
        })
        .defer(d3.csv, 'https://cdn.glitch.global/c153e3cf-7430-444d-9897-4e97f1ef8d35/us-state-county-geocodes-v2016.csv?v=1657704190160')
        .await(this.onDataLoaded.bind(this));
    },
    onDataLoaded: function(error, populationData, geocodes) {
      if (error) throw error;
      var stateFips = geocodes.filter(function (row) {
        return row['Summary_Level'] === '040'
      });
      var maxPopulation = d3.max(populationData, function (d) {
        return d.population;
      });
      var populationByFipsCode = populationData.reduce(function (accum, d) {
        var fipsForState = stateFips.find(function (fipsRow) { return fipsRow['Area_Name'] === d.state; });
        var fipsCode = fipsForState['State_Code_FIPS'];
        accum[fipsCode] = d.population;
        return accum;
      }, {});
      this.render(populationByFipsCode, maxPopulation, this.data.maxExtrudeHeight);
    },
    render: function (populationByFipsCode, maxPopulation, maxExtrudeHeight) {
      if (!populationByFipsCode) return;
      var material = [];
      var extrudeGeometry = null;
      var stateOutlineVertices = [];
      // Split the geoJson into features and render each one individually so that we can set a different
      // extrusion height for each based on the population.
      this.geoProjectionComponent.geoJson.features.forEach(function (feature) {
        var population = populationByFipsCode[feature.id];
        var extrudeAmount = (population / maxPopulation) * maxExtrudeHeight;
        var material="#999999";
        const extrudeSettings = {
          amount: extrudeAmount,
          bevelEnabled: false
        };
//Math.floor(Math.random()*16777215).toString(16);
        var mapRenderContext = this.system.renderToContext(feature, this.geoProjectionComponent.projection);
        const stateShapes = mapRenderContext.toShapes();

        // Gather the outline of the state and set the height of the outline to the extrude level
        // so that the top of the state is outlined
        stateOutlineVertices = stateOutlineVertices.concat(mapRenderContext.toVertices(extrudeAmount));

        // Merge all the extruded feature geometries together for better rendering performance
        // Need to use ExtrudeGeometry here instead of ExtrudeBufferGeometry because the latter doesn't merge properly
        // in this version of Three.js
        var extrudedFeatureGeometry = new THREE.ExtrudeGeometry(stateShapes, extrudeSettings);
        if (!extrudeGeometry) {
          extrudeGeometry = extrudedFeatureGeometry;
        } else {
          extrudeGeometry.merge(extrudedFeatureGeometry);
        }
      }.bind(this));

      // Convert the extrude geometry into a buffer geometry for better rendering performance
      var extrudeBufferGeometry = new THREE.BufferGeometry();
      extrudeBufferGeometry.fromGeometry(extrudeGeometry);

      var sideMaterial = new THREE.MeshStandardMaterial( { color: 0xaaafff } );
      var extrudedMap = new THREE.Mesh(extrudeBufferGeometry, [material, sideMaterial]);
      this.el.setObject3D('map', extrudedMap);

      var stateOutlineGeometry = new THREE.BufferGeometry();
      stateOutlineGeometry.addAttribute('position', new THREE.Float32BufferAttribute(stateOutlineVertices, 3));
      var stateOutlineMaterial = new THREE.LineBasicMaterial( { color: 0xcccaaa } );
      var stateOutlines = new THREE.LineSegments(stateOutlineGeometry, stateOutlineMaterial);
      this.el.setObject3D('lines', stateOutlines);
    }
  });
</script>
<a-scene>
    <a-assets>
        <a-asset-item id="json-us" src="https://unpkg.com/us-atlas@1/us/10m.json" />
    </a-assets>
    <a-sky color="#ECECEC"></a-sky>
    <a-entity id="map"
              rotation="-90 0 0"
               material="color: #123456;"
              topojson-loader="src: #json-us; topologyObject: states;"
              geo-projection="
                  projection: geoIdentity;
                  height: 6;
                  width: 10;"
              geo-extrude-population-renderer
    >
    </a-entity>
    <a-locomotor>
        <a-entity hand-controls="left" super-hands></a-entity>
        <a-entity hand-controls="right" super-hands></a-entity>
    </a-locomotor>
</a-scene>
</body>
</html>
<!--material="color: #123456;"-->

getting this error as well if I use aframe 1.3.0:

Uncaught TypeError: extrudeBufferGeometry.fromGeometry is not a function
at i.render ((index):104:29)
at i.onDataLoaded ((index):66:12)
at Queue._call (d3-queue.v3.js:43:54)
at maybeNotify (d3-queue.v3.js:120:7)
at d3-queue.v3.js:91:12
at Object.<anonymous> (d3.v4.js:11470:86)
at Dispatch.call (d3.v4.js:792:72)
at XMLHttpRequest.respond (d3.v4.js:11395:13)
Moh-Spark
  • 131
  • 7
  • https://stackoverflow.com/questions/45853966/d3-js-graph-dashboard-conversion-to-png-jpg-pdf Are you looking for this? – Vivek D. Jul 13 '22 at 07:43
  • Not sure how this is related to my problem – Moh-Spark Jul 13 '22 at 07:45
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Jul 13 '22 at 11:42

0 Answers0