Commit d242b570 authored by Don Gagne's avatar Don Gagne

Support for circular polygons

parent e5dd4678
...@@ -34,6 +34,8 @@ Item { ...@@ -34,6 +34,8 @@ Item {
property var _dragHandlesComponent property var _dragHandlesComponent
property var _splitHandlesComponent property var _splitHandlesComponent
property var _centerDragHandleComponent property var _centerDragHandleComponent
property bool _circle: false
property real _circleRadius
property real _zorderDragHandle: QGroundControl.zOrderMapItems + 3 // Highest to prevent splitting when items overlap property real _zorderDragHandle: QGroundControl.zOrderMapItems + 3 // Highest to prevent splitting when items overlap
property real _zorderSplitHandle: QGroundControl.zOrderMapItems + 2 property real _zorderSplitHandle: QGroundControl.zOrderMapItems + 2
...@@ -71,35 +73,77 @@ Item { ...@@ -71,35 +73,77 @@ Item {
} }
} }
/// Calculate the default/initial 4 sided polygon
function defaultPolygonVertices() {
// Initial polygon is inset to take 2/3rds space
var rect = Qt.rect(map.centerViewport.x, map.centerViewport.y, map.centerViewport.width, map.centerViewport.height)
rect.x += (rect.width * 0.25) / 2
rect.y += (rect.height * 0.25) / 2
rect.width *= 0.75
rect.height *= 0.75
var centerCoord = map.toCoordinate(Qt.point(rect.x + (rect.width / 2), rect.y + (rect.height / 2)), false /* clipToViewPort */)
var topLeftCoord = map.toCoordinate(Qt.point(rect.x, rect.y), false /* clipToViewPort */)
var topRightCoord = map.toCoordinate(Qt.point(rect.x + rect.width, rect.y), false /* clipToViewPort */)
var bottomLeftCoord = map.toCoordinate(Qt.point(rect.x, rect.y + rect.height), false /* clipToViewPort */)
var bottomRightCoord = map.toCoordinate(Qt.point(rect.x + rect.width, rect.y + rect.height), false /* clipToViewPort */)
// Initial polygon has max width and height of 3000 meters
var halfWidthMeters = Math.min(topLeftCoord.distanceTo(topRightCoord), 3000) / 2
var halfHeightMeters = Math.min(topLeftCoord.distanceTo(bottomLeftCoord), 3000) / 2
topLeftCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 0)
topRightCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 0)
bottomLeftCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 180)
bottomRightCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 180)
return [ topLeftCoord, topRightCoord, bottomRightCoord, bottomLeftCoord, centerCoord ]
}
/// Add an initial 4 sided polygon /// Add an initial 4 sided polygon
function addInitialPolygon() { function addInitialPolygon() {
if (mapPolygon.count < 3) { if (mapPolygon.count < 3) {
// Initial polygon is inset to take 2/3rds space initialVertices = defaultPolygonVertices()
var rect = Qt.rect(map.centerViewport.x, map.centerViewport.y, map.centerViewport.width, map.centerViewport.height) mapPolygon.appendVertex(initialVertices[0])
rect.x += (rect.width * 0.25) / 2 mapPolygon.appendVertex(initialVertices[1])
rect.y += (rect.height * 0.25) / 2 mapPolygon.appendVertex(initialVertices[2])
rect.width *= 0.75 mapPolygon.appendVertex(initialVertices[3])
rect.height *= 0.75 }
}
var centerCoord = map.toCoordinate(Qt.point(rect.x + (rect.width / 2), rect.y + (rect.height / 2)), false /* clipToViewPort */)
var topLeftCoord = map.toCoordinate(Qt.point(rect.x, rect.y), false /* clipToViewPort */) /// Reset polygon back to initial default
var topRightCoord = map.toCoordinate(Qt.point(rect.x + rect.width, rect.y), false /* clipToViewPort */) function resetPolygon() {
var bottomLeftCoord = map.toCoordinate(Qt.point(rect.x, rect.y + rect.height), false /* clipToViewPort */) var initialVertices = defaultPolygonVertices()
var bottomRightCoord = map.toCoordinate(Qt.point(rect.x + rect.width, rect.y + rect.height), false /* clipToViewPort */) mapPolygon.clear()
for (var i=0; i<4; i++) {
// Initial polygon has max width and height of 3000 meters mapPolygon.appendVertex(initialVertices[i])
var halfWidthMeters = Math.min(topLeftCoord.distanceTo(topRightCoord), 3000) / 2 }
var halfHeightMeters = Math.min(topLeftCoord.distanceTo(bottomLeftCoord), 3000) / 2 _circle = false
topLeftCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 0) }
topRightCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 0)
bottomLeftCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 180) /// Reset polygon to a circle which fits within initial polygon
bottomRightCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 180) function setCircleRadius(center, radius) {
var unboundCenter = center.atDistanceAndAzimuth(0, 0)
mapPolygon.appendVertex(topLeftCoord) _circleRadius = radius
mapPolygon.appendVertex(topRightCoord) var segments = 16
mapPolygon.appendVertex(bottomRightCoord) var angleIncrement = 360 / segments
mapPolygon.appendVertex(bottomLeftCoord) var angle = 0
mapPolygon.clear()
for (var i=0; i<segments; i++) {
var vertex = unboundCenter.atDistanceAndAzimuth(_circleRadius, angle)
mapPolygon.appendVertex(vertex)
angle += angleIncrement
} }
_circle = true
}
/// Reset polygon to a circle which fits within initial polygon
function resetCircle() {
var initialVertices = defaultPolygonVertices()
var width = initialVertices[0].distanceTo(initialVertices[1])
var height = initialVertices[1].distanceTo(initialVertices[2])
var radius = Math.min(width, height) / 2
var center = initialVertices[4]
setCircleRadius(center, radius)
} }
onInteractiveChanged: { onInteractiveChanged: {
...@@ -122,6 +166,8 @@ Item { ...@@ -122,6 +166,8 @@ Item {
removeHandles() removeHandles()
} }
QGCPalette { id: qgcPal }
Component { Component {
id: polygonComponent id: polygonComponent
...@@ -141,6 +187,7 @@ Item { ...@@ -141,6 +187,7 @@ Item {
id: mapQuickItem id: mapQuickItem
anchorPoint.x: dragHandle.width / 2 anchorPoint.x: dragHandle.width / 2
anchorPoint.y: dragHandle.height / 2 anchorPoint.y: dragHandle.height / 2
visible: !_circle
property int vertexIndex property int vertexIndex
...@@ -149,7 +196,8 @@ Item { ...@@ -149,7 +196,8 @@ Item {
width: ScreenTools.defaultFontPixelHeight * 1.5 width: ScreenTools.defaultFontPixelHeight * 1.5
height: width height: width
radius: width / 2 radius: width / 2
color: "white" border.color: "white"
color: "transparent"
opacity: .50 opacity: .50
z: _zorderSplitHandle z: _zorderSplitHandle
...@@ -208,8 +256,9 @@ Item { ...@@ -208,8 +256,9 @@ Item {
id: dragAreaComponent id: dragAreaComponent
MissionItemIndicatorDrag { MissionItemIndicatorDrag {
id: dragArea id: dragArea
z: _zorderDragHandle z: _zorderDragHandle
visible: !_circle
property int polygonVertex property int polygonVertex
...@@ -219,15 +268,44 @@ Item { ...@@ -219,15 +268,44 @@ Item {
onItemCoordinateChanged: { onItemCoordinateChanged: {
if (_creationComplete) { if (_creationComplete) {
// During component creation some bad coordinate values got through which screws up polygon draw // During component creation some bad coordinate values got through which screws up draw
mapPolygon.adjustVertex(polygonVertex, itemCoordinate) mapPolygon.adjustVertex(polygonVertex, itemCoordinate)
} }
} }
onDragStop: adjustCircleRadius(itemCoordinate)
onClicked: mapPolygon.removeVertex(polygonVertex) onClicked: mapPolygon.removeVertex(polygonVertex)
} }
} }
Component {
id: centerDragHandle
MapQuickItem {
id: mapQuickItem
anchorPoint.x: dragHandle.width / 2
anchorPoint.y: dragHandle.height / 2
z: _zorderDragHandle
sourceItem: Rectangle {
id: dragHandle
width: ScreenTools.defaultFontPixelHeight * 1.5
height: width
radius: width / 2
color: "white"
opacity: .90
QGCLabel {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
text: "..."
color: "black"
}
}
}
}
Component { Component {
id: dragHandleComponent id: dragHandleComponent
...@@ -236,6 +314,9 @@ Item { ...@@ -236,6 +314,9 @@ Item {
anchorPoint.x: dragHandle.width / 2 anchorPoint.x: dragHandle.width / 2
anchorPoint.y: dragHandle.height / 2 anchorPoint.y: dragHandle.height / 2
z: _zorderDragHandle z: _zorderDragHandle
visible: !_circle
property int polygonVertex
sourceItem: Rectangle { sourceItem: Rectangle {
id: dragHandle id: dragHandle
...@@ -261,6 +342,7 @@ Item { ...@@ -261,6 +342,7 @@ Item {
Component.onCompleted: { Component.onCompleted: {
var dragHandle = dragHandleComponent.createObject(mapControl) var dragHandle = dragHandleComponent.createObject(mapControl)
dragHandle.coordinate = Qt.binding(function() { return object.coordinate }) dragHandle.coordinate = Qt.binding(function() { return object.coordinate })
dragHandle.polygonVertex = Qt.binding(function() { return index })
mapControl.addMapItem(dragHandle) mapControl.addMapItem(dragHandle)
var dragArea = dragAreaComponent.createObject(mapControl, { "itemIndicator": dragHandle, "itemCoordinate": object.coordinate }) var dragArea = dragAreaComponent.createObject(mapControl, { "itemIndicator": dragHandle, "itemCoordinate": object.coordinate })
dragArea.polygonVertex = Qt.binding(function() { return index }) dragArea.polygonVertex = Qt.binding(function() { return index })
...@@ -286,6 +368,75 @@ Item { ...@@ -286,6 +368,75 @@ Item {
onItemCoordinateChanged: mapPolygon.center = itemCoordinate onItemCoordinateChanged: mapPolygon.center = itemCoordinate
onDragStart: mapPolygon.centerDrag = true onDragStart: mapPolygon.centerDrag = true
onDragStop: mapPolygon.centerDrag = false onDragStop: mapPolygon.centerDrag = false
onClicked: menu.popup()
function setRadiusFromDialog() {
setCircleRadius(mapPolygon.center, radiusField.text)
radiusDialog.visible = false
}
Menu {
id: menu
MenuItem {
text: qsTr("Circle" )
onTriggered: resetCircle()
}
MenuItem {
text: qsTr("Polygon")
onTriggered: resetPolygon()
}
MenuItem {
text: qsTr("Set radius..." )
enabled: _circle
onTriggered: radiusDialog.visible = true
}
MenuItem {
text: qsTr("Load KML...")
enabled: false
}
}
Rectangle {
id: radiusDialog
anchors.margins: _margin
anchors.left: parent.right
width: radiusColumn.width + (_margin *2)
height: radiusColumn.height + (_margin *2)
color: qgcPal.window
border.color: qgcPal.text
visible: false
Column {
id: radiusColumn
anchors.margins: _margin
anchors.left: parent.left
anchors.top: parent.top
spacing: _margin
QGCLabel { text: qsTr("Radius:") }
QGCTextField {
id: radiusField
text: _circleRadius.toFixed(2)
onEditingFinished: setRadiusFromDialog()
}
}
QGCLabel {
anchors.right: radiusColumn.right
anchors.top: radiusColumn.top
text: "X"
QGCMouseArea {
fillItem: parent
onClicked: setRadiusFromDialog()
}
}
}
} }
} }
...@@ -297,7 +448,7 @@ Item { ...@@ -297,7 +448,7 @@ Item {
property var dragArea property var dragArea
Component.onCompleted: { Component.onCompleted: {
dragHandle = dragHandleComponent.createObject(mapControl) dragHandle = centerDragHandle.createObject(mapControl)
dragHandle.coordinate = Qt.binding(function() { return mapPolygon.center }) dragHandle.coordinate = Qt.binding(function() { return mapPolygon.center })
mapControl.addMapItem(dragHandle) mapControl.addMapItem(dragHandle)
dragArea = centerDragAreaComponent.createObject(mapControl, { "itemIndicator": dragHandle, "itemCoordinate": mapPolygon.center }) dragArea = centerDragAreaComponent.createObject(mapControl, { "itemIndicator": dragHandle, "itemCoordinate": mapPolygon.center })
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment