vasturiano / three-globe

WebGL Globe Data Visualization as a ThreeJS reusable 3D object
https://vasturiano.github.io/three-globe/example/links/
MIT License
1.22k stars 147 forks source link

i want to be able to add a different color for a specific satellite. #66

Open zen85 opened 1 year ago

zen85 commented 1 year ago

In my application it would be great if i can track specific satellites visually. right now all of them have the same geometry and color.

If possible i would like to be able to store satellite names in an array and whenever i put a name or even part of a name in it i can define a different color for the matching satellites (iE turn all satellites with "starlink" in the name pink)

I tried to do a second fetch and add just the tle data of the ones that are interessting for me in it while still showing the others but i cannot get it to work.

The application i am doing should be able to show generall traffic of all satellites but sometimes i want to see specific satellites within the swarm of satellites.

vasturiano commented 1 year ago

@zen85 using the accessor method objectThreeObject you are in full control of how each individual item / satellite looks like.

https://github.com/vasturiano/three-globe/blob/7852f4105561e0128547b568e44a1ab26f806214/example/satellites/index.html#L46-L48

In the supplied example all of them are equal, but you can differentiate them if you like, using the input parameter of that method:

myGlobe.objectThreeObject(sat => /* your code */)
zen85 commented 1 year ago

i dont really get it completly... i tried to add the following lines to the example but apparently it still turns all the satellites from yellow to green:

const issGeometry = new THREE.OctahedronGeometry(ISS_SIZE * Globe.getGlobeRadius() / EARTH_RADIUS_KM / 2, 0);
const issMaterial = new THREE.MeshLambertMaterial({ color: 'green', transparent: true, opacity: 1 });         
const issSatellite = satData.find(d => d.name === "VANGUARD 2");
Globe.objectThreeObject(issSatellite => new THREE.Mesh(issGeometry, issMaterial));

here you can see where the lines are located exactly:

const satGeometry = new THREE.OctahedronGeometry(SAT_SIZE * Globe.getGlobeRadius() / EARTH_RADIUS_KM / 2, 0);
const satMaterial = new THREE.MeshLambertMaterial({ color: 'yellow', transparent: true, opacity: 0.7 });
Globe.objectThreeObject(() => new THREE.Mesh(satGeometry, satMaterial));

fetch('./all_satellites.txt').then(r => r.text()).then(rawData => {
              const tleData = rawData.replace(/\r/g, '').split(/\n(?=[^12])/).map(tle => tle.split('\n'));
              const satData = tleData.map(([name, ...tle]) => ({
              satrec: satellite.twoline2satrec(...tle),
              name: name.trim().replace(/^0 /, '')
              }));

const issGeometry = new THREE.OctahedronGeometry(ISS_SIZE * Globe.getGlobeRadius() / EARTH_RADIUS_KM / 2, 0);
const issMaterial = new THREE.MeshLambertMaterial({ color: 'green', transparent: true, opacity: 1 });         
const issSatellite = satData.find(d => d.name === "VANGUARD 2");
Globe.objectThreeObject(issSatellite => new THREE.Mesh(issGeometry, issMaterial));

              // time ticker
              let time = new Date();
              (function frameTicker() {
                requestAnimationFrame(frameTicker);

                time = new Date(+time + VELOCITY * 60 * 1000);

                timeEl.innerText = time.toString();

                // Update satellite positions
                const gmst = satellite.gstime(time);

                satData.forEach(d => {

                  const eci = satellite.propagate(d.satrec, time);
                  if (eci.position) {
                    const gdPos = satellite.eciToGeodetic(eci.position, gmst);
                    d.lat = satellite.radiansToDegrees(gdPos.latitude);
                    d.lng = satellite.radiansToDegrees(gdPos.longitude);
                    d.alt = gdPos.height / EARTH_RADIUS_KM
                  }
                });

                Globe.objectsData(satData);
              })();
            });
vasturiano commented 1 year ago

I think there's some confusion on how the objectThreeObject method works. The function supplied there is invoked once for every single object data item that you pass in via objectsData, and the data item is passed as argument to that function.

So you can use it to conditionally use different Three objects depending on what the data item is.

For example, if you want to have one geometry/material for the ISS, and a different one for all others you could do:

// define the various geometries / materials needed
const generalGeometry = new THREE.OctahedronGeometry(GENERAL_SIZE * Globe.getGlobeRadius() / EARTH_RADIUS_KM / 2, 0);
const generalMaterial = new THREE.MeshLambertMaterial({ color: 'blue', transparent: true, opacity: 0.4 });        
const issGeometry = new THREE.OctahedronGeometry(ISS_SIZE * Globe.getGlobeRadius() / EARTH_RADIUS_KM / 2, 0);
const issMaterial = new THREE.MeshLambertMaterial({ color: 'green', transparent: true, opacity: 1 });         

Globe.objectThreeObject(d => 
  d.name === 'VANGUARD 2' 
    ? new THREE.Mesh(issGeometry, issMaterial) 
    : new THREE.Mesh(generalGeometry, generalMaterial)
);
zen85 commented 1 year ago

oh yes. you were right - i didn't understand the concept before. Now it works amazingly!