Select to view content in your preferred language

How to snap a point to a line through arcade expression?

119
1
Jump to solution
a week ago
angiexx1
Emerging Contributor

I have a point feature called LineEnd and a line feature and when i create a point nearby to the line it should get snapped to the line end, i tried this using Arcade expression but i am not achieving the output required. So can anyone help me on this.

 

// Insert Trigger: Snap new LineEnd points to Line vertices

// Get the geometry of the newly inserted point
var point_geom = Geometry($feature);
var sr = point_geom.spatialReference;
Console('Spatial Reference WKID: ' + sr.wkid); // Debug: Log WKID only
Console('Inserted Point X: ' + point_geom.x + ', Y: ' + point_geom.y); // Debug: Log point

// Set snapping tolerance
var snap_tolerance = 1.0; // 1 meter for projected systems
if (sr.wkid == 4326) {
    snap_tolerance = 0.00001; // ~1 meter in degrees for WKID 4326
    Console('Using degrees-based tolerance');
} else {
    Console('Using meters-based tolerance');
}

// Create buffer around the point
var search_buffer = Buffer(point_geom, snap_tolerance, 'meters');
Console('Buffer created with tolerance: ' + snap_tolerance); // Debug: Confirm buffer

// Get Line features
var line_features = FeatureSetByName($datastore, 'Line', ['SHAPE'], false);
var nearby_lines = Intersects(line_features, search_buffer);
Console('Nearby lines count: ' + Count(nearby_lines)); // Debug: Check intersecting lines

// Track closest vertex
var closest_vertex = null;
var min_distance = snap_tolerance + 1; // Initialize to larger than tolerance

// Check each nearby line
for (var line_feature in nearby_lines) {
    var line_geom = Geometry(line_feature);
    
    // Try to access paths
    var paths = line_geom.paths;
    Console('Paths count for line: ' + Count(paths)); // Debug: Check number of paths
    if (IsEmpty(paths) || Count(paths) == 0) {
        Console('No valid paths in line');
        continue; // Skip if no paths
    }
    
    for (var i = 0; i < Count(paths); i++) {
        var path = paths[i];
        if (!IsEmpty(path) && Count(path) > 0) {
            // Check start vertex
            var start_vertex = path[0];
            var start_point = Point({
                'x': start_vertex.x,
                'y': start_vertex.y,
                'spatialReference': sr,
                'hasZ': false // Force 2D point
            });
            var start_distance = Distance(point_geom, start_point, 'meters');
            Console('Start distance: ' + start_distance); // Debug: Log distance
            
            if (start_distance < min_distance) {
                min_distance = start_distance;
                closest_vertex = start_point;
            }
            
            // Check end vertex
            if (Count(path) > 1) {
                var end_vertex = path[Count(path) - 1];
                var end_point = Point({
                    'x': end_vertex.x,
                    'y': end_vertex.y,
                    'spatialReference': sr,
                    'hasZ': false // Force 2D point
                });
                var end_distance = Distance(point_geom, end_point, 'meters');
                Console('End distance: ' + end_distance); // Debug: Log distance
                
                if (end_distance < min_distance) {
                    min_distance = end_distance;
                    closest_vertex = end_point;
                }
            }
        }
    }
}

// Update geometry if a closer vertex is found
if (closest_vertex != null) {
    Console('Snapped to vertex at X: ' + closest_vertex.x + ', Y: ' + closest_vertex.y);
    return {
        'result': closest_vertex,
        'edit': [{
            'className': 'LineEnd',
            'updates': [{
                'globalId': $feature.globalId,
                'geometry': closest_vertex
            }]
        }]
    };
} else {
    Console('No snap occurred');
    return {
        'result': point_geom,
        'edit': [{
            'className': 'LineEnd',
            'updates': [{
                'globalId': $feature.globalId,
                'geometry': point_geom
            }]
        }]
    };
}
0 Kudos
1 Solution

Accepted Solutions
DavidSolari
MVP Regular Contributor

On line 23 you're pulling the lines with includeGeometry set to false, see if setting that to true works better. There might also be issues with how you're trying to set the current feature's geometry using an edit object, simply apply the rule to your SHAPE field and return the new geometry object directly.

View solution in original post

0 Kudos
1 Reply
DavidSolari
MVP Regular Contributor

On line 23 you're pulling the lines with includeGeometry set to false, see if setting that to true works better. There might also be issues with how you're trying to set the current feature's geometry using an edit object, simply apply the rule to your SHAPE field and return the new geometry object directly.

0 Kudos