Comments (6)
The Azure Maps drawing tools don't have a copy/paste feature, so adding this to the labelling tool would likely be a lot of work. That said, I have been playing around with an idea of how this would work and some of us are considering creating and open source "advanced" drawing tools module for Azure Maps which might be the way to go here.
from satellite-imagery-labeling-tool.
I took a stab at creating a rough example of a copy/paste extension for the Azure Maps drawing tools. I haven't tested this a lot, so might be buggy, but seems to work well. Good starting point.
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<!-- Add references to the Azure Maps Map control JavaScript and CSS files. -->
<link href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.css" rel="stylesheet" />
<script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.js"></script>
<!-- Add references to the Azure Maps Map Drawing Tools JavaScript and CSS files. -->
<link rel="stylesheet" href="https://atlas.microsoft.com/sdk/javascript/drawing/1/atlas-drawing.min.css" type="text/css" />
<script src="https://atlas.microsoft.com/sdk/javascript/drawing/1/atlas-drawing.min.js"></script>
<script>
var map, drawingManager;
var copiedShape;
var mousePosition;
var dmSource;
function GetMap() {
//Initialize a map instance.
map = new atlas.Map('myMap', {
view: 'Auto',
authOptions: {
authType: 'subscriptionKey',
subscriptionKey: '<Your Azure Maps Key>'
}
});
//Wait until the map resources are ready.
map.events.add('ready', function () {
//Create an instance of the drawing manager and display the drawing toolbar.
drawingManager = new atlas.drawing.DrawingManager(map, {
toolbar: new atlas.control.DrawingToolbar({ position: 'top-right', style: 'light' })
});
dmSource = drawingManager.getSource();
//Monitor the mouse position over the map.
map.events.add('mousemove', mouseMoved);
map.events.add('mouseout', () => { mousePosition = null });
//Add keyboard shortcuts for copy/paste of shapes.
map.getMapContainer().addEventListener('keyup', keyup);
});
}
function keyup(e) {
//Check to see if the control button is held.
if(e.ctrlKey) {
//Check to see if user pressed C to copy.
if(e.keyCode === 67) {
//Copy the last drawn shape in the drawing manager.
var s = dmSource.getShapes();
if(s.length > 0) {
//Copy JSON version of shape.
copiedShape = s[s.length - 1].toJson();
//Delete ids to prevent issues.
delete copiedShape.id;
delete copiedShape.properties._azureMapsShapeId;
} else {
copiedShape = null;
}
}
//Check to see if user pressed V to paste.
else if (e.keyCode === 86){
pasteShape();
}
}
}
function mouseMoved(e) {
mousePosition= e.position;
}
/*function shapeClicked(e) {
//Check to see if in copy/paste mode.
var elm = document.getElementById('copyPasteMode');
if(elm.checked){
var ds = drawingManager.getSource();
//Check to see if the clicked shape is in the drawing manager data source.
for(var i=0;i< e.shapes.length;i++){
//Ensure object is a Shape and is in the drawing manager data source.
if(e.shapes[i] instanceof atlas.Shape && ds.getShapeById(e.shapes[i].getId())) {
//Storing json copy.
copiedShape = e.shapes[i].toJson();
//Delete ids to prevent issues.
delete copiedShape.id;
delete copiedShape.properties._azureMapsShapeId;
//Only select the first selected shape.
return;
}
}
}
}*/
function pasteShape() {
//Paste the shape to where the mouse is over the map, or the center of the map.
var pasteCenter = mousePosition || map.getCamera().center;
if(copiedShape) {
//Calculate the center point of the copied shape based on bounding box for simplicity.
var copiedCenter = atlas.data.BoundingBox.getCenter(atlas.data.BoundingBox.fromData(copiedShape));
//Calculate the offsets. Use pixels at zoom level 22 for visible accuracy.
var p = atlas.math.mercatorPositionsToPixels([copiedCenter, pasteCenter], 22);
var dx = p[1][0] - p[0][0];
var dy = p[1][1] - p[0][1];
var shapeToPaste = createShapeToPaste(dx, dy);
var ds = drawingManager.getSource();
ds.add(shapeToPaste);
//Get the last shape added to the data source and put it into edit mode.
var shapes = ds.getShapes();
var s = shapes[shapes.length - 1];
drawingManager.edit(s);
}
}
function createShapeToPaste(dx, dy) {
var g = copiedShape.geometry;
var newGeometry = {
type: g.type,
coordinates: []
};
//Offset the positions of the geometry.
switch(g.type) {
case 'Point':
newGeometry.coordinates = getOffsetPositions([g.coordinates], dx, dy)[0];
break;
case 'LineString':
case 'MultiPoint':
newGeometry.coordinates = getOffsetPositions(g.coordinates, dx, dy);
break;
case 'Polygon':
case 'MultiLineString':
newGeometry.coordinates = g.coordinates.map(r => {
return getOffsetPositions(r, dx, dy);
});
break;
//MultiPolygon
}
//Create a GeoJSON featuret from new geometry, copy the properties.
return new atlas.data.Feature(newGeometry, JSON.parse(JSON.stringify(copiedShape.properties)));
}
function getOffsetPositions(positions, dx, dy) {
//Convert positions to pixel at zoom level 22.
var pixels = atlas.math.mercatorPositionsToPixels(positions, 22);
//Offset pixels.
for(var i=0, len = pixels.length; i< len;i++) {
pixels[i][0] += dx;
pixels[i][1] += dy;
}
//Convert back to positions.
return atlas.math.mercatorPixelsToPositions(pixels, 22);
}
</script>
</head>
<body onload="GetMap()">
<div id="myMap" style="position:relative;width:100%;min-width:290px;height:600px;"></div>
<input id="copyPasteMode" type="checkbox" onclick="toggleCopyPasteMode()" />
<fieldset style="width:calc(100% - 30px);min-width:290px;margin-top:10px;">
<legend>Drawing tools - copy/paste extension</legend>
This is a rough example of adding a copy/paste capability to the drawing tools in Azure Maps.
When the map has focus and you press CTRL + C, the last added shape in the drawing manager will be copied to memory.
When you press CTRL + V, the copied shape will be added to the map, centered over the mouse pointer if it is above the map, otherwise the shape will be added to the center of the map.
Once a shape has been added, the drawing tools go into edit mode for that shape so that fine tune adjustments can be made by dragging the shape.
Note that circles will maintain their radiu, and as such they could have a different asize pixel area.
</fieldset>
</body>
</html>
from satellite-imagery-labeling-tool.
Ah that's awesome, appreciate the super quick response! I had a hard time getting the drawing keyboard shortcuts to work in the non-local Labeler so I was hopeful my fruitless search for a c&p feature in Azure Maps wasn't going to apply here.
I am a bit of a html neophyte so I might have to come back to your extension at a later point 😅 Is there a project roadmap for the satellite-imagery-labeling-tool or is it mostly in the POC phase these days? the simplicity of it's design is very appealing!
from satellite-imagery-labeling-tool.
The satellite-imagery-labeling-tool is a bit of a side project. It was created as part of a disaster response mission some of us were working on last year and we made it open source and have been improving it from time to time. Inside of Microsoft it's been used in at least a dozen different projects so far and has a lot more usage than we expected.
from satellite-imagery-labeling-tool.
I took a crack at this today and added in copy paste support. To use it, do the following:
- Go into edit mode and select a shape.
- Press
CTRL + c
to copy the selected shape into memory. - Press
CTRL + v
any time afterwards to paste the shape to the map.
In the settings you can control how the shapes offset when pasted to the map.
from satellite-imagery-labeling-tool.
wow awesome thanks so much! it's a really neat tool and it's awesome that it's OSS.
from satellite-imagery-labeling-tool.
Related Issues (12)
- Consider using Azure Maps for the map control HOT 6
- Unable to label a feature as a different secondary class by selecting it on the side-menu in the labeling tool HOT 3
- Way to remove basemaps so only my layer is visible? HOT 1
- Drawn shapes not visibile when using GeoTIFF HOT 5
- Adjust brightness and contrast of image only HOT 3
- Rename `src/overpassScripts/*.txt` to `src/overpassScripts/*.overpassql` HOT 3
- Availability of data/pre/annotations/pre_labels.geojson HOT 3
- On adding a result the project viewer does not open the project HOT 7
- Feature request: lasso delete HOT 3
- Test Service URL not catching bad URL if titiler running HOT 4
- Feature request: Selecting default map layer HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from satellite-imagery-labeling-tool.