0

I am trying to find the intersection of circles with their center given in Lat/Lng and their radius in meter.

I find this really good code here https://gis.stackexchange.com/questions/156371/finding-intersection-of-two-circle-given-lat-lon-and-radius that I modified, and it works with the given value, but when I try with mine, it return NaN as Lat/Lng.

//My value - radius in meter
{
  const circle1 = {lat:-4.504471833333334, lon:48.37154066666667, r:meterToNautMiles(2887.5)};
  const circle2 = {lat:-4.504421, lon:48.37154066666667, r:meterToNautMiles(2898.5)};
  console.log(findInterscetionOfTwoCircles(circle1,circle2));
}


{
  //Value that works - radius in NM
  const circle1 = {lat:37.673442, lon:-90.234036, r:107.5};
  const circle2 = {lat:36.109997, lon:-90.953669, r:145};
   console.log(findInterscetionOfTwoCircles(circle1,circle2));
}

function meterToNautMiles(meter){
    var NM = meter * 0.00053996;
    return NM;
}

function findInterscetionOfTwoCircles(circle1, circle2){
    var c1 = latLonToGeocentricCoords(circle1);
    var c2 = latLonToGeocentricCoords(circle2);
    var r1 = convertRadius(circle1.r);
    var r2 = convertRadius(circle2.r);
    var c1dotc2 = calculateDotProduct(c1, c2);

    var a = (Math.cos(r1) - (Math.cos(r2) * c1dotc2)) / (1 - (c1dotc2 * c1dotc2));
    var b = (Math.cos(r2) - (Math.cos(r1) * c1dotc2)) / (1 - (c1dotc2 * c1dotc2)); 
    var n = calculateCrossProduct(c1, c2); 

    var x0 = calculateLinearCombination(a, b, c1, c2);

    ndot = calculateDotProduct(n,n);
    xdot = calculateDotProduct(x0,x0);

    //This is where the problem occur
    //It should return a number but instead i get NaN
    var t = Math.sqrt((1 - xdot)/ndot);

    var point_1 = vectorPlusVector(x0,numberTimesVector(t, n));
    var point_2 = x0 + (numberTimesVector(-t, n));

    point1 = {
        lat: radToDeg(Math.asin(point_1[2])), 
        lon:radToDeg(Math.atan2(point_1[1], point_1[0]))
    }
    return point1;

}

function latLonToGeocentricCoords(circle){
    var x = Math.cos(degToRad(circle.lon)) * Math.cos(degToRad(circle.lat));
    var y = Math.sin(degToRad(circle.lon)) * Math.cos(degToRad(circle.lat));
    var z = Math.sin(degToRad(circle.lat));

    return {x:x, y:y, z:z};
}

function geocentricCoordsToLatLon(x, y, z){
    var lon = Math.atan2(x,y)
    var lat = Math.atan2(Math.sqrt((x*x)+(y*y)), z)

    return { lat: lat, lon: lon};
}

function convertRadius(radius){
    // converts NM right now
    return degToRad(radius) / 60;
}

function numberTimesVector(number, vector){
    for(let i=0; i < vector.length; i++){
        vector[i] = vector[i] * number;
    }
    return vector;
}

function vectorPlusVector(v1, v2){
    var vector = [];
    if(v1.length !== v2.length){
        throw new Error('Input lengths must be the same.');
    }
    for(let i=0; i < v1.length; i++){
        vector.push(v1[i]+v2[i]);
    }
    return vector;
}

function calculateDotProduct(input1, input2){
    if(arguments.length !== 2){
        throw new Error('You must supply two arguments to this method.');
    }

    if(Array.isArray(input1) !== Array.isArray(input2) || typeof input1 !== typeof input2){
        throw new Error('Inputs must be the same types.');
    }

    var dotProduct = 0;
    if(Array.isArray(input1)){
        // process as parallel arrays
        if(input1.length !== input2.length){
            throw new Error('Input lengths must be the same.');
        }
        for(var i = 0, len = input1.length; i < len; i++){
            dotProduct += input1[i] * input2[i];
        }
    } else if(typeof input1 === 'object' && !Array.isArray(input1)){
        // process as key-value object
        for(var key in input1){
            if (input1.hasOwnProperty(key)) {
                if(!input2[key]){
                    throw new Error('Both inputs must have the same properties to be processed.');
                }
                dotProduct += input1[key] * input2[key];
            }

        }
    }

    return dotProduct; 
}

function calculateCrossProduct(circle1, circle2){
    var x = (circle1.y * circle2.z) - (circle1.z * circle2.y);
    var y = (circle1.z * circle2.x) - (circle1.x * circle2.z);
    var z = (circle1.x * circle2.y) - (circle1.y * circle2.x);

    return [x, y, z];
}

function calculateLinearCombination(a, b, c1, c2){
    var x = {x: a * c1.x, y: a * c1.y, z: a * c1.z};
    var y = {x: b * c2.x, y: b * c2.y, z: b * c2.z};

    return [x.x+y.x, x.y+y.y,x.z+y.z];
} 

function degToRad(degree){
    return degree * Math.PI / 180;
}

function radToDeg(radian){
    return radian / Math.PI * 180;
}

I think it may be because the circles are too close to each other, but I'm not sure.

Antonin L
  • 1
  • 1
  • `var t = Math.sqrt((1 - xdot)/ndot);` The `1-xdot` is negative, the sqrt of a negative is `NaN`. Flipping to -> `(1 - ndot) / xdot` will give you some number, but I'm not sure this is correct. – Keith May 24 '23 at 10:06
  • Maybe `(1 - xdot/ndot)` – Stéphane Laurent May 24 '23 at 10:57
  • Thanks for your help, but unfortunately it didn’t work. I think the formulas are good, and I just need to find a way to treat circles very close to each other. Maybe there are other algorithms that can do the trick for such close points on earth – Antonin L May 24 '23 at 11:59

0 Answers0