When you import a GPX file it's suppose to treat the coordinates like a Polygon, right?
No, it imports it as a path, not a polygon.
Appreciate the quick response. I figured with the beginning coordinates matching the end coordinates, it would be able to tell the difference between the two. I'm gonna try to dig into the GeofenceMapController, GeofenceMap, GeofenceConverter scripts to see if I can carefully modify them so it can accept/correctly parse both a path or a polygon. If that doesn't work, I'll try to change it to only convert a GPX files to Polygons in the WKT format.
Even if start and end coordinates match, it doesn't necessarily mean it's a polygon. It could be a loop path.
Yeah you have a point there. For my use, I feel like the scenario is unlikely. If I come across that it, I would probably just modify the GPX file to where the first and last coordinate are offset by .00001 before I imported it.
It's not a big deal. I just have a lot of geofences to add and it takes time to make them look decent. If I accidently click the wrong one, I have to start over. With having the original KMLs, I figured it would be worth an attempt at fixing....might also make it easier for someone else. If someone did have a path with the same coordinates on each end, another combo box would be a good way to let the user pick the type of geofence type they plan to import. As close as they were together, I had thought the combo box next to the file upload did that at first.
Yeah, that's probably a good option to provide a choice in the UI. Feel free to send a pull request if you manage to implement it.
I was able to get come up with way of importing GPX files as polygons by modifying GeofenceMapController.js and GeofenceConverter.js. I feel like this fix does not meet standards for doing a pull because it replaces functionality rather than adding functionality. It no longer converts the file to a Polyline, only a Polygon. If I do come up with a better solution, I'll be sure to do a pull request.
For now, I figured I would my quick fix here if someone wants to import GPX files only as a Polygon without continuously making changes to the database.
I did figure out how to get into the database and was able to change the 'VARCHAR (4096)' to a 'LONGSTRING' so I didn't have to simplify my GPX files anymore. Looking back, it might have been easier to have just left the code alone, create all of the geofences I needed, upload the files and change values in the database from LINESTRING (x y, x y , x y, x y)
to POLYGON ((x y, x y , x y, x y))
.
I will warn you that I am new to Javascript and I'm trying to understand/ learn the language so my methods below may be unconventional and show lack of knowledge in Javascript.
Modification of the GeofenceConverter.js:
I noticed Polyline, Polygon, and Circle are mentioned in this file for geometryToWkt
. As a precaution, I copied the geometryToWkt
section and added it below that section as geometryToWktUpload
section so only files that are being uploaded using the LineString
constructor are converted to a polygon. I didn't want to chance affecting how the application creates/converts or interprets any other Polygons, Polylines or Circles elsewhere in the application.
Since the geometryToWkt
loop for the else if (geometry instanceof ol.geom.Polygon)
parses polygons differently than a else if (geometry instanceof ol.geom.Polygon)
, I just changed the result = 'LINESTRING ('
to result = 'POLYGON ((' " and then change the ')' to '))
under the else if (geometry instanceof ol.geom.LineString)
statement within the newly created geometryToWktUpload
section of GeofenceConverter.js. This way if anything is actually a LineString
, it will refer to the geometryToWkt
within GeofenceConverter.js.
Using (geometry instanceof ol.geom.Polygon)
was giving me issues so I just used (geometry instanceof ol.geom.LineString)
instead.
geometryToWktUpload: function (projection, geometry) {
var result, i, center, radius, edgeCoordinate, groundRadius, points;
if (geometry instanceof ol.geom.Circle) {
center = geometry.getCenter();
radius = geometry.getRadius();
edgeCoordinate = [center[0] + radius, center[1]];
center = ol.proj.transform(center, projection, 'EPSG:4326');
groundRadius = ol.sphere.getDistance(
center, ol.proj.transform(edgeCoordinate, projection, 'EPSG:4326'), 6378137);
result = 'CIRCLE (';
result += center[1] + ' ' + center[0] + ', ';
result += groundRadius.toFixed(1) + ')';
} else if (geometry instanceof ol.geom.Polygon) {
geometry.transform(projection, 'EPSG:4326');
points = geometry.getCoordinates();
result = 'POLYGON((';
for (i = 0; i < points[0].length; i += 1) {
result += points[0][i][1] + ' ' + points[0][i][0] + ', ';
}
result = result.substring(0, result.length - 2) + '))';
} else if (geometry instanceof ol.geom.LineString) {
geometry.transform(projection, 'EPSG:4326');
points = geometry.getCoordinates();
<b>result = 'POLYGON ((';</b>
for (i = 0; i < points.length; i += 1) {
result += points[i][1] + ' ' + points[i][0] + ', ';
}
result = result.substring(0, result.length - 2) + <b>'))'</b>;
}
return result;
}
});
Modification of the GeofenceMapController.js:
Involved changing geometryToWkt
to geometryToWktUpload
.
onSaveClick: function (button) {
var geometry, projection;
if (this.getView().getFeatures().getLength() > 0) {
geometry = this.getView().getFeatures().pop().getGeometry();
projection = this.getView().getMapView().getProjection();
this.fireEvent('savearea', Traccar.GeofenceConverter.geometryToWktUpload(projection, geometry));
button.up('window').close();
}
},
After minifying the code, I tested it and it works without issue. I can still create Polygons, Polylines and Circles in the GUI if I wish and whenever I upload a GPX file, it will always treat it as a Polygon.
I have several geofences I need to add into Traccar. The areas are townships and municipalities with relatively large/complicated polygons. Rather than do them all by hand, I happen to have KML files of each Township and Municipality I need a geofence for. I saw the files have to be in a GPX file format. I was able convert them with a free utility called GPSBabel. When trying it the first time, the GPX files were too large/had too many data points. After enabling the option to simplify them to less than 100 coordinates, the GPX files uploaded into Traccar without giving an error.
After reviewing the report for events, I noticed that the entering/exiting Geofence events were not right and many were being missed. When you import a GPX file it's suppose to treat the coordinates like a Polygon, right?
I ended up redrawing one of the geofences using the shape tool. When I completed the polygon manually, I noticed it shaded the area with a light blue. The entering/exiting events appeared to be more accurate. If it is supposed to treat them like a polygon, is there something wrong or missing on the GPX file causing Traccar to do what it is doing? Is there a certain way you have to export the polygon from Google Earth? I have ensured that the first coordinate is the same as the end. Thanks, in advance.
Screenshot of the GPX import results:
https://drive.google.com/file/d/1RfmacQYLKNkgaOpVV_lPMjwcxyot0sTR/view?usp=sharing
Screenshot of the manual polygon:
https://drive.google.com/file/d/1O4R7nS7i-7kiB2JiNbArvux2wYmcpXGy/view?usp=sharing
Code of the GPX file being imported:
<?xml version="1.0" encoding="UTF-8"?> <gpx version="1.0" creator="GPSBabel - https://www.gpsbabel.org" xmlns="http://www.topografix.com/GPX/1/0"> <time>2022-01-06T14:35:57.695Z</time> <bounds minlat="41.180640776" minlon="-87.957190263" maxlat="41.210710338" maxlon="-87.906851350"/> <trk> <name>TestPath</name> <trkseg> <trkpt lat="41.198861679" lon="-87.918235451"> <ele>0.000</ele> </trkpt> <trkpt lat="41.194231250" lon="-87.917391320"> <ele>0.000</ele> </trkpt> <trkpt lat="41.191402495" lon="-87.907098193"> <ele>0.000</ele> </trkpt> <trkpt lat="41.185219827" lon="-87.906851350"> <ele>0.000</ele> </trkpt> <trkpt lat="41.183180278" lon="-87.910502766"> <ele>0.000</ele> </trkpt> <trkpt lat="41.180640776" lon="-87.919421567"> <ele>0.000</ele> </trkpt> <trkpt lat="41.188419563" lon="-87.937947333"> <ele>0.000</ele> </trkpt> <trkpt lat="41.198190327" lon="-87.957190263"> <ele>0.000</ele> </trkpt> <trkpt lat="41.205112095" lon="-87.942853092"> <ele>0.000</ele> </trkpt> <trkpt lat="41.197311763" lon="-87.940876473"> <ele>0.000</ele> </trkpt> <trkpt lat="41.197116338" lon="-87.932470607"> <ele>0.000</ele> </trkpt> <trkpt lat="41.210710338" lon="-87.929415233"> <ele>0.000</ele> </trkpt> <trkpt lat="41.208024191" lon="-87.925738036"> <ele>0.000</ele> </trkpt> <trkpt lat="41.204639708" lon="-87.923530265"> <ele>0.000</ele> </trkpt> <trkpt lat="41.204624176" lon="-87.927478984"> <ele>0.000</ele> </trkpt> <trkpt lat="41.202530266" lon="-87.924536434"> <ele>0.000</ele> </trkpt> <trkpt lat="41.201727729" lon="-87.929331716"> <ele>0.000</ele> </trkpt> <trkpt lat="41.199688349" lon="-87.922609049"> <ele>0.000</ele> </trkpt> <trkpt lat="41.200540926" lon="-87.920277764"> <ele>0.000</ele> </trkpt> <trkpt lat="41.198861679" lon="-87.918235451"> <ele>0.000</ele> </trkpt> </trkseg> </trk> </gpx>