Vanuatu GIS Feed

@vanuatugis.bsky.social

The Vanuatu GIS Feed will be used to aggregate site posts. It is monitored, but will probably not be very 'personal'. - @raetlomi.bsky.social Technology Feed @vanuatutech.bsky.social. 231124

Create mapping between overlapping linestrings

What I have is two shapefiles, describing roads in a city. The shapefiles are made of linestrings, each covering a section of road. * The road segments in shapefile 1 are generally several times larger than the segments in shapefile 2. * The road segments break at road junctions for both shapefiles. * The shapefiles do not describe every road in the city. * Both shapefiles describe the same city, although there is some difference in the roads they cover. Some roads decribed by segments in shapefile 1 are not present in shapefile 2, and vice versa. What I want is to create a many to one map between the shapefiles. I would like a table that lists each segment in shapefile 2, and it's closest match in shapefile 1. By closest match I mean closest in similarity, not necessarily in distance. In situations where a segment in shapefile 2 overlaps two segments in shapefile 1, the segment it overlaps the most would be chosen. Where there is no matching segment in shapefile 1, the table entry would be null. I'm not sure how to best approach this task. My initial plan is to create a new polygon layer using the buffer tool in QGIS, from the features in shapefile 1, and then somehow find which buffer the linestrings from shapefile 2 predominantly fall in. I don't know if there are any tools which would help with this second step, or tackles the whole problem. I know how to use QGIS, and Python.

gis.stackexchange.com

QgsTaskManager active vs queued vs running task

I am confused by the documentation in https://qgis.org/pyqgis/master/core/QgsTaskManager.html, which says that QgsTaskManager.countActiveTasks() returns "the number of active (queued or running) tasks". I find this confusing because, from my point of view, a task should not be deemed active until it is running. Why is a queued task counted as active? I agree that when I add a task to the manager, the number of active tasks is incremented, because I can print debug output when I handle the manager's taskAdded and countActiveTasksChanged signals. MyPlugin.on_taskAdded( taskId=50 ) MyPlugin.on_countActiveTasksChanged( 1 ) However, I also handle the manager's statusChanged signal, and the debug output from that demonstrates that when a task begins running, the number of active tasks is decremented. MyPlugin.on_statusChanged( taskId=50, status=2=Running ) MyPlugin.on_countActiveTasksChanged( 0 ) This leaves me wondering if I can rely on countActiveTasks() and the countActiveTasksChanged signal to really tell me how many tasks are running. Any insight is appreciated. P.S. As an aside, how does the manager enqueue the tasks, and how does it decide when an enqueued task should begin running? My motivation for asking is that I want to limit how many tasks run at any one time. Currently, I am doing that by having my own manager that wraps the QgsTaskManager. My manager has its own queue of what I think of as "pending" tasks, and I pop a task from my pending queue and provide it to QgsManager.addTask() when the number of active tasks drops below the threshold I desire.

gis.stackexchange.com

How to calculate a geofence in ArcGIS Survey123 Connect

Have you ever wanted to make sure your surveyors stay within a specific area while collecting data? In this GeoSnap, I’ll show you how to use conditional read-only questions in ArcGIS Survey123 Connect to create a geofence that allows survey submissions only from a specified location. Example read-only calculation from demonstration: if(pulldata("@layer", "getValueAt","attributes.OBJECTID", "{layerURL}", ${location}) {greater than symbol} 0, "", "yes") Have a question about Geofences in ArcGIS Survey123 Connect?  Ask in the Comments below.  Learn more: https://doc.arcgis.com/en/survey123/create/main/xlsformexpressions.htm 0:00 – Intro 0:30 – Offline disclaimer 0:48 – Setting up the survey 1:10 – Setting up the equations 2:26 – Adding the equations to the survey 2:52 – Results 3:26 - Outro  ---------------------------------------------------------------------------------  About ArcGIS Survey123  ► Product Page https://www.esri.com/en-us/arcgis/products/arcgis-survey123/overview  ► Blogs https://community.esri.com/t5/arcgis-survey123-blog/bg-p/arcgis-survey123-blog  ► Esri Community https://community.esri.com/t5/arcgis-survey123/ct-p/arcgis-survey123  ---------------------------------------------------------------------------------- About GeoSnaps | Videos by Esri Canada  ► A collection of bite-sized technical videos about all things in the ArcGIS universe.   ► Have a suggestion for a GeoSnap?  Email us at geosnaps@esri.ca  ► Be sure to subscribe to our channel and hit the notification bell to stay up to date with the latest tutorials and technical inspiration: https://www.youtube.com/user/esricanadatv  ----------------------------------------------------------------------------------  Want more from Esri Canada?  ► Sign up for our email and select ‘Getting Technical’ under Esri Canada Blog Digests to receive the latest in your inbox: https://pages.esri.ca/Esri-Canada-Preference-Centre.html To learn more, contact us: https://esri.ca/contactus

youtube.com

GEE - Inspector and rendered classification disagree at max zoom — OBIA pipeline

I’m running an OBIA classification pipeline in GEE using SNIC segmentation and Random Forest. The problem: At maximum zoom level, the rendered classification map in GEE shows different results than the Inspector tool reports for the same pixel locations. When I export the classification as GeoTIFF for QGIS, the exported image matches the wrong rendered map, not the Inspector values. What I’ve tried: * reproject({crs: 'EPSG:32734', scale: 0.5}) on features before classification * reproject() on the classification output * Adding projection: 'EPSG:32734' to sampleRegions — this fixed training sample extraction but not the rendering How do I make the rendered/exported classification match what the Inspector reads? Is this a known issue with reduceConnectedComponents? Best, Ted // ── LOAD ASSETS ── var ms = ee.Image('projects/masters-thesis-496612/assets/26JUL13084732-M3DS-050587773010_01_P001'); var pan = ee.Image('projects/masters-thesis-496612/assets/26JUL13084732-P3DS-050587773010_01_P001'); var aoi = ee.FeatureCollection('projects/masters-thesis-496612/assets/AOI'); var aa_possible_terms = ee.FeatureCollection('projects/masters-thesis-496612/assets/aa_possible_terms'); var training_possible_terms = ee.FeatureCollection('projects/masters-thesis-496612/assets/training_possible_terms'); // ── PANSHARPENING ── var ms_resampled = ms.resample('bilinear').reproject({crs: pan.projection()}); var ms_mean = ms_resampled.reduce(ee.Reducer.mean()); var ratio = pan.divide(ms_mean); var pansharpened = ms_resampled.multiply(ratio); pansharpened = pansharpened.rename(['b1','b2','b3','b4','b5','b6','b7','b8']); // ── TRAINING POINTS ── var nonMoundsLabelled = ee.FeatureCollection(non_mounds.geometries().map(function(geom) { return ee.Feature(ee.Geometry(geom), {'class_id': 0}); })); var allTraining = training_possible_terms.merge(nonMoundsLabelled); // ── SEGMENTATION ── var snic = ee.Algorithms.Image.Segmentation.SNIC({ image: pansharpened, size: 30, compactness: 0.1, connectivity: 8, neighborhoodSize: 2 }); var clusters = snic.select('clusters'); var edges = clusters.subtract(clusters.focal_min(1)).abs().gt(0); // ── FEATURE EXTRACTION ── var meanBands = pansharpened.addBands(clusters).reduceConnectedComponents({ reducer: ee.Reducer.mean(), labelBand: 'clusters' }); var brightness = pansharpened.reduce(ee.Reducer.mean()).rename('brightness'); var bsi = pansharpened.expression( '((b6 + b5) - (b8 + b2)) / ((b6 + b5) + (b8 + b2))', {b2: pansharpened.select('b2'), b5: pansharpened.select('b5'), b6: pansharpened.select('b6'), b8: pansharpened.select('b8')} ).rename('BSI'); var indices = brightness.addBands(bsi).addBands(clusters).reduceConnectedComponents({ reducer: ee.Reducer.mean(), labelBand: 'clusters' }); var features = meanBands.addBands(indices); // ── CLASSIFICATION ── var trainingSamples = features.sampleRegions({ collection: allTraining, properties: ['class_id'], scale: 0.5, projection: 'EPSG:32734' }); var rf = ee.Classifier.smileRandomForest(100).train({ features: trainingSamples, classProperty: 'class_id', inputProperties: features.bandNames() }); var svm = ee.Classifier.libsvm().train({ features: trainingSamples, classProperty: 'class_id', inputProperties: features.bandNames() }); var rfClassification = features.classify(rf); var svmClassification = features.classify(svm); // ── VISUALIZE ── Map.setOptions('HYBRID'); Map.centerObject(aoi, 15); Map.addLayer(pansharpened, {min: 0, max: 2000, bands: ['b5', 'b3', 'b2']}, 'Pansharpened'); Map.addLayer(edges.updateMask(edges), {palette: ['ff0000']}, 'Segments'); Map.addLayer(rfClassification.eq(1).selfMask(), {palette: ['ff0000']}, 'RF Mounds'); Map.addLayer(svmClassification.eq(1).selfMask(), {palette: ['0000ff']}, 'SVM Mounds'); Map.addLayer(training_possible_terms, {color: 'cyan'}, 'termitaries training'); print('Training points:'); print(allTraining.size()); print('RF trained!'); print('SVM trained!'); // ── LOAD ASSETS ── var aoi = ee.FeatureCollection( 'projects/masters-thesis-496612/assets/AOI' ); var aa_possible_terms = ee.FeatureCollection( 'projects/masters-thesis-496612/assets/aa_possible_terms' ); // ── VISUALIZE ── Map.setOptions('HYBRID'); // AOI Map.addLayer( aoi, {color: 'yellow'}, 'AOI' ); // Possible terms Map.addLayer( aa_possible_terms, {color: 'red'}, 'aa_possible_terms' ); //export var non_mounds_fc = ee.FeatureCollection(non_mounds.coordinates().map(function(coord) { return ee.Feature(ee.Geometry.Point(coord), {class_id: 0}); })); Export.table.toDrive({ collection: non_mounds_fc, description: 'non_mounds_round1', folder: 'termite_thesis', fileFormat: 'SHP' }); Export.image.toDrive({ image: rfClassification, description: 'rf_classification_round1_small', folder: 'termite_thesis', scale: 0.5, crs: 'EPSG:32734', region: training_area, maxPixels: 1e13 }); Export.image.toDrive({ image: svmClassification, description: 'svm_classification_round1_small', folder: 'termite_thesis', scale: 0.5, crs: 'EPSG:32734', region: training_area, maxPixels: 1e13 });

gis.stackexchange.com

Python and Google Maps API place search: Read csv read row by row and loop fuction

I want to automate a task in Python with the Google API Search Place. Right now, my code with Google Maps API is returning places 'hospital' for one set of geographic coordinates. But, I have a CSV file which contains many geographic coordinates. 1: Hanoi 10.762622, 106.660172 2: Ho Chi Minh 12.762622, 108.660175 3: Ho Chi Minh 11.8542, 108.660175 4: ... 5: ... As you can see in my code, this is not efficient because I need to change the geographic coordinates manually. For each row (geographic coordinates) in my CSV file, I want my code to read the geographic coordinates 1: Hanoi and give me results 'hospitals' for this geographic coordinates. After read row 2: Ho Chi Minh and same for all the other rows. How I can achieve that or any good examples of making tasks like this more efficient? import urllib import urllib.request import json googleGeocodeUrl = 'https://maps.googleapis.com/maps/api/place/textsearch/json?query=' keyword = "hospital" geolocation = "&location=-12.135,-77.023&radius=5000" APIKEY = '&key='+'apikey' url = googleGeocodeUrl + keyword + geolocation + APIKEY print(url) url = googleGeocodeUrl + keyword + geolocation + APIKEY json_response = urllib.request.urlopen(url) search = json_response.read().decode('utf-8') searchjson = json.loads(search) export = open('hopital.csv','w') for place in searchjson['results']: print(place['name']) print(place['geometry']['location']) export.write(place['name']+','+str(place['geometry']['location']['lng'])\ +','+str(place['geometry']['location']['lat'])+'\n') export.close()

gis.stackexchange.com