0

I am trying to get a script together that would based on a geo point lat long return the label of a line segment by proximity. This could also be the devices own lat long as soon as the survey opens if easier. Here is some code work that Ismael from Esri had done and I tried modifying it. However, my java is terrible. The below code block pulls the nearest record when I want to pull the nearest value of the field Label. it also has it point to a web service when I want it point to the json stored within the media folder media/scat_segment.json. Any help would be appreciated

function getNearestRecord(featureLayer, location, searchWithinMeters,fields,where,token,debugmode){
    
    if (featureLayer==="" || featureLayer===undefined){
        featureLayer = "https://services.arcgis.com/P3ePLMYs2RVChkJx/ArcGIS/rest/services/USA_Major_Cities/FeatureServer/0";
    }

    if (location==="" || location===undefined){
        return (debugmode? "Location Object is empty":"");
    }

    if (fields==="" || fields===undefined){
        fields="*";
    }

    if (where==="" || where===undefined){
        where="1=1";
    }

    var coordsArray = location.split(" ");
    var coords = coordsArray[1] + "," + coordsArray[0]

    var xmlhttp = new XMLHttpRequest();
    var url = featureLayer + "/query?geometry=" + coords +  "&where=" + where + "&geometryType=esriGeometryPoint&inSR=4326&distance=" + searchWithinMeters + "&units=esriSRUnit_Meter&outFields=" + fields + "&returnGeometry=true&outSR=4326&f=json"

    if (token){
        url = url + "&token=" + token;
    }

    xmlhttp.open("GET",url,false);
        xmlhttp.send();

    if (xmlhttp.status!==200){
        return (debugmode? xmlhttp.status:"");
    } else {
        var responseJSON=JSON.parse(xmlhttp.responseText)
        if (responseJSON.error){
            return (debugmode? JSON.stringify(responseJSON.error):"");
        } else {
            var count = responseJSON.features.length;
            if (count===0){
                return (debugmode? "No Features Found":"");
            }
            else if (count===1){
                return JSON.stringify(responseJSON.features[0]);
            }
            else if (count>1){
                var nearestIndex = findNearestIndex (location, responseJSON.features);
                return JSON.stringify(responseJSON.features[nearestIndex]);
            }
        }
    }
}

function findNearestIndex(location, features){
    var nearestIndex = 0;
    var minDistance = 999999999999;

    var coordsArray = location.split(" ");
    var lat1 = coordsArray[0];
    var lon1 = coordsArray[1];

    for (let i = 0; i < features.length; i++) {
      var dist = getDistanceKM(lat1,lon1,features[i].geometry.y,features[i].geometry.x);
      if (dist < minDistance){
        minDistance = dist;
        nearestIndex = i;
      }
    } 

    return nearestIndex;
}

function getDistanceKM(lat1, lon1, lat2, lon2) {
    if ((lat1 == lat2) && (lon1 == lon2)) {
        return 0;
    }
    else {
        var radlat1 = Math.PI * lat1/180;
        var radlat2 = Math.PI * lat2/180;
        var theta = lon1-lon2;
        var radtheta = Math.PI * theta/180;
        var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
        if (dist > 1) {
            dist = 1;
        }
        dist = Math.acos(dist);
        dist = dist * 180/Math.PI;
        dist = dist * 60 * 1.1515;
        return dist * 1.609344;
    }
}

I tried editing the lines myself and I got to the point in survey 123 where it returns this enter image description here my reference inside arcgis survey 123 is:

enter image description here

the code block I have is

function getNearestLabel(filePath, segmentPoint, debugmode) {
    if (!filePath || filePath === undefined) {
        return (debugmode ? "File path is not provided" : "");
    }

    if (!segmentPoint || segmentPoint === undefined) {
        return (debugmode ? "Segment point is not provided" : "");
    }

    var coordsArray = segmentPoint.split(" ");
    var pointLat = parseFloat(coordsArray[0]);
    var pointLon = parseFloat(coordsArray[1]);

    // Assuming data is stored in a JSON file
    var xmlhttp = new XMLHttpRequest();
    var url = "media/scat_segment.json"; // Corrected file path
    xmlhttp.open("GET", url, false);
    xmlhttp.send();

    if (xmlhttp.status !== 200) {
        return (debugmode ? "Failed to fetch data from JSON file" : "");
    } else {
        var responseJSON = JSON.parse(xmlhttp.responseText);
        var nearestIndex = findNearestLineIndex(pointLat, pointLon, responseJSON.features);
        var nearestLabel = responseJSON.features[nearestIndex].attributes.Label;
        return nearestLabel.toString(); // Convert to string before returning
    }
}

function findNearestLineIndex(pointLat, pointLon, features) {
    var nearestIndex = 0;
    var minDistance = Number.MAX_VALUE;

    for (var i = 0; i < features.length; i++) {
        var coords = features[i].geometry.coordinates;
        var dist = getDistanceToPoint(pointLat, pointLon, coords);
        if (dist < minDistance) {
            minDistance = dist;
            nearestIndex = i;
        }
    }

    return nearestIndex;
}

function getDistanceToPoint(pointLat, pointLon, lineCoords) {
    var minDistance = Number.MAX_VALUE;

    for (var i = 0; i < lineCoords.length - 1; i++) {
        var dist = distanceToSegment(pointLat, pointLon, lineCoords[i][1], lineCoords[i][0], lineCoords[i + 1][1], lineCoords[i + 1][0]);
        minDistance = Math.min(minDistance, dist);
    }

    return minDistance;
}

// Function to calculate the distance from a point to a line segment
function distanceToSegment(pointLat, pointLon, lat1, lon1, lat2, lon2) {
    var x0 = pointLon;
    var y0 = pointLat;
    var x1 = lon1;
    var y1 = lat1;
    var x2 = lon2;
    var y2 = lat2;

    var dx = x2 - x1;
    var dy = y2 - y1;
    var along = ((x0 - x1) * dx + (y0 - y1) * dy) / (dx * dx + dy * dy);

    var x, y;
    if (along <= 0) {
        x = x1;
        y = y1;
    } else if (along >= 1) {
        x = x2;
        y = y2;
    } else {
        x = x1 + along * dx;
        y = y1 + along * dy;
    }

    return Math.sqrt((x - x0) * (x - x0) + (y - y0) * (y - y0));
}


1
  • Please trim your code to make it easier to find your problem. Follow these guidelines to create a minimal reproducible example. Commented Apr 4, 2024 at 3:07

1 Answer 1

0

Unfortunately, you cannot access local files in ArcGIS Survey123 Connect JavaScript functions [1].

You could try transferring scat_segment.json to a CSV file in the survey's media folder where one of the columns is the JSON string:

name,json
scat_segment,"{""features"":[{""type"":""Feature"",""geometry"":{""type"":""Point"",""coordinates"":[102.0,0.5]},""properties"":{""prop0"":""value0""}},...]}"

Load this in a question via pulldata('mycsvfile', 'json', 'name', 'scat_segment') [2], passing the returned JSON string to your JavaScript function as a parameter for processing there.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.