Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qgroundcontrol
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Valentin Platzgummer
qgroundcontrol
Commits
47641f63
Commit
47641f63
authored
Sep 26, 2020
by
Valentin Platzgummer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wima planer edited
parent
1ac83998
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
555 additions
and
1030 deletions
+555
-1030
CircularSurveyItemEditor.qml
src/PlanView/CircularSurveyItemEditor.qml
+48
-24
CSWorker.cpp
src/Wima/CSWorker.cpp
+1
-1
CS_old.cc
src/Wima/CS_old.cc
+0
-737
CircularSurvey.cc
src/Wima/CircularSurvey.cc
+228
-44
CircularSurvey.h
src/Wima/CircularSurvey.h
+24
-12
WimaJoinedAreaData.cc
src/Wima/Geometry/WimaJoinedAreaData.cc
+26
-36
WimaMeasurementAreaData.cc
src/Wima/Geometry/WimaMeasurementAreaData.cc
+49
-35
WimaMeasurementAreaData.h
src/Wima/Geometry/WimaMeasurementAreaData.h
+19
-18
WimaController.cc
src/Wima/WimaController.cc
+36
-32
WimaController.h
src/Wima/WimaController.h
+8
-13
WimaPlanData.cc
src/Wima/WimaPlanData.cc
+8
-0
WimaPlanData.h
src/Wima/WimaPlanData.h
+5
-7
WimaPlaner.cc
src/Wima/WimaPlaner.cc
+11
-14
WimaPlaner.h
src/Wima/WimaPlaner.h
+1
-0
CircularSurvey.SettingsGroup.json
src/Wima/json/CircularSurvey.SettingsGroup.json
+13
-25
CircularSurveyMapVisual.qml
src/WimaView/CircularSurveyMapVisual.qml
+77
-31
WimaServiceAreaMapVisual.qml
src/WimaView/WimaServiceAreaMapVisual.qml
+1
-1
No files found.
src/PlanView/CircularSurveyItemEditor.qml
View file @
47641f63
...
@@ -64,6 +64,7 @@ Rectangle {
...
@@ -64,6 +64,7 @@ Rectangle {
GridLayout
{
GridLayout
{
id
:
generalGrid
anchors.left
:
parent
.
left
anchors.left
:
parent
.
left
anchors.right
:
parent
.
right
anchors.right
:
parent
.
right
columnSpacing
:
_margin
columnSpacing
:
_margin
...
@@ -75,7 +76,48 @@ Rectangle {
...
@@ -75,7 +76,48 @@ Rectangle {
FactTextField
{
FactTextField
{
fact
:
missionItem
.
cameraCalc
.
distanceToSurface
fact
:
missionItem
.
cameraCalc
.
distanceToSurface
Layout.fillWidth
:
true
Layout.fillWidth
:
true
//onUpdated: rSlider.value = missionItem.deltaR.value
}
QGCCheckBox
{
id
:
relAlt
text
:
qsTr
(
"
Relative altitude
"
)
checked
:
missionItem
.
cameraCalc
.
distanceToSurfaceRelative
enabled
:
missionItem
.
cameraCalc
.
isManualCamera
&&
!
missionItem
.
followTerrain
visible
:
QGroundControl
.
corePlugin
.
options
.
showMissionAbsoluteAltitude
||
(
!
missionItem
.
cameraCalc
.
distanceToSurfaceRelative
&&
!
missionItem
.
followTerrain
)
onClicked
:
missionItem
.
cameraCalc
.
distanceToSurfaceRelative
=
checked
Layout.fillWidth
:
true
Layout.columnSpan
:
2
Connections
{
target
:
missionItem
.
cameraCalc
onDistanceToSurfaceRelativeChanged
:
relAlt
.
checked
=
missionItem
.
cameraCalc
.
distanceToSurfaceRelative
}
}
QGCLabel
{
text
:
qsTr
(
"
Type
"
)
Layout.columnSpan
:
2
}
property
var
typeFact
:
missionItem
.
type
property
int
type
:
typeFact
.
value
property
var
names
:
[
"
Circular
"
,
"
Linear
"
]
ExclusiveGroup
{
id
:
typeGroup
}
Repeater
{
model
:
missionItem
.
typeCount
QGCRadioButton
{
checked
:
index
===
generalGrid
.
type
text
:
qsTr
(
generalGrid
.
names
[
index
])
onCheckedChanged
:
{
if
(
checked
){
missionItem
.
type
.
value
=
index
}
checked
=
Qt
.
binding
(
function
(){
return
index
===
generalGrid
.
type
})
}
}
}
}
}
}
...
@@ -92,11 +134,10 @@ Rectangle {
...
@@ -92,11 +134,10 @@ Rectangle {
columns
:
2
columns
:
2
visible
:
transectsHeader
.
checked
visible
:
transectsHeader
.
checked
QGCLabel
{
text
:
qsTr
(
"
D
elta R
"
)
}
QGCLabel
{
text
:
qsTr
(
"
D
istance
"
)
}
FactTextField
{
FactTextField
{
fact
:
missionItem
.
deltaR
fact
:
missionItem
.
transectDistance
Layout.fillWidth
:
true
Layout.fillWidth
:
true
//onUpdated: rSlider.value = missionItem.deltaR.value
}
}
/*QGCSlider {
/*QGCSlider {
...
@@ -113,18 +154,16 @@ Rectangle {
...
@@ -113,18 +154,16 @@ Rectangle {
updateValueWhileDragging: true
updateValueWhileDragging: true
}*/
}*/
QGCLabel
{
text
:
qsTr
(
"
Delta
Alpha
"
)
}
QGCLabel
{
text
:
qsTr
(
"
Alpha
"
)
}
FactTextField
{
FactTextField
{
fact
:
missionItem
.
deltaA
lpha
fact
:
missionItem
.
a
lpha
Layout.fillWidth
:
true
Layout.fillWidth
:
true
//onUpdated: angleSlider.value = missionItem.deltaAlpha.value
}
}
QGCLabel
{
text
:
qsTr
(
"
Min. Length
"
)
}
QGCLabel
{
text
:
qsTr
(
"
Min. Length
"
)
}
FactTextField
{
FactTextField
{
fact
:
missionItem
.
transectM
inLength
fact
:
missionItem
.
m
inLength
Layout.fillWidth
:
true
Layout.fillWidth
:
true
//onUpdated: angleSlider.value = missionItem.deltaAlpha.value
}
}
}
}
...
@@ -148,21 +187,6 @@ Rectangle {
...
@@ -148,21 +187,6 @@ Rectangle {
Layout.fillWidth
:
true
Layout.fillWidth
:
true
}
}
QGCCheckBox
{
id
:
relAlt
text
:
qsTr
(
"
Relative altitude
"
)
checked
:
missionItem
.
cameraCalc
.
distanceToSurfaceRelative
enabled
:
missionItem
.
cameraCalc
.
isManualCamera
&&
!
missionItem
.
followTerrain
visible
:
QGroundControl
.
corePlugin
.
options
.
showMissionAbsoluteAltitude
||
(
!
missionItem
.
cameraCalc
.
distanceToSurfaceRelative
&&
!
missionItem
.
followTerrain
)
onClicked
:
missionItem
.
cameraCalc
.
distanceToSurfaceRelative
=
checked
Layout.fillWidth
:
true
Layout.columnSpan
:
2
Connections
{
target
:
missionItem
.
cameraCalc
onDistanceToSurfaceRelativeChanged
:
relAlt
.
checked
=
missionItem
.
cameraCalc
.
distanceToSurfaceRelative
}
}
}
}
...
...
src/Wima/CSWorker.cpp
View file @
47641f63
...
@@ -73,7 +73,7 @@ void RoutingWorker::run() {
...
@@ -73,7 +73,7 @@ void RoutingWorker::run() {
auto
&
transectsInfo
=
pRouteData
->
transectsInfo
;
auto
&
transectsInfo
=
pRouteData
->
transectsInfo
;
auto
&
route
=
pRouteData
->
route
;
auto
&
route
=
pRouteData
->
route
;
const
auto
routingStart
=
std
::
chrono
::
high_resolution_clock
::
now
();
const
auto
routingStart
=
std
::
chrono
::
high_resolution_clock
::
now
();
const
auto
maxRoutingTime
=
std
::
chrono
::
minutes
(
1
);
const
auto
maxRoutingTime
=
std
::
chrono
::
minutes
(
1
0
);
const
auto
routingEnd
=
routingStart
+
maxRoutingTime
;
const
auto
routingEnd
=
routingStart
+
maxRoutingTime
;
const
auto
&
restart
=
this
->
_restart
;
const
auto
&
restart
=
this
->
_restart
;
auto
stopLambda
=
[
&
restart
,
routingEnd
]
{
auto
stopLambda
=
[
&
restart
,
routingEnd
]
{
...
...
src/Wima/CS_old.cc
deleted
100644 → 0
View file @
1ac83998
#
include
"CircularSurveyComplexItem.h"
#include "JsonHelper.h"
#include "QGCApplication.h"
#include <chrono>
const
char
*
CircularSurveyComplexItem
::
settingsGroup
=
"CircularSurvey"
;
const
char
*
CircularSurveyComplexItem
::
deltaRName
=
"DeltaR"
;
const
char
*
CircularSurveyComplexItem
::
deltaAlphaName
=
"DeltaAlpha"
;
const
char
*
CircularSurveyComplexItem
::
transectMinLengthName
=
"TransectMinLength"
;
const
char
*
CircularSurveyComplexItem
::
fixedDirectionName
=
"FixedDirection"
;
const
char
*
CircularSurveyComplexItem
::
reverseName
=
"Reverse"
;
const
char
*
CircularSurveyComplexItem
::
maxWaypointsName
=
"MaxWaypoints"
;
const
char
*
CircularSurveyComplexItem
::
jsonComplexItemTypeValue
=
"circularSurvey"
;
const
char
*
CircularSurveyComplexItem
::
jsonDeltaRKey
=
"deltaR"
;
const
char
*
CircularSurveyComplexItem
::
jsonDeltaAlphaKey
=
"deltaAlpha"
;
const
char
*
CircularSurveyComplexItem
::
jsonTransectMinLengthKey
=
"transectMinLength"
;
const
char
*
CircularSurveyComplexItem
::
jsonfixedDirectionKey
=
"fixedDirection"
;
const
char
*
CircularSurveyComplexItem
::
jsonReverseKey
=
"reverse"
;
const
char
*
CircularSurveyComplexItem
::
jsonReferencePointLatKey
=
"referencePointLat"
;
const
char
*
CircularSurveyComplexItem
::
jsonReferencePointLongKey
=
"referencePointLong"
;
const
char
*
CircularSurveyComplexItem
::
jsonReferencePointAltKey
=
"referencePointAlt"
;
CircularSurveyComplexItem
::
CircularSurveyComplexItem
(
Vehicle
*
vehicle
,
bool
flyView
,
const
QString
&
kmlOrShpFile
,
QObject
*
parent
)
:
TransectStyleComplexItem
(
vehicle
,
flyView
,
settingsGroup
,
parent
)
,
_referencePoint
(
QGeoCoordinate
(
0
,
0
,
0
))
,
_metaDataMap
(
FactMetaData
::
createMapFromJsonFile
(
QStringLiteral
(
":/json/CircularSurvey.SettingsGroup.json"
),
this
))
,
_deltaR
(
settingsGroup
,
_metaDataMap
[
deltaRName
])
,
_deltaAlpha
(
settingsGroup
,
_metaDataMap
[
deltaAlphaName
])
,
_transectMinLength
(
settingsGroup
,
_metaDataMap
[
transectMinLengthName
])
,
_fixedDirection
(
settingsGroup
,
_metaDataMap
[
fixedDirectionName
])
,
_reverse
(
settingsGroup
,
_metaDataMap
[
reverseName
])
,
_maxWaypoints
(
settingsGroup
,
_metaDataMap
[
maxWaypointsName
])
,
_isInitialized
(
false
)
,
_reverseOnly
(
false
)
{
Q_UNUSED
(
kmlOrShpFile
)
_editorQml
=
"qrc:/qml/CircularSurveyItemEditor.qml"
;
connect
(
&
_deltaR
,
&
Fact
::
valueChanged
,
this
,
&
CircularSurveyComplexItem
::
_triggerSlowRecalc
);
connect
(
&
_deltaAlpha
,
&
Fact
::
valueChanged
,
this
,
&
CircularSurveyComplexItem
::
_triggerSlowRecalc
);
connect
(
&
_transectMinLength
,
&
Fact
::
valueChanged
,
this
,
&
CircularSurveyComplexItem
::
_triggerSlowRecalc
);
connect
(
&
_fixedDirection
,
&
Fact
::
valueChanged
,
this
,
&
CircularSurveyComplexItem
::
_triggerSlowRecalc
);
connect
(
&
_maxWaypoints
,
&
Fact
::
valueChanged
,
this
,
&
CircularSurveyComplexItem
::
_triggerSlowRecalc
);
connect
(
&
_reverse
,
&
Fact
::
valueChanged
,
this
,
&
CircularSurveyComplexItem
::
_reverseTransects
);
connect
(
this
,
&
CircularSurveyComplexItem
::
refPointChanged
,
this
,
&
CircularSurveyComplexItem
::
_triggerSlowRecalc
);
//connect(&_cameraCalc.distanceToSurface(), &Fact::rawValueChanged, this->)
}
void
CircularSurveyComplexItem
::
resetReference
()
{
setRefPoint
(
_surveyAreaPolygon
.
center
());
}
void
CircularSurveyComplexItem
::
comprehensiveUpdate
()
{
_triggerSlowRecalc
();
}
void
CircularSurveyComplexItem
::
setRefPoint
(
const
QGeoCoordinate
&
refPt
)
{
if
(
refPt
!=
_referencePoint
){
_referencePoint
=
refPt
;
emit
refPointChanged
();
}
}
void
CircularSurveyComplexItem
::
setIsInitialized
(
bool
isInitialized
)
{
if
(
isInitialized
!=
_isInitialized
)
{
_isInitialized
=
isInitialized
;
emit
isInitializedChanged
();
}
}
QGeoCoordinate
CircularSurveyComplexItem
::
refPoint
()
const
{
return
_referencePoint
;
}
Fact
*
CircularSurveyComplexItem
::
deltaR
()
{
return
&
_deltaR
;
}
Fact
*
CircularSurveyComplexItem
::
deltaAlpha
()
{
return
&
_deltaAlpha
;
}
bool
CircularSurveyComplexItem
::
isInitialized
()
{
return
_isInitialized
;
}
bool
CircularSurveyComplexItem
::
load
(
const
QJsonObject
&
complexObject
,
int
sequenceNumber
,
QString
&
errorString
)
{
// We need to pull version first to determine what validation/conversion needs to be performed
QList
<
JsonHelper
::
KeyValidateInfo
>
versionKeyInfoList
=
{
{
JsonHelper
::
jsonVersionKey
,
QJsonValue
::
Double
,
true
},
};
if
(
!
JsonHelper
::
validateKeys
(
complexObject
,
versionKeyInfoList
,
errorString
))
{
return
false
;
}
int
version
=
complexObject
[
JsonHelper
::
jsonVersionKey
].
toInt
();
if
(
version
!=
1
)
{
errorString
=
tr
(
"Survey items do not support version %1"
).
arg
(
version
);
return
false
;
}
QList
<
JsonHelper
::
KeyValidateInfo
>
keyInfoList
=
{
{
VisualMissionItem
::
jsonTypeKey
,
QJsonValue
::
String
,
true
},
{
ComplexMissionItem
::
jsonComplexItemTypeKey
,
QJsonValue
::
String
,
true
},
{
jsonDeltaRKey
,
QJsonValue
::
Double
,
true
},
{
jsonDeltaAlphaKey
,
QJsonValue
::
Double
,
true
},
{
jsonTransectMinLengthKey
,
QJsonValue
::
Double
,
true
},
{
jsonfixedDirectionKey
,
QJsonValue
::
Bool
,
true
},
{
jsonReverseKey
,
QJsonValue
::
Bool
,
true
},
{
jsonReferencePointLatKey
,
QJsonValue
::
Double
,
true
},
{
jsonReferencePointLongKey
,
QJsonValue
::
Double
,
true
},
{
jsonReferencePointAltKey
,
QJsonValue
::
Double
,
true
},
};
if
(
!
JsonHelper
::
validateKeys
(
complexObject
,
keyInfoList
,
errorString
))
{
return
false
;
}
QString
itemType
=
complexObject
[
VisualMissionItem
::
jsonTypeKey
].
toString
();
QString
complexType
=
complexObject
[
ComplexMissionItem
::
jsonComplexItemTypeKey
].
toString
();
if
(
itemType
!=
VisualMissionItem
::
jsonTypeComplexItemValue
||
complexType
!=
jsonComplexItemTypeValue
)
{
errorString
=
tr
(
"%1 does not support loading this complex mission item type: %2:%3"
).
arg
(
qgcApp
()
->
applicationName
()).
arg
(
itemType
).
arg
(
complexType
);
return
false
;
}
_ignoreRecalc
=
true
;
setSequenceNumber
(
sequenceNumber
);
if
(
!
_surveyAreaPolygon
.
loadFromJson
(
complexObject
,
true
/* required */
,
errorString
))
{
_surveyAreaPolygon
.
clear
();
return
false
;
}
if
(
!
_load
(
complexObject
,
errorString
))
{
_ignoreRecalc
=
false
;
return
false
;
}
_deltaR
.
setRawValue
(
complexObject
[
jsonDeltaRKey
].
toDouble
());
_deltaAlpha
.
setRawValue
(
complexObject
[
jsonDeltaAlphaKey
].
toDouble
());
_transectMinLength
.
setRawValue
(
complexObject
[
jsonTransectMinLengthKey
].
toDouble
());
_referencePoint
.
setLongitude
(
complexObject
[
jsonReferencePointLongKey
].
toDouble
());
_referencePoint
.
setLatitude
(
complexObject
[
jsonReferencePointLatKey
].
toDouble
());
_referencePoint
.
setAltitude
(
complexObject
[
jsonReferencePointAltKey
].
toDouble
());
_fixedDirection
.
setRawValue
(
complexObject
[
jsonfixedDirectionKey
].
toBool
());
_reverse
.
setRawValue
(
complexObject
[
jsonReverseKey
].
toBool
());
setIsInitialized
(
true
);
_ignoreRecalc
=
false
;
_recalcComplexDistance
();
if
(
_cameraShots
==
0
)
{
// Shot count was possibly not available from plan file
_recalcCameraShots
();
}
return
true
;
}
void
CircularSurveyComplexItem
::
save
(
QJsonArray
&
planItems
)
{
QJsonObject
saveObject
;
_save
(
saveObject
);
saveObject
[
JsonHelper
::
jsonVersionKey
]
=
1
;
saveObject
[
VisualMissionItem
::
jsonTypeKey
]
=
VisualMissionItem
::
jsonTypeComplexItemValue
;
saveObject
[
ComplexMissionItem
::
jsonComplexItemTypeKey
]
=
jsonComplexItemTypeValue
;
saveObject
[
jsonDeltaRKey
]
=
_deltaR
.
rawValue
().
toDouble
();
saveObject
[
jsonDeltaAlphaKey
]
=
_deltaAlpha
.
rawValue
().
toDouble
();
saveObject
[
jsonTransectMinLengthKey
]
=
_transectMinLength
.
rawValue
().
toDouble
();
saveObject
[
jsonfixedDirectionKey
]
=
_fixedDirection
.
rawValue
().
toBool
();
saveObject
[
jsonReverseKey
]
=
_reverse
.
rawValue
().
toBool
();
saveObject
[
jsonReferencePointLongKey
]
=
_referencePoint
.
longitude
();
saveObject
[
jsonReferencePointLatKey
]
=
_referencePoint
.
latitude
();
saveObject
[
jsonReferencePointAltKey
]
=
_referencePoint
.
altitude
();
// Polygon shape
_surveyAreaPolygon
.
saveToJson
(
saveObject
);
planItems
.
append
(
saveObject
);
}
void
CircularSurveyComplexItem
::
appendMissionItems
(
QList
<
MissionItem
*>
&
items
,
QObject
*
missionItemParent
)
{
if
(
_transectsDirty
)
return
;
if
(
_loadedMissionItems
.
count
())
{
// We have mission items from the loaded plan, use those
_appendLoadedMissionItems
(
items
,
missionItemParent
);
}
else
{
// Build the mission items on the fly
_buildAndAppendMissionItems
(
items
,
missionItemParent
);
}
}
void
CircularSurveyComplexItem
::
_appendLoadedMissionItems
(
QList
<
MissionItem
*>&
items
,
QObject
*
missionItemParent
)
{
//qCDebug(SurveyComplexItemLog) << "_appendLoadedMissionItems";
if
(
_transectsDirty
)
return
;
int
seqNum
=
_sequenceNumber
;
for
(
const
MissionItem
*
loadedMissionItem
:
_loadedMissionItems
)
{
MissionItem
*
item
=
new
MissionItem
(
*
loadedMissionItem
,
missionItemParent
);
item
->
setSequenceNumber
(
seqNum
++
);
items
.
append
(
item
);
}
}
void
CircularSurveyComplexItem
::
_buildAndAppendMissionItems
(
QList
<
MissionItem
*>&
items
,
QObject
*
missionItemParent
)
{
// original code: SurveyComplexItem::_buildAndAppendMissionItems()
//qCDebug(SurveyComplexItemLog) << "_buildAndAppendMissionItems";
// Now build the mission items from the transect points
if
(
_transectsDirty
)
return
;
MissionItem
*
item
;
int
seqNum
=
_sequenceNumber
;
MAV_FRAME
mavFrame
=
followTerrain
()
||
!
_cameraCalc
.
distanceToSurfaceRelative
()
?
MAV_FRAME_GLOBAL
:
MAV_FRAME_GLOBAL_RELATIVE_ALT
;
for
(
const
QList
<
TransectStyleComplexItem
::
CoordInfo_t
>&
transect
:
_transects
)
{
//bool transectEntry = true;
for
(
const
CoordInfo_t
&
transectCoordInfo
:
transect
)
{
item
=
new
MissionItem
(
seqNum
++
,
MAV_CMD_NAV_WAYPOINT
,
mavFrame
,
0
,
// Hold time (delay for hover and capture to settle vehicle before image is taken)
0.0
,
// No acceptance radius specified
0.0
,
// Pass through waypoint
std
::
numeric_limits
<
double
>::
quiet_NaN
(),
// Yaw unchanged
transectCoordInfo
.
coord
.
latitude
(),
transectCoordInfo
.
coord
.
longitude
(),
transectCoordInfo
.
coord
.
altitude
(),
true
,
// autoContinue
false
,
// isCurrentItem
missionItemParent
);
items
.
append
(
item
);
}
}
}
void
CircularSurveyComplexItem
::
applyNewAltitude
(
double
newAltitude
)
{
_cameraCalc
.
valueSetIsDistance
()
->
setRawValue
(
true
);
_cameraCalc
.
distanceToSurface
()
->
setRawValue
(
newAltitude
);
_cameraCalc
.
setDistanceToSurfaceRelative
(
true
);
}
double
CircularSurveyComplexItem
::
timeBetweenShots
()
{
return
1
;
}
bool
CircularSurveyComplexItem
::
readyForSave
()
const
{
return
TransectStyleComplexItem
::
readyForSave
();
}
double
CircularSurveyComplexItem
::
additionalTimeDelay
()
const
{
return
0
;
}
void
CircularSurveyComplexItem
::
_rebuildTransectsPhase1
(
void
){
if
(
_doFastRecalc
){
_rebuildTransectsFast
();
}
else
{
_rebuildTransectsSlow
();
_doFastRecalc
=
true
;
}
}
void
CircularSurveyComplexItem
::
_rebuildTransectsFast
()
{
using
namespace
GeoUtilities
;
using
namespace
PolygonCalculus
;
using
namespace
PlanimetryCalculus
;
_transects
.
clear
();
QPolygonF
surveyPolygon
;
toCartesianList
(
_surveyAreaPolygon
.
coordinateList
(),
_referencePoint
,
surveyPolygon
);
if
(
!
_rebuildTransectsInputCheck
(
surveyPolygon
))
return
;
// If the transects are getting rebuilt then any previously loaded mission items are now invalid
if
(
_loadedMissionItemsParent
)
{
_loadedMissionItems
.
clear
();
_loadedMissionItemsParent
->
deleteLater
();
_loadedMissionItemsParent
=
nullptr
;
}
QVector
<
QVector
<
QPointF
>>
transectPath
;
if
(
!
_generateTransectPath
(
transectPath
,
surveyPolygon
))
return
;
/// optimize path to snake or zig-zag pattern
bool
fixedDirectionBool
=
_fixedDirection
.
rawValue
().
toBool
();
QVector
<
QPointF
>
currentSection
=
transectPath
.
takeFirst
();
if
(
currentSection
.
isEmpty
()
)
return
;
QVector
<
QPointF
>
optiPath
;
// optimized path
while
(
!
transectPath
.
empty
()
)
{
optiPath
.
append
(
currentSection
);
QPointF
endVertex
=
currentSection
.
last
();
double
minDist
=
std
::
numeric_limits
<
double
>::
infinity
();
int
index
=
0
;
bool
reversePath
=
false
;
// iterate over all paths in fullPath and assign the one with the shortest distance to endVertex to currentSection
for
(
int
i
=
0
;
i
<
transectPath
.
size
();
i
++
)
{
auto
iteratorPath
=
transectPath
[
i
];
double
dist
=
PlanimetryCalculus
::
distance
(
endVertex
,
iteratorPath
.
first
());
if
(
dist
<
minDist
)
{
minDist
=
dist
;
index
=
i
;
reversePath
=
false
;
}
dist
=
PlanimetryCalculus
::
distance
(
endVertex
,
iteratorPath
.
last
());
if
(
dist
<
minDist
)
{
minDist
=
dist
;
index
=
i
;
reversePath
=
true
;
}
}
currentSection
=
transectPath
.
takeAt
(
index
);
if
(
reversePath
&&
!
fixedDirectionBool
)
{
PolygonCalculus
::
reversePath
(
currentSection
);
}
}
optiPath
.
append
(
currentSection
);
// append last section
if
(
optiPath
.
size
()
>
_maxWaypoints
.
rawValue
().
toInt
())
return
;
_rebuildTransectsToGeo
(
optiPath
,
_referencePoint
);
_transectsDirty
=
true
;
}
void
CircularSurveyComplexItem
::
_rebuildTransectsSlow
()
{
using
namespace
GeoUtilities
;
using
namespace
PolygonCalculus
;
using
namespace
PlanimetryCalculus
;
if
(
_reverseOnly
)
{
// reverse transects and return
_reverseOnly
=
false
;
QList
<
QList
<
CoordInfo_t
>>
transectsReverse
;
transectsReverse
.
reserve
(
_transects
.
size
());
for
(
auto
list
:
_transects
)
{
QList
<
CoordInfo_t
>
listReverse
;
for
(
auto
coordinate
:
list
)
listReverse
.
prepend
(
coordinate
);
transectsReverse
.
prepend
(
listReverse
);
}
_transects
=
transectsReverse
;
return
;
}
_transects
.
clear
();
QPolygonF
surveyPolygon
;
toCartesianList
(
_surveyAreaPolygon
.
coordinateList
(),
_referencePoint
,
surveyPolygon
);
if
(
!
_rebuildTransectsInputCheck
(
surveyPolygon
))
return
;
// If the transects are getting rebuilt then any previously loaded mission items are now invalid.
if
(
_loadedMissionItemsParent
)
{
_loadedMissionItems
.
clear
();
_loadedMissionItemsParent
->
deleteLater
();
_loadedMissionItemsParent
=
nullptr
;
}
QVector
<
QVector
<
QPointF
>>
transectPath
;
if
(
!
_generateTransectPath
(
transectPath
,
surveyPolygon
))
return
;
// optimize path to snake or zig-zag pattern
const
bool
fixedDirectionBool
=
_fixedDirection
.
rawValue
().
toBool
();
QVector
<
QPointF
>
currentSection
=
transectPath
.
takeFirst
();
if
(
currentSection
.
isEmpty
()
)
return
;
QVector
<
QPointF
>
optimizedPath
(
currentSection
);
bool
reversePath
=
true
;
// controlls if currentSection gets reversed, has nothing todo with _reverseOnly
while
(
!
transectPath
.
empty
()
)
{
QPointF
endVertex
=
currentSection
.
last
();
double
minDist
=
std
::
numeric_limits
<
double
>::
infinity
();
int
index
=
0
;
// iterate over all paths in fullPath and assign the one with the shortest distance to endVertex to currentSection
QVector
<
QPointF
>
connectorPath
;
for
(
int
i
=
0
;
i
<
transectPath
.
size
();
i
++
)
{
QVector
<
QPointF
>
iteratorPath
=
transectPath
[
i
];
QVector
<
QPointF
>
tempConnectorPath
;
bool
retVal
;
if
(
reversePath
&&
!
fixedDirectionBool
)
{
retVal
=
PolygonCalculus
::
shortestPath
(
surveyPolygon
,
endVertex
,
iteratorPath
.
last
(),
tempConnectorPath
);
}
else
{
retVal
=
PolygonCalculus
::
shortestPath
(
surveyPolygon
,
endVertex
,
iteratorPath
.
first
(),
tempConnectorPath
);
}
if
(
!
retVal
)
qWarning
(
"CircularSurveyComplexItem::_rebuildTransectsPhase1: internal error; false shortestPath"
);
double
dist
=
0
;
for
(
int
i
=
0
;
i
<
tempConnectorPath
.
size
()
-
1
;
++
i
)
dist
+=
PlanimetryCalculus
::
distance
(
tempConnectorPath
[
i
],
tempConnectorPath
[
i
+
1
]);
if
(
dist
<
minDist
)
{
minDist
=
dist
;
index
=
i
;
connectorPath
=
tempConnectorPath
;
}
}
currentSection
=
transectPath
.
takeAt
(
index
);
if
(
reversePath
&&
!
fixedDirectionBool
)
{
PolygonCalculus
::
reversePath
(
currentSection
);
}
reversePath
^=
true
;
// toggle
connectorPath
.
pop_front
();
connectorPath
.
pop_back
();
if
(
connectorPath
.
size
()
>
0
)
optimizedPath
.
append
(
connectorPath
);
optimizedPath
.
append
(
currentSection
);
}
if
(
optimizedPath
.
size
()
>
_maxWaypoints
.
rawValue
().
toInt
())
return
;
_rebuildTransectsToGeo
(
optimizedPath
,
_referencePoint
);
_transectsDirty
=
false
;
//_triggerSlowRecalcTimer.stop(); // stop any pending slow recalculations
return
;
}
void
CircularSurveyComplexItem
::
_triggerSlowRecalc
()
{
_doFastRecalc
=
false
;
_rebuildTransects
();
}
void
CircularSurveyComplexItem
::
_recalcComplexDistance
()
{
_complexDistance
=
0
;
if
(
_transectsDirty
)
return
;
for
(
int
i
=
0
;
i
<
_visualTransectPoints
.
count
()
-
1
;
i
++
)
{
_complexDistance
+=
_visualTransectPoints
[
i
].
value
<
QGeoCoordinate
>
().
distanceTo
(
_visualTransectPoints
[
i
+
1
].
value
<
QGeoCoordinate
>
());
}
emit
complexDistanceChanged
();
}
// no cameraShots in Circular Survey, add if desired
void
CircularSurveyComplexItem
::
_recalcCameraShots
()
{
_cameraShots
=
0
;
}
void
CircularSurveyComplexItem
::
_reverseTransects
()
{
_reverseOnly
=
true
;
_triggerSlowRecalc
();
}
bool
CircularSurveyComplexItem
::
_shortestPath
(
const
QGeoCoordinate
&
start
,
const
QGeoCoordinate
&
destination
,
QVector
<
QGeoCoordinate
>
&
shortestPath
)
{
using
namespace
GeoUtilities
;
using
namespace
PolygonCalculus
;
QPolygonF
polygon2D
;
toCartesianList
(
this
->
surveyAreaPolygon
()
->
coordinateList
(),
/*origin*/
start
,
polygon2D
);
QPointF
start2D
(
0
,
0
);
QPointF
end2D
;
toCartesian
(
destination
,
start
,
end2D
);
QVector
<
QPointF
>
path2D
;
bool
retVal
=
PolygonCalculus
::
shortestPath
(
polygon2D
,
start2D
,
end2D
,
path2D
);
if
(
retVal
)
toGeoList
(
path2D
,
/*origin*/
start
,
shortestPath
);
return
retVal
;
}
bool
CircularSurveyComplexItem
::
_generateTransectPath
(
QVector
<
QVector
<
QPointF
>
>
&
transectPath
,
const
QPolygonF
&
surveyPolygon
)
{
using
namespace
PlanimetryCalculus
;
QVector
<
double
>
distances
;
for
(
const
QPointF
&
p
:
surveyPolygon
)
distances
.
append
(
norm
(
p
));
// fetch input data
double
dalpha
=
_deltaAlpha
.
rawValue
().
toDouble
()
/
180.0
*
M_PI
;
// angle discretisation of circles
double
dr
=
_deltaR
.
rawValue
().
toDouble
();
// distance between circles
double
lmin
=
_transectMinLength
.
rawValue
().
toDouble
();
// minimal transect length
double
r_min
=
dr
;
// minimal circle radius
double
r_max
=
(
*
std
::
max_element
(
distances
.
begin
(),
distances
.
end
()));
// maximal circle radius
unsigned
int
maxWaypoints
=
_maxWaypoints
.
rawValue
().
toUInt
();
QPointF
origin
(
0
,
0
);
IntersectType
type
;
bool
originInside
=
true
;
if
(
!
contains
(
surveyPolygon
,
origin
,
type
))
{
QVector
<
double
>
angles
;
for
(
const
QPointF
&
p
:
surveyPolygon
)
angles
.
append
(
truncateAngle
(
angle
(
p
)));
// determine r_min by successive approximation
double
r
=
r_min
;
while
(
r
<
r_max
)
{
Circle
circle
(
r
,
origin
);
if
(
intersects
(
circle
,
surveyPolygon
))
{
r_min
=
r
;
break
;
}
r
+=
dr
;
}
originInside
=
false
;
}
double
r
=
r_min
;
unsigned
int
waypointCounter
=
0
;
while
(
r
<
r_max
)
{
Circle
circle
(
r
,
origin
);
QVector
<
QPointFVector
>
intersectPoints
;
QVector
<
IntersectType
>
typeList
;
QVector
<
QPair
<
int
,
int
>>
neighbourList
;
if
(
intersects
(
circle
,
surveyPolygon
,
intersectPoints
,
neighbourList
,
typeList
))
{
// intersection Points between circle and polygon, entering polygon
// when walking in counterclockwise direction along circle
QVector
<
QPointF
>
entryPoints
;
// intersection Points between circle and polygon, leaving polygon
// when walking in counterclockwise direction along circle
QVector
<
QPointF
>
exitPoints
;
// determine entryPoints and exit Points
for
(
int
j
=
0
;
j
<
intersectPoints
.
size
();
j
++
)
{
QVector
<
QPointF
>
intersects
=
intersectPoints
[
j
];
// one pt = tangent, two pt = sekant
QPointF
p1
=
surveyPolygon
[
neighbourList
[
j
].
first
];
QPointF
p2
=
surveyPolygon
[
neighbourList
[
j
].
second
];
QLineF
intersetLine
(
p1
,
p2
);
double
lineAngle
=
angle
(
intersetLine
);
for
(
QPointF
ipt
:
intersects
)
{
double
circleTangentAngle
=
angle
(
ipt
)
+
M_PI_2
;
if
(
!
qFuzzyIsNull
(
truncateAngle
(
lineAngle
-
circleTangentAngle
))
&&
!
qFuzzyIsNull
(
truncateAngle
(
lineAngle
-
circleTangentAngle
-
M_PI
)
))
{
if
(
truncateAngle
(
circleTangentAngle
-
lineAngle
)
>
M_PI
)
{
entryPoints
.
append
(
ipt
);
}
else
{
exitPoints
.
append
(
ipt
);
}
}
}
}
// sort
std
::
sort
(
entryPoints
.
begin
(),
entryPoints
.
end
(),
[](
QPointF
p1
,
QPointF
p2
)
{
return
angle
(
p1
)
<
angle
(
p2
);
});
std
::
sort
(
exitPoints
.
begin
(),
exitPoints
.
end
(),
[](
QPointF
p1
,
QPointF
p2
)
{
return
angle
(
p1
)
<
angle
(
p2
);
});
// match entry and exit points
int
offset
=
0
;
double
minAngle
=
std
::
numeric_limits
<
double
>::
infinity
();
for
(
int
k
=
0
;
k
<
exitPoints
.
size
();
k
++
)
{
QPointF
pt
=
exitPoints
[
k
];
double
alpha
=
truncateAngle
(
angle
(
pt
)
-
angle
(
entryPoints
[
0
]));
if
(
minAngle
>
alpha
)
{
minAngle
=
alpha
;
offset
=
k
;
}
}
// generate circle sectors
for
(
int
k
=
0
;
k
<
entryPoints
.
size
();
k
++
)
{
double
alpha1
=
angle
(
entryPoints
[
k
]);
double
alpha2
=
angle
(
exitPoints
[(
k
+
offset
)
%
entryPoints
.
size
()]);
double
dAlpha
=
truncateAngle
(
alpha2
-
alpha1
);
int
numNodes
=
int
(
ceil
(
dAlpha
/
dalpha
))
+
1
;
QVector
<
QPointF
>
sectorPath
=
circle
.
approximateSektor
(
numNodes
,
alpha1
,
alpha2
);
// use shortestPath() here if necessary, could be a problem if dr >>
if
(
sectorPath
.
size
()
>
0
)
{
waypointCounter
+=
uint
(
sectorPath
.
size
());
if
(
waypointCounter
>
maxWaypoints
)
return
false
;
transectPath
.
append
(
sectorPath
);
}
}
}
else
if
(
originInside
)
{
// circle fully inside polygon
int
numNodes
=
int
(
ceil
(
2
*
M_PI
/
dalpha
))
+
1
;
QVector
<
QPointF
>
sectorPath
=
circle
.
approximateSektor
(
numNodes
,
0
,
2
*
M_PI
);
// use shortestPath() here if necessary, could be a problem if dr >>
waypointCounter
+=
uint
(
sectorPath
.
size
());
if
(
waypointCounter
>
maxWaypoints
)
return
false
;
transectPath
.
append
(
sectorPath
);
}
r
+=
dr
;
}
if
(
transectPath
.
size
()
==
0
)
return
false
;;
// remove short transects
for
(
int
i
=
0
;
i
<
transectPath
.
size
();
i
++
)
{
auto
transect
=
transectPath
[
i
];
double
len
=
0
;
for
(
int
j
=
0
;
j
<
transect
.
size
()
-
1
;
++
j
)
{
len
+=
PlanimetryCalculus
::
distance
(
transect
[
j
],
transect
[
j
+
1
]);
}
if
(
len
<
lmin
)
transectPath
.
removeAt
(
i
--
);
}
if
(
transectPath
.
size
()
==
0
)
return
false
;
return
true
;
}
bool
CircularSurveyComplexItem
::
_rebuildTransectsInputCheck
(
QPolygonF
&
poly
)
{
// rebuild not necessary?
if
(
!
_isInitialized
)
return
false
;
// check if input is valid
if
(
_surveyAreaPolygon
.
count
()
<
3
)
return
false
;
// some more checks
if
(
!
PolygonCalculus
::
isSimplePolygon
(
poly
))
return
false
;
// even more checks
if
(
!
PolygonCalculus
::
hasClockwiseWinding
(
poly
))
PolygonCalculus
::
reversePath
(
poly
);
// check if input is valid
if
(
_deltaAlpha
.
rawValue
()
>
_deltaAlpha
.
rawMax
()
&&
_deltaAlpha
.
rawValue
()
<
_deltaAlpha
.
rawMin
())
return
false
;
if
(
_deltaR
.
rawValue
()
>
_deltaR
.
rawMax
()
&&
_deltaR
.
rawValue
()
<
_deltaR
.
rawMin
())
return
false
;
return
true
;
}
void
CircularSurveyComplexItem
::
_rebuildTransectsToGeo
(
const
QVector
<
QPointF
>
&
path
,
const
QGeoCoordinate
&
reference
)
{
using
namespace
GeoUtilities
;
QVector
<
QGeoCoordinate
>
geoPath
;
toGeoList
(
path
,
reference
,
geoPath
);
QList
<
CoordInfo_t
>
transectList
;
transectList
.
reserve
(
path
.
size
());
for
(
const
QGeoCoordinate
&
coordinate
:
geoPath
)
{
CoordInfo_t
coordinfo
=
{
coordinate
,
CoordTypeInterior
};
transectList
.
append
(
coordinfo
);
}
_transects
.
append
(
transectList
);
}
Fact
*
CircularSurveyComplexItem
::
transectMinLength
()
{
return
&
_transectMinLength
;
}
Fact
*
CircularSurveyComplexItem
::
fixedDirection
()
{
return
&
_fixedDirection
;
}
Fact
*
CircularSurveyComplexItem
::
reverse
()
{
return
&
_reverse
;
}
Fact
*
CircularSurveyComplexItem
::
maxWaypoints
()
{
return
&
_maxWaypoints
;
}
/*!
\class CircularSurveyComplexItem
\inmodule Wima
\brief The \c CircularSurveyComplexItem class provides a survey mission item with circular transects around a point of interest.
CircularSurveyComplexItem class provides a survey mission item with circular transects around a point of interest. Within the
\c Wima module it's used to scan a defined area with constant angle (circular transects) to the base station (point of interest).
\sa WimaArea
*/
src/Wima/CircularSurvey.cc
View file @
47641f63
...
@@ -25,15 +25,26 @@ private:
...
@@ -25,15 +25,26 @@ private:
Functor
fun
;
Functor
fun
;
};
};
template
<
typename
T
>
constexpr
typename
std
::
underlying_type
<
T
>::
type
integral
(
T
value
)
{
return
static_cast
<
typename
std
::
underlying_type
<
T
>::
type
>
(
value
);
}
bool
circularTransects
(
const
QGeoCoordinate
&
ref
,
const
QGeoCoordinate
&
depot
,
bool
circularTransects
(
const
QGeoCoordinate
&
ref
,
const
QGeoCoordinate
&
depot
,
const
QList
<
QGeoCoordinate
>
&
polygon
,
bool
useDepot
,
const
QList
<
QGeoCoordinate
>
&
polygon
,
snake
::
Length
deltaR
,
snake
::
Angle
deltaAlpha
,
snake
::
Length
deltaR
,
snake
::
Angle
deltaAlpha
,
snake
::
Length
minLength
,
snake
::
Transects
&
transects
);
snake
::
Length
minLength
,
snake
::
Transects
&
transects
);
bool
linearTransects
(
const
QGeoCoordinate
&
origin
,
const
QGeoCoordinate
&
depot
,
bool
useDepot
,
const
QList
<
QGeoCoordinate
>
&
polygon
,
snake
::
Length
distance
,
snake
::
Angle
angle
,
snake
::
Length
minLength
,
snake
::
Transects
&
transects
);
const
char
*
CircularSurvey
::
settingsGroup
=
"CircularSurvey"
;
const
char
*
CircularSurvey
::
settingsGroup
=
"CircularSurvey"
;
const
char
*
CircularSurvey
::
deltaRName
=
"DeltaR"
;
const
char
*
CircularSurvey
::
transectDistanceName
=
"TransectDistance"
;
const
char
*
CircularSurvey
::
deltaAlphaName
=
"DeltaAlpha"
;
const
char
*
CircularSurvey
::
alphaName
=
"Alpha"
;
const
char
*
CircularSurvey
::
transectMinLengthName
=
"TransectMinLength"
;
const
char
*
CircularSurvey
::
minLengthName
=
"MinLength"
;
const
char
*
CircularSurvey
::
typeName
=
"Type"
;
const
char
*
CircularSurvey
::
CircularSurveyName
=
"CircularSurvey"
;
const
char
*
CircularSurvey
::
CircularSurveyName
=
"CircularSurvey"
;
const
char
*
CircularSurvey
::
refPointLatitudeName
=
"ReferencePointLat"
;
const
char
*
CircularSurvey
::
refPointLatitudeName
=
"ReferencePointLat"
;
const
char
*
CircularSurvey
::
refPointLongitudeName
=
"ReferencePointLong"
;
const
char
*
CircularSurvey
::
refPointLongitudeName
=
"ReferencePointLong"
;
...
@@ -45,18 +56,19 @@ CircularSurvey::CircularSurvey(Vehicle *vehicle, bool flyView,
...
@@ -45,18 +56,19 @@ CircularSurvey::CircularSurvey(Vehicle *vehicle, bool flyView,
_referencePoint
(
QGeoCoordinate
(
0
,
0
,
0
)),
_referencePoint
(
QGeoCoordinate
(
0
,
0
,
0
)),
_metaDataMap
(
FactMetaData
::
createMapFromJsonFile
(
_metaDataMap
(
FactMetaData
::
createMapFromJsonFile
(
QStringLiteral
(
":/json/CircularSurvey.SettingsGroup.json"
),
this
)),
QStringLiteral
(
":/json/CircularSurvey.SettingsGroup.json"
),
this
)),
_deltaR
(
settingsGroup
,
_metaDataMap
[
deltaRName
]),
_transectDistance
(
settingsGroup
,
_metaDataMap
[
transectDistanceName
]),
_deltaAlpha
(
settingsGroup
,
_metaDataMap
[
deltaAlphaName
]),
_alpha
(
settingsGroup
,
_metaDataMap
[
alphaName
]),
_minLength
(
settingsGroup
,
_metaDataMap
[
transectMinLengthName
]),
_minLength
(
settingsGroup
,
_metaDataMap
[
minLengthName
]),
_type
(
settingsGroup
,
_metaDataMap
[
typeName
]),
_pWorker
(
std
::
make_unique
<
RoutingWorker
>
()),
_needsStoring
(
false
),
_pWorker
(
std
::
make_unique
<
RoutingWorker
>
()),
_needsStoring
(
false
),
_needsReversal
(
false
),
_hidePolygon
(
false
)
{
_needsReversal
(
false
),
_hidePolygon
(
false
)
{
Q_UNUSED
(
kmlOrShpFile
)
Q_UNUSED
(
kmlOrShpFile
)
_editorQml
=
"qrc:/qml/CircularSurveyItemEditor.qml"
;
_editorQml
=
"qrc:/qml/CircularSurveyItemEditor.qml"
;
// Connect facts.
// Connect facts.
connect
(
&
_
deltaR
,
&
Fact
::
valueChanged
,
this
,
connect
(
&
_
transectDistance
,
&
Fact
::
valueChanged
,
this
,
&
CircularSurvey
::
_rebuildTransects
);
&
CircularSurvey
::
_rebuildTransects
);
connect
(
&
_
deltaA
lpha
,
&
Fact
::
valueChanged
,
this
,
connect
(
&
_
a
lpha
,
&
Fact
::
valueChanged
,
this
,
&
CircularSurvey
::
_rebuildTransects
);
&
CircularSurvey
::
_rebuildTransects
);
connect
(
&
_minLength
,
&
Fact
::
valueChanged
,
this
,
connect
(
&
_minLength
,
&
Fact
::
valueChanged
,
this
,
&
CircularSurvey
::
_rebuildTransects
);
&
CircularSurvey
::
_rebuildTransects
);
...
@@ -66,6 +78,8 @@ CircularSurvey::CircularSurvey(Vehicle *vehicle, bool flyView,
...
@@ -66,6 +78,8 @@ CircularSurvey::CircularSurvey(Vehicle *vehicle, bool flyView,
&
CircularSurvey
::
_rebuildTransects
);
&
CircularSurvey
::
_rebuildTransects
);
connect
(
this
,
&
CircularSurvey
::
safeAreaChanged
,
this
,
connect
(
this
,
&
CircularSurvey
::
safeAreaChanged
,
this
,
&
CircularSurvey
::
_rebuildTransects
);
&
CircularSurvey
::
_rebuildTransects
);
connect
(
&
this
->
_type
,
&
Fact
::
rawValueChanged
,
this
,
&
CircularSurvey
::
_rebuildTransects
);
// Connect worker.
// Connect worker.
connect
(
this
->
_pWorker
.
get
(),
&
RoutingWorker
::
result
,
this
,
connect
(
this
->
_pWorker
.
get
(),
&
RoutingWorker
::
result
,
this
,
&
CircularSurvey
::
_setTransects
);
&
CircularSurvey
::
_setTransects
);
...
@@ -88,6 +102,7 @@ void CircularSurvey::reverse() {
...
@@ -88,6 +102,7 @@ void CircularSurvey::reverse() {
void
CircularSurvey
::
setRefPoint
(
const
QGeoCoordinate
&
refPt
)
{
void
CircularSurvey
::
setRefPoint
(
const
QGeoCoordinate
&
refPt
)
{
if
(
refPt
!=
_referencePoint
)
{
if
(
refPt
!=
_referencePoint
)
{
_referencePoint
=
refPt
;
_referencePoint
=
refPt
;
_referencePoint
.
setAltitude
(
0
);
emit
refPointChanged
();
emit
refPointChanged
();
}
}
...
@@ -95,9 +110,9 @@ void CircularSurvey::setRefPoint(const QGeoCoordinate &refPt) {
...
@@ -95,9 +110,9 @@ void CircularSurvey::setRefPoint(const QGeoCoordinate &refPt) {
QGeoCoordinate
CircularSurvey
::
refPoint
()
const
{
return
_referencePoint
;
}
QGeoCoordinate
CircularSurvey
::
refPoint
()
const
{
return
_referencePoint
;
}
Fact
*
CircularSurvey
::
deltaR
()
{
return
&
_deltaR
;
}
Fact
*
CircularSurvey
::
transectDistance
()
{
return
&
_transectDistance
;
}
Fact
*
CircularSurvey
::
deltaAlpha
()
{
return
&
_deltaA
lpha
;
}
Fact
*
CircularSurvey
::
alpha
()
{
return
&
_a
lpha
;
}
bool
CircularSurvey
::
hidePolygon
()
const
{
return
_hidePolygon
;
}
bool
CircularSurvey
::
hidePolygon
()
const
{
return
_hidePolygon
;
}
...
@@ -107,6 +122,10 @@ QList<QGeoCoordinate> CircularSurvey::safeArea() const {
...
@@ -107,6 +122,10 @@ QList<QGeoCoordinate> CircularSurvey::safeArea() const {
return
this
->
_safeArea
;
return
this
->
_safeArea
;
}
}
const
QList
<
QList
<
QGeoCoordinate
>>
&
CircularSurvey
::
rawTransects
()
const
{
return
this
->
_rawTransects
;
}
void
CircularSurvey
::
setHidePolygon
(
bool
hide
)
{
void
CircularSurvey
::
setHidePolygon
(
bool
hide
)
{
if
(
this
->
_hidePolygon
!=
hide
)
{
if
(
this
->
_hidePolygon
!=
hide
)
{
this
->
_hidePolygon
=
hide
;
this
->
_hidePolygon
=
hide
;
...
@@ -117,6 +136,7 @@ void CircularSurvey::setHidePolygon(bool hide) {
...
@@ -117,6 +136,7 @@ void CircularSurvey::setHidePolygon(bool hide) {
void
CircularSurvey
::
setDepot
(
const
QGeoCoordinate
&
depot
)
{
void
CircularSurvey
::
setDepot
(
const
QGeoCoordinate
&
depot
)
{
if
(
this
->
_depot
!=
depot
)
{
if
(
this
->
_depot
!=
depot
)
{
this
->
_depot
=
depot
;
this
->
_depot
=
depot
;
this
->
_depot
.
setAltitude
(
0
);
emit
depotChanged
();
emit
depotChanged
();
}
}
}
}
...
@@ -149,9 +169,10 @@ bool CircularSurvey::load(const QJsonObject &complexObject, int sequenceNumber,
...
@@ -149,9 +169,10 @@ bool CircularSurvey::load(const QJsonObject &complexObject, int sequenceNumber,
QList
<
JsonHelper
::
KeyValidateInfo
>
keyInfoList
=
{
QList
<
JsonHelper
::
KeyValidateInfo
>
keyInfoList
=
{
{
VisualMissionItem
::
jsonTypeKey
,
QJsonValue
::
String
,
true
},
{
VisualMissionItem
::
jsonTypeKey
,
QJsonValue
::
String
,
true
},
{
ComplexMissionItem
::
jsonComplexItemTypeKey
,
QJsonValue
::
String
,
true
},
{
ComplexMissionItem
::
jsonComplexItemTypeKey
,
QJsonValue
::
String
,
true
},
{
deltaRName
,
QJsonValue
::
Double
,
true
},
{
transectDistanceName
,
QJsonValue
::
Double
,
true
},
{
deltaAlphaName
,
QJsonValue
::
Double
,
true
},
{
alphaName
,
QJsonValue
::
Double
,
true
},
{
transectMinLengthName
,
QJsonValue
::
Double
,
true
},
{
minLengthName
,
QJsonValue
::
Double
,
true
},
{
typeName
,
QJsonValue
::
Double
,
true
},
{
refPointLatitudeName
,
QJsonValue
::
Double
,
true
},
{
refPointLatitudeName
,
QJsonValue
::
Double
,
true
},
{
refPointLongitudeName
,
QJsonValue
::
Double
,
true
},
{
refPointLongitudeName
,
QJsonValue
::
Double
,
true
},
{
refPointAltitudeName
,
QJsonValue
::
Double
,
true
},
{
refPointAltitudeName
,
QJsonValue
::
Double
,
true
},
...
@@ -189,9 +210,10 @@ bool CircularSurvey::load(const QJsonObject &complexObject, int sequenceNumber,
...
@@ -189,9 +210,10 @@ bool CircularSurvey::load(const QJsonObject &complexObject, int sequenceNumber,
return
false
;
return
false
;
}
}
_deltaR
.
setRawValue
(
complexObject
[
deltaRName
].
toDouble
());
_transectDistance
.
setRawValue
(
complexObject
[
transectDistanceName
].
toDouble
());
_deltaAlpha
.
setRawValue
(
complexObject
[
deltaAlphaName
].
toDouble
());
_alpha
.
setRawValue
(
complexObject
[
alphaName
].
toDouble
());
_minLength
.
setRawValue
(
complexObject
[
transectMinLengthName
].
toDouble
());
_minLength
.
setRawValue
(
complexObject
[
minLengthName
].
toDouble
());
_type
.
setRawValue
(
complexObject
[
typeName
].
toInt
());
_referencePoint
.
setLongitude
(
complexObject
[
refPointLongitudeName
].
toDouble
());
_referencePoint
.
setLongitude
(
complexObject
[
refPointLongitudeName
].
toDouble
());
_referencePoint
.
setLatitude
(
complexObject
[
refPointLatitudeName
].
toDouble
());
_referencePoint
.
setLatitude
(
complexObject
[
refPointLatitudeName
].
toDouble
());
_referencePoint
.
setAltitude
(
complexObject
[
refPointAltitudeName
].
toDouble
());
_referencePoint
.
setAltitude
(
complexObject
[
refPointAltitudeName
].
toDouble
());
...
@@ -221,9 +243,10 @@ void CircularSurvey::save(QJsonArray &planItems) {
...
@@ -221,9 +243,10 @@ void CircularSurvey::save(QJsonArray &planItems) {
VisualMissionItem
::
jsonTypeComplexItemValue
;
VisualMissionItem
::
jsonTypeComplexItemValue
;
saveObject
[
ComplexMissionItem
::
jsonComplexItemTypeKey
]
=
CircularSurveyName
;
saveObject
[
ComplexMissionItem
::
jsonComplexItemTypeKey
]
=
CircularSurveyName
;
saveObject
[
deltaRName
]
=
_deltaR
.
rawValue
().
toDouble
();
saveObject
[
transectDistanceName
]
=
_transectDistance
.
rawValue
().
toDouble
();
saveObject
[
deltaAlphaName
]
=
_deltaAlpha
.
rawValue
().
toDouble
();
saveObject
[
alphaName
]
=
_alpha
.
rawValue
().
toDouble
();
saveObject
[
transectMinLengthName
]
=
_minLength
.
rawValue
().
toDouble
();
saveObject
[
minLengthName
]
=
_minLength
.
rawValue
().
toDouble
();
saveObject
[
typeName
]
=
double
(
_type
.
rawValue
().
toUInt
());
saveObject
[
refPointLongitudeName
]
=
_referencePoint
.
longitude
();
saveObject
[
refPointLongitudeName
]
=
_referencePoint
.
longitude
();
saveObject
[
refPointLatitudeName
]
=
_referencePoint
.
latitude
();
saveObject
[
refPointLatitudeName
]
=
_referencePoint
.
latitude
();
saveObject
[
refPointAltitudeName
]
=
_referencePoint
.
altitude
();
saveObject
[
refPointAltitudeName
]
=
_referencePoint
.
altitude
();
...
@@ -334,7 +357,6 @@ void CircularSurvey::_rebuildTransectsPhase1(void) {
...
@@ -334,7 +357,6 @@ void CircularSurvey::_rebuildTransectsPhase1(void) {
_loadedMissionItemsParent
=
nullptr
;
_loadedMissionItemsParent
=
nullptr
;
}
}
// Store raw transects.
// Store raw transects.
this
->
_rawTransects
.
clear
();
const
auto
&
transectsENU
=
this
->
_workerOutput
->
transects
;
const
auto
&
transectsENU
=
this
->
_workerOutput
->
transects
;
const
auto
&
ori
=
this
->
_referencePoint
;
const
auto
&
ori
=
this
->
_referencePoint
;
for
(
auto
&
t
:
transectsENU
)
{
for
(
auto
&
t
:
transectsENU
)
{
...
@@ -379,7 +401,7 @@ void CircularSurvey::_rebuildTransectsPhase1(void) {
...
@@ -379,7 +401,7 @@ void CircularSurvey::_rebuildTransectsPhase1(void) {
// Convert to geo coordinates.
// Convert to geo coordinates.
QList
<
CoordInfo_t
>
list
;
QList
<
CoordInfo_t
>
list
;
for
(
std
::
size_t
i
=
idxFirst
;
i
<=
idxLast
;
++
i
)
{
for
(
std
::
size_t
i
=
idxFirst
;
i
<=
idxLast
;
++
i
)
{
auto
vertex
=
route
[
i
];
auto
&
vertex
=
route
[
i
];
QGeoCoordinate
c
;
QGeoCoordinate
c
;
snake
::
fromENU
(
ori
,
vertex
,
c
);
snake
::
fromENU
(
ori
,
vertex
,
c
);
list
.
append
(
CoordInfo_t
{
c
,
CoordTypeInterior
});
list
.
append
(
CoordInfo_t
{
c
,
CoordTypeInterior
});
...
@@ -416,9 +438,9 @@ void CircularSurvey::_rebuildTransectsPhase1(void) {
...
@@ -416,9 +438,9 @@ void CircularSurvey::_rebuildTransectsPhase1(void) {
auto
start
=
std
::
chrono
::
high_resolution_clock
::
now
();
auto
start
=
std
::
chrono
::
high_resolution_clock
::
now
();
#endif
#endif
this
->
_transects
.
clear
();
this
->
_transects
.
clear
();
this
->
_rawTransects
.
clear
();
// Prepare data.
// Prepare data.
auto
ref
=
this
->
_referencePoint
;
auto
ref
=
this
->
_referencePoint
;
ref
.
setAltitude
(
0
);
auto
polygon
=
this
->
_surveyAreaPolygon
.
coordinateList
();
auto
polygon
=
this
->
_surveyAreaPolygon
.
coordinateList
();
for
(
auto
&
v
:
polygon
)
{
for
(
auto
&
v
:
polygon
)
{
v
.
setAltitude
(
0
);
v
.
setAltitude
(
0
);
...
@@ -427,27 +449,52 @@ void CircularSurvey::_rebuildTransectsPhase1(void) {
...
@@ -427,27 +449,52 @@ void CircularSurvey::_rebuildTransectsPhase1(void) {
for
(
auto
&
v
:
safeArea
)
{
for
(
auto
&
v
:
safeArea
)
{
v
.
setAltitude
(
0
);
v
.
setAltitude
(
0
);
}
}
QGeoCoordinate
depot
;
auto
depot
=
this
->
_
depot
;
snake
::
BoostPolygon
safeAreaENU
;
snake
::
BoostPolygon
safeAreaENU
;
bool
useDepot
=
false
;
if
(
this
->
_depot
.
isValid
()
&&
this
->
_safeArea
.
size
()
>=
3
)
{
if
(
this
->
_depot
.
isValid
()
&&
this
->
_safeArea
.
size
()
>=
3
)
{
depot
=
this
->
_depot
;
useDepot
=
true
;
snake
::
areaToEnu
(
ref
,
safeArea
,
safeAreaENU
);
snake
::
areaToEnu
(
ref
,
safeArea
,
safeAreaENU
);
}
else
{
}
else
{
snake
::
areaToEnu
(
ref
,
polygon
,
safeAreaENU
);
snake
::
areaToEnu
(
ref
,
polygon
,
safeAreaENU
);
}
}
auto
d
eltaR
=
auto
d
istance
=
snake
::
Length
(
snake
::
Length
(
this
->
_deltaR
.
rawValue
().
toDouble
()
*
bu
::
si
::
meter
);
this
->
_transectDistance
.
rawValue
().
toDouble
()
*
bu
::
si
::
meter
);
auto
minLength
=
auto
minLength
=
snake
::
Length
(
this
->
_minLength
.
rawValue
().
toDouble
()
*
bu
::
si
::
meter
);
snake
::
Length
(
this
->
_minLength
.
rawValue
().
toDouble
()
*
bu
::
si
::
meter
);
auto
deltaAlpha
=
snake
::
Angle
(
this
->
_deltaAlpha
.
rawValue
().
toDouble
()
*
auto
alpha
=
bu
::
degree
::
degree
);
snake
::
Angle
(
this
->
_alpha
.
rawValue
().
toDouble
()
*
bu
::
degree
::
degree
);
auto
generator
=
[
ref
,
depot
,
polygon
,
deltaR
,
deltaAlpha
,
// Select survey type.
minLength
](
snake
::
Transects
&
transects
)
->
bool
{
if
(
this
->
_type
.
rawValue
().
toUInt
()
==
integral
(
Type
::
Circular
))
{
return
circularTransects
(
ref
,
depot
,
polygon
,
deltaR
,
deltaAlpha
,
if
(
alpha
>=
snake
::
Angle
(
0.3
*
bu
::
degree
::
degree
)
&&
alpha
<=
snake
::
Angle
(
45
*
bu
::
degree
::
degree
))
{
auto
generator
=
[
ref
,
depot
,
useDepot
,
polygon
,
distance
,
alpha
,
minLength
](
snake
::
Transects
&
transects
)
->
bool
{
return
circularTransects
(
ref
,
depot
,
useDepot
,
polygon
,
distance
,
alpha
,
minLength
,
transects
);
};
// Start routing worker.
this
->
_pWorker
->
route
(
safeAreaENU
,
generator
);
}
else
{
if
(
alpha
<
snake
::
Angle
(
0.3
*
bu
::
degree
::
degree
))
{
this
->
_alpha
.
setCookedValue
(
QVariant
(
0.3
));
}
else
{
this
->
_alpha
.
setCookedValue
(
QVariant
(
45
));
}
}
}
else
if
(
this
->
_type
.
rawValue
().
toUInt
()
==
integral
(
Type
::
Linear
))
{
auto
generator
=
[
ref
,
depot
,
useDepot
,
polygon
,
distance
,
alpha
,
minLength
](
snake
::
Transects
&
transects
)
->
bool
{
return
linearTransects
(
ref
,
depot
,
useDepot
,
polygon
,
distance
,
alpha
,
minLength
,
transects
);
minLength
,
transects
);
};
};
// Start routing worker.
// Start routing worker.
this
->
_pWorker
->
route
(
safeAreaENU
,
generator
);
this
->
_pWorker
->
route
(
safeAreaENU
,
generator
);
}
else
{
qWarning
()
<<
"CircularSurvey::rebuildTransectsPhase1(): invalid survey type:"
<<
this
->
_type
.
rawValue
().
toUInt
();
}
// Mark transects as dirty.
// Mark transects as dirty.
this
->
_transectsDirty
=
true
;
this
->
_transectsDirty
=
true
;
#ifdef SHOW_CIRCULAR_SURVEY_TIME
#ifdef SHOW_CIRCULAR_SURVEY_TIME
...
@@ -481,14 +528,18 @@ void CircularSurvey::_setTransects(CircularSurvey::PtrRoutingData pRoute) {
...
@@ -481,14 +528,18 @@ void CircularSurvey::_setTransects(CircularSurvey::PtrRoutingData pRoute) {
this
->
_rebuildTransects
();
this
->
_rebuildTransects
();
}
}
Fact
*
CircularSurvey
::
transectMinLength
()
{
return
&
_minLength
;
}
Fact
*
CircularSurvey
::
minLength
()
{
return
&
_minLength
;
}
Fact
*
CircularSurvey
::
type
()
{
return
&
_type
;
}
int
CircularSurvey
::
typeCount
()
const
{
return
int
(
integral
(
Type
::
Count
));
}
bool
CircularSurvey
::
calculating
()
const
{
bool
CircularSurvey
::
calculating
()
const
{
return
this
->
_pWorker
->
calculating
();
return
this
->
_pWorker
->
calculating
();
}
}
bool
circularTransects
(
const
QGeoCoordinate
&
ref
,
const
QGeoCoordinate
&
depot
,
bool
circularTransects
(
const
QGeoCoordinate
&
ref
,
const
QGeoCoordinate
&
depot
,
const
QList
<
QGeoCoordinate
>
&
polygon
,
bool
useDepot
,
const
QList
<
QGeoCoordinate
>
&
polygon
,
snake
::
Length
deltaR
,
snake
::
Angle
deltaAlpha
,
snake
::
Length
deltaR
,
snake
::
Angle
deltaAlpha
,
snake
::
Length
minLength
,
snake
::
Transects
&
transects
)
{
snake
::
Length
minLength
,
snake
::
Transects
&
transects
)
{
#ifdef SHOW_CIRCULAR_SURVEY_TIME
#ifdef SHOW_CIRCULAR_SURVEY_TIME
...
@@ -503,9 +554,7 @@ bool circularTransects(const QGeoCoordinate &ref, const QGeoCoordinate &depot,
...
@@ -503,9 +554,7 @@ bool circularTransects(const QGeoCoordinate &ref, const QGeoCoordinate &depot,
snake
::
BoostPoint
depotENU
{
0
,
0
};
snake
::
BoostPoint
depotENU
{
0
,
0
};
snake
::
areaToEnu
(
ref
,
polygon
,
polygonENU
);
snake
::
areaToEnu
(
ref
,
polygon
,
polygonENU
);
snake
::
toENU
(
ref
,
ref
,
originENU
);
snake
::
toENU
(
ref
,
ref
,
originENU
);
bool
depotValid
=
depot
.
isValid
();
snake
::
toENU
(
ref
,
depot
,
depotENU
);
if
(
depotValid
)
snake
::
toENU
(
ref
,
depot
,
depotENU
);
std
::
string
error
;
std
::
string
error
;
// Check validity.
// Check validity.
if
(
!
bg
::
is_valid
(
polygonENU
,
error
))
{
if
(
!
bg
::
is_valid
(
polygonENU
,
error
))
{
...
@@ -588,7 +637,7 @@ bool circularTransects(const QGeoCoordinate &ref, const QGeoCoordinate &depot,
...
@@ -588,7 +637,7 @@ bool circularTransects(const QGeoCoordinate &ref, const QGeoCoordinate &depot,
snake
::
BoostPolygon
shrinked
;
snake
::
BoostPolygon
shrinked
;
snake
::
offsetPolygon
(
polygonENU
,
shrinked
,
-
0.3
);
snake
::
offsetPolygon
(
polygonENU
,
shrinked
,
-
0.3
);
auto
&
outer
=
shrinked
.
outer
();
auto
&
outer
=
shrinked
.
outer
();
polygonClipper
.
reserve
(
outer
.
size
()
-
1
);
polygonClipper
.
reserve
(
outer
.
size
());
for
(
auto
it
=
outer
.
begin
();
it
<
outer
.
end
()
-
1
;
++
it
)
{
for
(
auto
it
=
outer
.
begin
();
it
<
outer
.
end
()
-
1
;
++
it
)
{
auto
x
=
ClipperLib
::
cInt
(
std
::
round
(
it
->
get
<
0
>
()
*
CLIPPER_SCALE
));
auto
x
=
ClipperLib
::
cInt
(
std
::
round
(
it
->
get
<
0
>
()
*
CLIPPER_SCALE
));
auto
y
=
ClipperLib
::
cInt
(
std
::
round
(
it
->
get
<
1
>
()
*
CLIPPER_SCALE
));
auto
y
=
ClipperLib
::
cInt
(
std
::
round
(
it
->
get
<
1
>
()
*
CLIPPER_SCALE
));
...
@@ -603,7 +652,7 @@ bool circularTransects(const QGeoCoordinate &ref, const QGeoCoordinate &depot,
...
@@ -603,7 +652,7 @@ bool circularTransects(const QGeoCoordinate &ref, const QGeoCoordinate &depot,
// Extract transects from PolyTree and convert them to
// Extract transects from PolyTree and convert them to
// BoostLineString
// BoostLineString
if
(
depotValid
)
{
if
(
useDepot
)
{
transects
.
push_back
(
snake
::
BoostLineString
{
depotENU
});
transects
.
push_back
(
snake
::
BoostLineString
{
depotENU
});
}
}
for
(
const
auto
&
child
:
transectsClipper
.
Childs
)
{
for
(
const
auto
&
child
:
transectsClipper
.
Childs
)
{
...
@@ -663,7 +712,7 @@ bool circularTransects(const QGeoCoordinate &ref, const QGeoCoordinate &depot,
...
@@ -663,7 +712,7 @@ bool circularTransects(const QGeoCoordinate &ref, const QGeoCoordinate &depot,
}
}
}
}
// Remove short transects
// Remove short transects
auto
begin
=
depotValid
?
transects
.
begin
()
+
1
:
transects
.
begin
();
auto
begin
=
useDepot
?
transects
.
begin
()
+
1
:
transects
.
begin
();
for
(
auto
it
=
begin
;
it
<
transects
.
end
();)
{
for
(
auto
it
=
begin
;
it
<
transects
.
end
();)
{
if
(
bg
::
length
(
*
it
)
<
minLength
.
value
())
{
if
(
bg
::
length
(
*
it
)
<
minLength
.
value
())
{
it
=
transects
.
erase
(
it
);
it
=
transects
.
erase
(
it
);
...
@@ -672,7 +721,7 @@ bool circularTransects(const QGeoCoordinate &ref, const QGeoCoordinate &depot,
...
@@ -672,7 +721,7 @@ bool circularTransects(const QGeoCoordinate &ref, const QGeoCoordinate &depot,
}
}
}
}
if
(
!
depotValid
)
{
if
(
!
useDepot
)
{
// Move transect with min. distance to the front.
// Move transect with min. distance to the front.
auto
minDist
=
std
::
numeric_limits
<
double
>::
max
();
auto
minDist
=
std
::
numeric_limits
<
double
>::
max
();
auto
minIt
=
transects
.
begin
();
auto
minIt
=
transects
.
begin
();
...
@@ -718,6 +767,141 @@ bool circularTransects(const QGeoCoordinate &ref, const QGeoCoordinate &depot,
...
@@ -718,6 +767,141 @@ bool circularTransects(const QGeoCoordinate &ref, const QGeoCoordinate &depot,
}
}
return
false
;
return
false
;
}
}
bool
linearTransects
(
const
QGeoCoordinate
&
origin
,
const
QGeoCoordinate
&
depot
,
bool
useDepot
,
const
QList
<
QGeoCoordinate
>
&
polygon
,
snake
::
Length
distance
,
snake
::
Angle
angle
,
snake
::
Length
minLength
,
snake
::
Transects
&
transects
)
{
namespace
tr
=
bg
::
strategy
::
transform
;
#ifdef SHOW_CIRCULAR_SURVEY_TIME
auto
s1
=
std
::
chrono
::
high_resolution_clock
::
now
();
#endif
// Check preconitions
if
(
polygon
.
size
()
>=
3
)
{
// Convert to ENU system.
snake
::
BoostPolygon
polygonENU
;
snake
::
areaToEnu
(
origin
,
polygon
,
polygonENU
);
std
::
string
error
;
// Check validity.
if
(
!
bg
::
is_valid
(
polygonENU
,
error
))
{
#ifdef DEBUG_CIRCULAR_SURVEY
qWarning
()
<<
"CS::circularTransects(): "
"invalid polygon."
;
qWarning
()
<<
error
.
c_str
();
std
::
stringstream
ss
;
ss
<<
bg
::
wkt
(
polygonENU
);
qWarning
()
<<
ss
.
str
().
c_str
();
#endif
}
else
{
snake
::
BoostPoint
depotENU
;
snake
::
toENU
(
origin
,
depot
,
depotENU
);
tr
::
rotate_transformer
<
bg
::
degree
,
double
,
2
,
2
>
rotate
(
angle
.
value
()
*
180
/
M_PI
);
// Rotate polygon by angle and calculate bounding box.
snake
::
BoostPolygon
polygonENURotated
;
bg
::
transform
(
polygonENU
,
polygonENURotated
,
rotate
);
snake
::
BoostBox
box
;
boost
::
geometry
::
envelope
(
polygonENURotated
,
box
);
double
x0
=
box
.
min_corner
().
get
<
0
>
();
double
y0
=
box
.
min_corner
().
get
<
1
>
();
double
x1
=
box
.
max_corner
().
get
<
0
>
();
double
y1
=
box
.
max_corner
().
get
<
1
>
();
// Generate transects and convert them to clipper path.
size_t
num_t
=
ceil
((
y1
-
y0
)
/
distance
.
value
());
// number of transects
vector
<
ClipperLib
::
Path
>
transectsClipper
;
transectsClipper
.
reserve
(
num_t
);
for
(
size_t
i
=
0
;
i
<
num_t
;
++
i
)
{
// calculate transect
snake
::
BoostPoint
v1
{
x0
,
y0
+
i
*
distance
.
value
()};
snake
::
BoostPoint
v2
{
x1
,
y0
+
i
*
distance
.
value
()};
snake
::
BoostLineString
transect
;
transect
.
push_back
(
v1
);
transect
.
push_back
(
v2
);
// transform back
snake
::
BoostLineString
temp_transect
;
tr
::
rotate_transformer
<
bg
::
degree
,
double
,
2
,
2
>
rotate_back
(
-
angle
.
value
()
*
180
/
M_PI
);
bg
::
transform
(
transect
,
temp_transect
,
rotate_back
);
// to clipper
ClipperLib
::
IntPoint
c1
{
static_cast
<
ClipperLib
::
cInt
>
(
temp_transect
[
0
].
get
<
0
>
()
*
CLIPPER_SCALE
),
static_cast
<
ClipperLib
::
cInt
>
(
temp_transect
[
0
].
get
<
1
>
()
*
CLIPPER_SCALE
)};
ClipperLib
::
IntPoint
c2
{
static_cast
<
ClipperLib
::
cInt
>
(
temp_transect
[
1
].
get
<
0
>
()
*
CLIPPER_SCALE
),
static_cast
<
ClipperLib
::
cInt
>
(
temp_transect
[
1
].
get
<
1
>
()
*
CLIPPER_SCALE
)};
ClipperLib
::
Path
path
{
c1
,
c2
};
transectsClipper
.
push_back
(
path
);
}
if
(
transectsClipper
.
size
()
==
0
)
{
std
::
stringstream
ss
;
ss
<<
"Not able to generate transects. Parameter: distance = "
<<
distance
<<
std
::
endl
;
qWarning
()
<<
"CircularSurvey::linearTransects(): "
<<
ss
.
str
().
c_str
();
return
false
;
}
// Convert measurement area to clipper path.
snake
::
BoostPolygon
shrinked
;
snake
::
offsetPolygon
(
polygonENU
,
shrinked
,
-
0.2
);
auto
&
outer
=
shrinked
.
outer
();
ClipperLib
::
Path
polygonClipper
;
for
(
auto
vertex
:
outer
)
{
polygonClipper
.
push_back
(
ClipperLib
::
IntPoint
{
static_cast
<
ClipperLib
::
cInt
>
(
vertex
.
get
<
0
>
()
*
CLIPPER_SCALE
),
static_cast
<
ClipperLib
::
cInt
>
(
vertex
.
get
<
1
>
()
*
CLIPPER_SCALE
)});
}
// Perform clipping.
// Clip transects to measurement area.
ClipperLib
::
Clipper
clipper
;
clipper
.
AddPath
(
polygonClipper
,
ClipperLib
::
ptClip
,
true
);
clipper
.
AddPaths
(
transectsClipper
,
ClipperLib
::
ptSubject
,
false
);
ClipperLib
::
PolyTree
clippedTransecs
;
clipper
.
Execute
(
ClipperLib
::
ctIntersection
,
clippedTransecs
,
ClipperLib
::
pftNonZero
,
ClipperLib
::
pftNonZero
);
// Extract transects from PolyTree and convert them to BoostLineString
if
(
useDepot
)
{
transects
.
push_back
(
snake
::
BoostLineString
{
depotENU
});
}
for
(
const
auto
&
child
:
clippedTransecs
.
Childs
)
{
const
auto
&
clipperTransect
=
child
->
Contour
;
snake
::
BoostPoint
v1
{
static_cast
<
double
>
(
clipperTransect
[
0
].
X
)
/
CLIPPER_SCALE
,
static_cast
<
double
>
(
clipperTransect
[
0
].
Y
)
/
CLIPPER_SCALE
};
snake
::
BoostPoint
v2
{
static_cast
<
double
>
(
clipperTransect
[
1
].
X
)
/
CLIPPER_SCALE
,
static_cast
<
double
>
(
clipperTransect
[
1
].
Y
)
/
CLIPPER_SCALE
};
snake
::
BoostLineString
transect
{
v1
,
v2
};
if
(
bg
::
length
(
transect
)
>=
minLength
.
value
())
{
transects
.
push_back
(
transect
);
}
}
if
(
transects
.
size
()
==
0
)
{
std
::
stringstream
ss
;
ss
<<
"Not able to generate transects. Parameter: minLength = "
<<
minLength
<<
std
::
endl
;
qWarning
()
<<
"CircularSurvey::linearTransects(): "
<<
ss
.
str
().
c_str
();
return
false
;
}
#ifdef SHOW_CIRCULAR_SURVEY_TIME
qWarning
()
<<
"CS::circularTransects(): transect gen. time: "
<<
std
::
chrono
::
duration_cast
<
std
::
chrono
::
milliseconds
>
(
std
::
chrono
::
high_resolution_clock
::
now
()
-
s1
)
.
count
()
<<
" ms"
;
#endif
return
true
;
}
}
return
false
;
}
/*!
/*!
\class CircularSurveyComplexItem
\class CircularSurveyComplexItem
\inmodule Wima
\inmodule Wima
...
...
src/Wima/CircularSurvey.h
View file @
47641f63
...
@@ -13,6 +13,11 @@ class CircularSurvey : public TransectStyleComplexItem {
...
@@ -13,6 +13,11 @@ class CircularSurvey : public TransectStyleComplexItem {
Q_OBJECT
Q_OBJECT
public:
public:
using
PtrRoutingData
=
QSharedPointer
<
RoutingData
>
;
using
PtrRoutingData
=
QSharedPointer
<
RoutingData
>
;
enum
class
Type
{
Circular
=
0
,
Linear
=
1
,
Count
=
2
// Must me last, onyl for counting
};
/// @param vehicle Vehicle which this is being contructed for
/// @param vehicle Vehicle which this is being contructed for
/// @param flyView true: Created for use in the Fly View, false: Created for
/// @param flyView true: Created for use in the Fly View, false: Created for
...
@@ -25,9 +30,11 @@ public:
...
@@ -25,9 +30,11 @@ public:
Q_PROPERTY
(
QGeoCoordinate
refPoint
READ
refPoint
WRITE
setRefPoint
NOTIFY
Q_PROPERTY
(
QGeoCoordinate
refPoint
READ
refPoint
WRITE
setRefPoint
NOTIFY
refPointChanged
)
refPointChanged
)
Q_PROPERTY
(
Fact
*
deltaR
READ
deltaR
CONSTANT
)
Q_PROPERTY
(
Fact
*
transectDistance
READ
transectDistance
CONSTANT
)
Q_PROPERTY
(
Fact
*
deltaAlpha
READ
deltaAlpha
CONSTANT
)
Q_PROPERTY
(
Fact
*
alpha
READ
alpha
CONSTANT
)
Q_PROPERTY
(
Fact
*
transectMinLength
READ
transectMinLength
CONSTANT
)
Q_PROPERTY
(
Fact
*
minLength
READ
minLength
CONSTANT
)
Q_PROPERTY
(
Fact
*
type
READ
type
CONSTANT
)
Q_PROPERTY
(
int
typeCount
READ
typeCount
CONSTANT
)
Q_PROPERTY
(
bool
calculating
READ
calculating
NOTIFY
calculatingChanged
)
Q_PROPERTY
(
bool
calculating
READ
calculating
NOTIFY
calculatingChanged
)
Q_PROPERTY
(
bool
hidePolygon
READ
hidePolygon
NOTIFY
hidePolygonChanged
)
Q_PROPERTY
(
bool
hidePolygon
READ
hidePolygon
NOTIFY
hidePolygonChanged
)
...
@@ -42,13 +49,16 @@ public:
...
@@ -42,13 +49,16 @@ public:
// Property getters
// Property getters
QGeoCoordinate
refPoint
()
const
;
QGeoCoordinate
refPoint
()
const
;
Fact
*
deltaR
();
Fact
*
transectDistance
();
Fact
*
deltaAlpha
();
Fact
*
alpha
();
Fact
*
transectMinLength
();
Fact
*
minLength
();
Fact
*
type
();
int
typeCount
()
const
;
bool
calculating
()
const
;
bool
calculating
()
const
;
bool
hidePolygon
()
const
;
bool
hidePolygon
()
const
;
QGeoCoordinate
depot
()
const
;
QGeoCoordinate
depot
()
const
;
QList
<
QGeoCoordinate
>
safeArea
()
const
;
QList
<
QGeoCoordinate
>
safeArea
()
const
;
const
QList
<
QList
<
QGeoCoordinate
>>
&
rawTransects
()
const
;
// Overrides
// Overrides
bool
load
(
const
QJsonObject
&
complexObject
,
int
sequenceNumber
,
bool
load
(
const
QJsonObject
&
complexObject
,
int
sequenceNumber
,
...
@@ -67,9 +77,10 @@ public:
...
@@ -67,9 +77,10 @@ public:
double
additionalTimeDelay
(
void
)
const
override
final
;
double
additionalTimeDelay
(
void
)
const
override
final
;
static
const
char
*
settingsGroup
;
static
const
char
*
settingsGroup
;
static
const
char
*
deltaRName
;
static
const
char
*
transectDistanceName
;
static
const
char
*
deltaAlphaName
;
static
const
char
*
alphaName
;
static
const
char
*
transectMinLengthName
;
static
const
char
*
minLengthName
;
static
const
char
*
typeName
;
static
const
char
*
CircularSurveyName
;
static
const
char
*
CircularSurveyName
;
static
const
char
*
refPointLongitudeName
;
static
const
char
*
refPointLongitudeName
;
static
const
char
*
refPointLatitudeName
;
static
const
char
*
refPointLatitudeName
;
...
@@ -97,16 +108,17 @@ private:
...
@@ -97,16 +108,17 @@ private:
// center of the circular lanes, e.g. base station
// center of the circular lanes, e.g. base station
QGeoCoordinate
_referencePoint
;
QGeoCoordinate
_referencePoint
;
QMap
<
QString
,
FactMetaData
*>
_metaDataMap
;
QMap
<
QString
,
FactMetaData
*>
_metaDataMap
;
// distance between two neighbour circles
// distance between two neighbour circles
SettingsFact
_
deltaR
;
SettingsFact
_
transectDistance
;
// angle discretisation of the circles
// angle discretisation of the circles
SettingsFact
_
deltaA
lpha
;
SettingsFact
_
a
lpha
;
// minimal transect lenght, transects are rejected if they are shorter than
// minimal transect lenght, transects are rejected if they are shorter than
// this value
// this value
SettingsFact
_minLength
;
SettingsFact
_minLength
;
SettingsFact
_type
;
// Worker
using
PtrWorker
=
std
::
shared_ptr
<
RoutingWorker
>
;
using
PtrWorker
=
std
::
shared_ptr
<
RoutingWorker
>
;
PtrWorker
_pWorker
;
PtrWorker
_pWorker
;
PtrRoutingData
_workerOutput
;
PtrRoutingData
_workerOutput
;
...
...
src/Wima/Geometry/WimaJoinedAreaData.cc
View file @
47641f63
...
@@ -3,21 +3,18 @@
...
@@ -3,21 +3,18 @@
const
char
*
WimaJoinedAreaData
::
typeString
=
"WimaJoinedAreaData"
;
const
char
*
WimaJoinedAreaData
::
typeString
=
"WimaJoinedAreaData"
;
WimaJoinedAreaData
::
WimaJoinedAreaData
(
QObject
*
parent
)
WimaJoinedAreaData
::
WimaJoinedAreaData
(
QObject
*
parent
)
:
WimaAreaData
(
parent
)
:
WimaAreaData
(
parent
)
{}
{
WimaJoinedAreaData
::
WimaJoinedAreaData
(
const
WimaJoinedAreaData
&
other
,
QObject
*
parent
)
:
WimaAreaData
(
parent
)
{
*
this
=
other
;
}
}
WimaJoinedAreaData
::
WimaJoinedAreaData
(
const
WimaJoinedAreaData
&
other
,
QObject
*
parent
)
WimaJoinedAreaData
::
WimaJoinedAreaData
(
const
WimaJoinedArea
&
other
,
:
WimaAreaData
(
parent
)
QObject
*
parent
)
{
:
WimaAreaData
(
parent
)
{
*
this
=
other
;
*
this
=
other
;
}
WimaJoinedAreaData
::
WimaJoinedAreaData
(
const
WimaJoinedArea
&
other
,
QObject
*
parent
)
:
WimaAreaData
(
parent
)
{
*
this
=
other
;
}
}
/*!
/*!
...
@@ -25,11 +22,11 @@ WimaJoinedAreaData::WimaJoinedAreaData(const WimaJoinedArea &other, QObject *par
...
@@ -25,11 +22,11 @@ WimaJoinedAreaData::WimaJoinedAreaData(const WimaJoinedArea &other, QObject *par
*
*
* Assigns \a other to the invoking object.
* Assigns \a other to the invoking object.
*/
*/
WimaJoinedAreaData
&
WimaJoinedAreaData
::
operator
=
(
const
WimaJoinedAreaData
&
other
)
WimaJoinedAreaData
&
WimaJoinedAreaData
::
{
operator
=
(
const
WimaJoinedAreaData
&
other
)
{
assign
(
other
);
assign
(
other
);
return
*
this
;
return
*
this
;
}
}
/*!
/*!
...
@@ -37,36 +34,29 @@ WimaJoinedAreaData &WimaJoinedAreaData::operator=(const WimaJoinedAreaData &othe
...
@@ -37,36 +34,29 @@ WimaJoinedAreaData &WimaJoinedAreaData::operator=(const WimaJoinedAreaData &othe
*
*
* Assigns \a other to the invoking object.
* Assigns \a other to the invoking object.
*/
*/
WimaJoinedAreaData
&
WimaJoinedAreaData
::
operator
=
(
const
WimaJoinedArea
&
other
)
WimaJoinedAreaData
&
WimaJoinedAreaData
::
operator
=
(
const
WimaJoinedArea
&
other
)
{
{
assign
(
other
);
assign
(
other
);
return
*
this
;
return
*
this
;
}
}
QString
WimaJoinedAreaData
::
type
()
const
QString
WimaJoinedAreaData
::
type
()
const
{
return
this
->
typeString
;
}
{
return
this
->
typeString
;
}
void
WimaJoinedAreaData
::
assign
(
const
WimaJoinedAreaData
&
other
)
void
WimaJoinedAreaData
::
assign
(
const
WimaJoinedAreaData
&
other
)
{
{
WimaAreaData
::
assign
(
other
);
WimaAreaData
::
assign
(
other
);
}
}
void
WimaJoinedAreaData
::
assign
(
const
WimaJoinedArea
&
other
)
void
WimaJoinedAreaData
::
assign
(
const
WimaJoinedArea
&
other
)
{
{
WimaAreaData
::
assign
(
other
);
WimaAreaData
::
assign
(
other
);
}
}
/*!
/*!
* \class WimaAreaData::WimaJoinedAreaData
* \class WimaAreaData::WimaJoinedAreaData
* \brief Class to store and exchange data of a \c WimaJoinedAreaData Object.
* \brief Class to store and exchange data of a \c WimaJoinedAreaData Object.
* Class to store and exchange data of a \c WimaJoinedArea Object. In contrast to \c WimaJoinedArea this class
* Class to store and exchange data of a \c WimaJoinedArea Object. In contrast
* does not provied any interface to a grafical user interface, neiter it uses the QGC Fact System.
* to \c WimaJoinedArea this class does not provied any interface to a grafical
* It is designed to exchange data between the \c WimaPlaner and the \c WimaController class. And it
* user interface, neiter it uses the QGC Fact System. It is designed to
* is the derived from WimaAreaData.
* exchange data between the \c WimaPlaner and the \c WimaController class. And
* it is the derived from WimaAreaData.
*
*
* \sa WimaJoinedArea, WimaAreaData
* \sa WimaJoinedArea, WimaAreaData
*/
*/
src/Wima/Geometry/WimaMeasurementAreaData.cc
View file @
47641f63
#include "WimaMeasurementAreaData.h"
#include "WimaMeasurementAreaData.h"
#include "SnakeTile.h"
const
char
*
WimaMeasurementAreaData
::
typeString
=
"WimaMeasurementAreaData"
;
const
char
*
WimaMeasurementAreaData
::
typeString
=
"WimaMeasurementAreaData"
;
WimaMeasurementAreaData
::
WimaMeasurementAreaData
(
QObject
*
parent
)
WimaMeasurementAreaData
::
WimaMeasurementAreaData
(
QObject
*
parent
)
:
WimaAreaData
(
parent
)
:
WimaAreaData
(
parent
)
{}
{
WimaMeasurementAreaData
::
WimaMeasurementAreaData
(
const
WimaMeasurementAreaData
&
other
,
QObject
*
parent
)
:
WimaAreaData
(
parent
)
{
*
this
=
other
;
}
}
WimaMeasurementAreaData
::
WimaMeasurementAreaData
(
const
WimaMeasurementAreaData
&
other
,
QObject
*
parent
)
WimaMeasurementAreaData
::
WimaMeasurementAreaData
(
:
WimaAreaData
(
parent
)
const
WimaMeasurementArea
&
other
,
QObject
*
parent
)
{
:
WimaAreaData
(
parent
)
{
*
this
=
other
;
*
this
=
other
;
}
WimaMeasurementAreaData
::
WimaMeasurementAreaData
(
const
WimaMeasurementArea
&
other
,
QObject
*
parent
)
:
WimaAreaData
(
parent
)
{
*
this
=
other
;
}
}
/*!
/*!
...
@@ -25,11 +23,11 @@ WimaMeasurementAreaData::WimaMeasurementAreaData(const WimaMeasurementArea &othe
...
@@ -25,11 +23,11 @@ WimaMeasurementAreaData::WimaMeasurementAreaData(const WimaMeasurementArea &othe
*
*
* Assigns \a other to the invoking object.
* Assigns \a other to the invoking object.
*/
*/
WimaMeasurementAreaData
&
WimaMeasurementAreaData
::
operator
=
(
const
WimaMeasurementAreaData
&
other
)
WimaMeasurementAreaData
&
WimaMeasurementAreaData
::
{
operator
=
(
const
WimaMeasurementAreaData
&
other
)
{
assign
(
other
);
assign
(
other
);
return
*
this
;
return
*
this
;
}
}
/*!
/*!
...
@@ -37,28 +35,44 @@ WimaMeasurementAreaData &WimaMeasurementAreaData::operator=(const WimaMeasuremen
...
@@ -37,28 +35,44 @@ WimaMeasurementAreaData &WimaMeasurementAreaData::operator=(const WimaMeasuremen
*
*
* Assigns \a other to the invoking object.
* Assigns \a other to the invoking object.
*/
*/
WimaMeasurementAreaData
&
WimaMeasurementAreaData
::
operator
=
(
const
WimaMeasurementArea
&
other
)
WimaMeasurementAreaData
&
WimaMeasurementAreaData
::
{
operator
=
(
const
WimaMeasurementArea
&
other
)
{
assign
(
other
);
assign
(
other
);
return
*
this
;
}
QString
WimaMeasurementAreaData
::
type
()
const
return
*
this
;
{
return
this
->
typeString
;
}
}
void
WimaMeasurementAreaData
::
assign
(
const
WimaMeasurementAreaData
&
other
)
QString
WimaMeasurementAreaData
::
type
()
const
{
return
this
->
typeString
;
}
{
WimaAreaData
::
assign
(
other
);
void
WimaMeasurementAreaData
::
assign
(
const
WimaMeasurementAreaData
&
other
)
{
WimaAreaData
::
assign
(
other
);
this
->
tiles
.
clearAndDeleteContents
();
for
(
std
::
size_t
i
=
0
;
i
<
other
.
tiles
.
count
();
++
i
)
{
auto
*
obj
=
other
.
tiles
.
get
(
i
);
auto
*
tile
=
qobject_cast
<
SnakeTile
*>
(
obj
);
if
(
tile
!=
nullptr
)
{
this
->
tiles
.
append
(
new
SnakeTile
(
*
tile
,
this
));
}
else
{
qWarning
()
<<
"WimaMeasurementAreaData::assign(): type cast failed."
;
}
}
}
}
void
WimaMeasurementAreaData
::
assign
(
const
WimaMeasurementArea
&
other
)
void
WimaMeasurementAreaData
::
assign
(
const
WimaMeasurementArea
&
other
)
{
{
WimaAreaData
::
assign
(
other
);
WimaAreaData
::
assign
(
other
);
this
->
tiles
.
clearAndDeleteContents
();
if
(
other
.
ready
())
{
for
(
std
::
size_t
i
=
0
;
i
<
other
.
tiles
()
->
count
();
++
i
)
{
auto
*
obj
=
other
.
tiles
()
->
get
(
i
);
auto
*
tile
=
qobject_cast
<
SnakeTile
*>
(
obj
);
if
(
tile
!=
nullptr
)
{
this
->
tiles
.
append
(
new
SnakeTile
(
*
tile
,
this
));
}
else
{
qWarning
()
<<
"WimaMeasurementAreaData::assign(): type cast failed."
;
}
}
}
else
{
qWarning
()
<<
"WimaMeasurementAreaData::assign(): WimaMeasurementArea not ready."
;
}
}
}
src/Wima/Geometry/WimaMeasurementAreaData.h
View file @
47641f63
#pragma once
#pragma once
#include <QObject>
#include <QGeoCoordinate>
#include <QGeoCoordinate>
#include <QObject>
#include "WimaAreaData.h"
#include "WimaAreaData.h"
#include "WimaMeasurementArea.h"
#include "WimaMeasurementArea.h"
class
WimaMeasurementAreaData
:
public
WimaAreaData
{
Q_OBJECT
class
WimaMeasurementAreaData
:
public
WimaAreaData
{
Q_OBJECT
public:
public:
WimaMeasurementAreaData
(
QObject
*
parent
=
nullptr
);
WimaMeasurementAreaData
(
QObject
*
parent
=
nullptr
);
WimaMeasurementAreaData
(
const
WimaMeasurementAreaData
&
other
,
QObject
*
parent
=
nullptr
);
WimaMeasurementAreaData
(
const
WimaMeasurementAreaData
&
other
,
WimaMeasurementAreaData
(
const
WimaMeasurementArea
&
other
,
QObject
*
parent
=
nullptr
);
QObject
*
parent
=
nullptr
);
WimaMeasurementAreaData
&
operator
=
(
const
WimaMeasurementAreaData
&
other
);
WimaMeasurementAreaData
(
const
WimaMeasurementArea
&
other
,
WimaMeasurementAreaData
&
operator
=
(
const
WimaMeasurementArea
&
other
);
QObject
*
parent
=
nullptr
);
WimaMeasurementAreaData
&
operator
=
(
const
WimaMeasurementAreaData
&
other
);
WimaMeasurementAreaData
&
operator
=
(
const
WimaMeasurementArea
&
other
);
QString
type
()
const
;
QString
type
()
const
;
WimaMeasurementAreaData
*
Clone
()
const
{
return
new
WimaMeasurementAreaData
(
*
this
);}
WimaMeasurementAreaData
*
Clone
()
const
{
return
new
WimaMeasurementAreaData
(
*
this
);
}
static
const
char
*
typeString
;
static
const
char
*
typeString
;
signals:
signals:
public
slots
:
public
slots
:
protected:
protected:
void
assign
(
const
WimaMeasurementAreaData
&
other
);
void
assign
(
const
WimaMeasurementAreaData
&
other
);
void
assign
(
const
WimaMeasurementArea
&
other
);
void
assign
(
const
WimaMeasurementArea
&
other
);
private:
private:
// see WimaMeasurementArea.h for explanation
// see WimaMeasurementArea.h for explanation
QmlObjectListModel
tiles
;
};
};
src/Wima/WimaController.cc
View file @
47641f63
...
@@ -423,38 +423,42 @@ bool WimaController::setWimaPlanData(QSharedPointer<WimaPlanData> planData) {
...
@@ -423,38 +423,42 @@ bool WimaController::setWimaPlanData(QSharedPointer<WimaPlanData> planData) {
emit
visualItemsChanged
();
emit
visualItemsChanged
();
// extract mission items
// Copy transects.
auto
tempMissionItems
=
planData
->
missionItems
();
this
->
_rawTransects
=
planData
->
transects
();
if
(
tempMissionItems
.
size
()
<
1
)
{
qWarning
(
"WimaController: Mission items from WimaPlaner empty!"
);
// // extract mission items
return
false
;
// auto tempMissionItems = planData->missionItems();
}
// if (tempMissionItems.size() < 1) {
// qWarning("WimaController: Mission items from WimaPlaner empty!");
qWarning
()
<<
"WimaController:"
;
// return false;
for
(
auto
*
item
:
tempMissionItems
)
{
// }
qWarning
()
<<
item
->
coordinate
();
_defaultWM
.
push_back
(
item
->
coordinate
());
// qWarning() << "WimaController:";
}
// for (auto *item : tempMissionItems) {
// qWarning() << item->coordinate();
_WMSettings
.
setHomePosition
(
QGeoCoordinate
(
// _defaultWM.push_back(item->coordinate());
_serviceArea
.
depot
().
latitude
(),
_serviceArea
.
depot
().
longitude
(),
0
));
// }
qWarning
()
<<
"service area depot: "
<<
_serviceArea
.
depot
();
// _WMSettings.setHomePosition(QGeoCoordinate(
if
(
!
_defaultWM
.
reset
())
{
// _serviceArea.depot().latitude(), _serviceArea.depot().longitude(),
qWarning
()
<<
"_defaultWM.reset() failed"
;
// 0));
return
false
;
// qWarning() << "service area depot: " << _serviceArea.depot();
}
// if (!_defaultWM.reset()) {
emit
missionItemsChanged
();
// qWarning() << "_defaultWM.reset() failed";
emit
currentMissionItemsChanged
();
// return false;
emit
waypointPathChanged
();
// }
emit
currentWaypointPathChanged
();
// emit missionItemsChanged();
// Update Snake Data Manager
// emit currentMissionItemsChanged();
_snakeThread
.
setMeasurementArea
(
_measurementArea
.
coordinateList
());
// emit waypointPathChanged();
_snakeThread
.
setServiceArea
(
_serviceArea
.
coordinateList
());
// emit currentWaypointPathChanged();
_snakeThread
.
setCorridor
(
_corridor
.
coordinateList
());
_currentThread
->
start
();
// // Update Snake Data Manager
// _snakeThread.setMeasurementArea(_measurementArea.coordinateList());
// _snakeThread.setServiceArea(_serviceArea.coordinateList());
// _snakeThread.setCorridor(_corridor.coordinateList());
// _currentThread->start();
_localPlanDataValid
=
true
;
_localPlanDataValid
=
true
;
return
true
;
return
true
;
...
...
src/Wima/WimaController.h
View file @
47641f63
...
@@ -254,8 +254,8 @@ private:
...
@@ -254,8 +254,8 @@ private:
// Wima Data.
// Wima Data.
QmlObjectListModel
_areas
;
// contains all visible areas
QmlObjectListModel
_areas
;
// contains all visible areas
WimaJoinedAreaData
// joined area fromed by opArea, serArea, _corridor
_joinedArea
;
// joined area fromed by opArea, serArea, _corridor
WimaJoinedAreaData
_joinedArea
;
WimaMeasurementAreaData
_measurementArea
;
// measurement area
WimaMeasurementAreaData
_measurementArea
;
// measurement area
WimaServiceAreaData
_serviceArea
;
// area for supplying
WimaServiceAreaData
_serviceArea
;
// area for supplying
WimaCorridorData
_corridor
;
// corridor connecting opArea and serArea
WimaCorridorData
_corridor
;
// corridor connecting opArea and serArea
...
@@ -274,11 +274,11 @@ private:
...
@@ -274,11 +274,11 @@ private:
// Settings Facts.
// Settings Facts.
QMap
<
QString
,
FactMetaData
*>
_metaDataMap
;
QMap
<
QString
,
FactMetaData
*>
_metaDataMap
;
SettingsFact
_enableWimaController
;
// enables or disables the wimaControler
SettingsFact
_enableWimaController
;
// enables or disables the wimaControler
SettingsFact
// determines the number of overlapping waypoints between two consecutive
_overlapWaypoints
;
// determines the number of overlapping waypoint
s
// mission phase
s
// between two consecutive mission phases
SettingsFact
_overlapWaypoints
;
SettingsFact
_maxWaypointsPerPhase
;
// determines the maximum number waypoints
// determines the maximum number waypoints per phase
// per phase
SettingsFact
_maxWaypointsPerPhase
;
SettingsFact
SettingsFact
_nextPhaseStartWaypointIndex
;
// index (displayed on the map, -1 to get
_nextPhaseStartWaypointIndex
;
// index (displayed on the map, -1 to get
// index of item in _missionItems) of the
// index of item in _missionItems) of the
...
@@ -294,11 +294,6 @@ private:
...
@@ -294,11 +294,6 @@ private:
SettingsFact
_arrivalReturnSpeed
;
// arrival and return path speed
SettingsFact
_arrivalReturnSpeed
;
// arrival and return path speed
SettingsFact
_altitude
;
// mission altitude
SettingsFact
_altitude
;
// mission altitude
SettingsFact
_enableSnake
;
// Enable Snake (see snake.h)
SettingsFact
_enableSnake
;
// Enable Snake (see snake.h)
SettingsFact
_snakeTileWidth
;
SettingsFact
_snakeTileHeight
;
SettingsFact
_snakeMinTileArea
;
SettingsFact
_snakeLineDistance
;
SettingsFact
_snakeMinTransectLength
;
// Smart RTL.
// Smart RTL.
QTimer
_smartRTLTimer
;
QTimer
_smartRTLTimer
;
...
@@ -308,7 +303,7 @@ private:
...
@@ -308,7 +303,7 @@ private:
double
_measurementPathLength
;
// the lenght of the phase in meters
double
_measurementPathLength
;
// the lenght of the phase in meters
// Snake
// Snake
Q
mlObjectListModel
tile
s
;
Q
List
<
QList
<
QGeoCoordinate
>>
_rawTransect
s
;
SnakeThread
_snakeThread
;
// Snake Data Manager
SnakeThread
_snakeThread
;
// Snake Data Manager
SnakeThread
_emptyThread
;
SnakeThread
_emptyThread
;
SnakeThread
*
_currentThread
;
SnakeThread
*
_currentThread
;
...
...
src/Wima/WimaPlanData.cc
View file @
47641f63
...
@@ -76,6 +76,10 @@ void WimaPlanData::append(const WimaCorridorData &areaData) {
...
@@ -76,6 +76,10 @@ void WimaPlanData::append(const WimaCorridorData &areaData) {
}
}
}
}
void
WimaPlanData
::
setTransects
(
const
QList
<
QList
<
QGeoCoordinate
>>
&
transects
)
{
this
->
_transects
=
transects
;
}
/*!
/*!
* \fn void WimaPlanData::append(const WimaServiceAreaData &areaData)
* \fn void WimaPlanData::append(const WimaServiceAreaData &areaData)
*
*
...
@@ -110,6 +114,10 @@ const QList<const WimaAreaData *> &WimaPlanData::areaList() const {
...
@@ -110,6 +114,10 @@ const QList<const WimaAreaData *> &WimaPlanData::areaList() const {
return
_areaList
;
return
_areaList
;
}
}
const
QList
<
QList
<
QGeoCoordinate
>>
&
WimaPlanData
::
transects
()
const
{
return
_transects
;
}
const
QList
<
MissionItem
*>
&
WimaPlanData
::
missionItems
()
const
{
const
QList
<
MissionItem
*>
&
WimaPlanData
::
missionItems
()
const
{
return
_missionItems
;
return
_missionItems
;
}
}
...
...
src/Wima/WimaPlanData.h
View file @
47641f63
#pragma once
#pragma once
#include <QGeoCoordinate>
#include <QObject>
#include <QObject>
#include "Geometry/WimaAreaData.h"
#include "Geometry/WimaAreaData.h"
...
@@ -7,7 +8,6 @@
...
@@ -7,7 +8,6 @@
#include "Geometry/WimaJoinedAreaData.h"
#include "Geometry/WimaJoinedAreaData.h"
#include "Geometry/WimaMeasurementAreaData.h"
#include "Geometry/WimaMeasurementAreaData.h"
#include "Geometry/WimaServiceAreaData.h"
#include "Geometry/WimaServiceAreaData.h"
#include "MissionItem.h"
class
WimaPlanData
:
public
QObject
{
class
WimaPlanData
:
public
QObject
{
Q_OBJECT
Q_OBJECT
...
@@ -20,7 +20,8 @@ public:
...
@@ -20,7 +20,8 @@ public:
void
append
(
const
WimaJoinedAreaData
&
areaData
);
void
append
(
const
WimaJoinedAreaData
&
areaData
);
void
append
(
const
WimaServiceAreaData
&
areaData
);
void
append
(
const
WimaServiceAreaData
&
areaData
);
void
append
(
const
WimaCorridorData
&
areaData
);
void
append
(
const
WimaCorridorData
&
areaData
);
void
append
(
const
WimaMeasurementAreaData
&
areaData
);
void
setTransects
(
const
QList
<
QList
<
QGeoCoordinate
>>
&
transects
);
//!
//!
//! \brief append
//! \brief append
//! \param missionItems
//! \param missionItems
...
@@ -29,14 +30,11 @@ public:
...
@@ -29,14 +30,11 @@ public:
void
clear
();
void
clear
();
const
QList
<
const
WimaAreaData
*>
&
areaList
()
const
;
const
QList
<
const
WimaAreaData
*>
&
areaList
()
const
;
const
QList
<
MissionItem
*>
&
missionItem
s
()
const
;
const
QList
<
QList
<
QGeoCoordinate
>>
&
transect
s
()
const
;
signals:
signals:
void
areaListChanged
();
void
areaListChanged
();
private:
void
_clearAndDeleteMissionItems
();
private:
private:
WimaJoinedAreaData
_joinedArea
;
WimaJoinedAreaData
_joinedArea
;
WimaServiceAreaData
_serviceArea
;
WimaServiceAreaData
_serviceArea
;
...
@@ -44,5 +42,5 @@ private:
...
@@ -44,5 +42,5 @@ private:
WimaMeasurementAreaData
_measurementArea
;
WimaMeasurementAreaData
_measurementArea
;
QList
<
const
WimaAreaData
*>
_areaList
;
QList
<
const
WimaAreaData
*>
_areaList
;
QList
<
MissionItem
*>
_missionItem
s
;
QList
<
QList
<
QGeoCoordinate
>>
_transect
s
;
};
};
src/Wima/WimaPlaner.cc
View file @
47641f63
...
@@ -666,17 +666,21 @@ void WimaPlaner::updatePolygonInteractivity(int index) {
...
@@ -666,17 +666,21 @@ void WimaPlaner::updatePolygonInteractivity(int index) {
void
WimaPlaner
::
synchronize
()
{
void
WimaPlaner
::
synchronize
()
{
if
(
_wimaBridge
!=
nullptr
)
{
if
(
_wimaBridge
!=
nullptr
)
{
if
(
_needsUpdate
)
if
(
readyForSynchronization
())
{
return
;
auto
planData
=
toPlanData
()
;
auto
planData
=
toPlanData
(
);
(
void
)
_wimaBridge
->
setWimaPlanData
(
planData
);
(
void
)
_wimaBridge
->
setWimaPlanData
(
planData
)
;
this
->
_synchronized
=
true
;
this
->
_synchronized
=
true
;
emit
synchronizedChanged
()
;
emit
synchronizedChanged
();
}
}
else
{
}
else
{
qWarning
(
"WimaPlaner::uploadToContainer(): no container assigned."
);
qWarning
(
"WimaPlaner::uploadToContainer(): no container assigned."
);
}
}
}
}
bool
WimaPlaner
::
readyForSynchronization
()
{
return
!
_needsUpdate
&&
_measurementArea
.
ready
();
}
bool
WimaPlaner
::
shortestPath
(
const
QGeoCoordinate
&
start
,
bool
WimaPlaner
::
shortestPath
(
const
QGeoCoordinate
&
start
,
const
QGeoCoordinate
&
destination
,
const
QGeoCoordinate
&
destination
,
QVector
<
QGeoCoordinate
>
&
path
)
{
QVector
<
QGeoCoordinate
>
&
path
)
{
...
@@ -737,14 +741,7 @@ QSharedPointer<WimaPlanData> WimaPlaner::toPlanData() {
...
@@ -737,14 +741,7 @@ QSharedPointer<WimaPlanData> WimaPlaner::toPlanData() {
planData
->
append
(
WimaJoinedAreaData
(
_joinedArea
));
planData
->
append
(
WimaJoinedAreaData
(
_joinedArea
));
// convert mission items to mavlink commands
// convert mission items to mavlink commands
QList
<
MissionItem
*>
missionItems
;
planData
->
setTransects
(
this
->
_TSComplexItem
->
rawTransects
());
_TSComplexItem
->
appendMissionItems
(
missionItems
,
nullptr
);
// store mavlink commands
qWarning
()
<<
"WimaPlaner"
;
for
(
auto
*
item
:
missionItems
)
{
qWarning
()
<<
item
->
coordinate
();
}
planData
->
append
(
missionItems
);
return
planData
;
return
planData
;
}
}
...
...
src/Wima/WimaPlaner.h
View file @
47641f63
...
@@ -84,6 +84,7 @@ public:
...
@@ -84,6 +84,7 @@ public:
Q_INVOKABLE
bool
update
();
Q_INVOKABLE
bool
update
();
/// Pushes the generated mission data to the wimaController.
/// Pushes the generated mission data to the wimaController.
Q_INVOKABLE
void
synchronize
();
Q_INVOKABLE
void
synchronize
();
Q_INVOKABLE
bool
readyForSynchronization
();
Q_INVOKABLE
void
saveToCurrent
();
Q_INVOKABLE
void
saveToCurrent
();
Q_INVOKABLE
void
saveToFile
(
const
QString
&
filename
);
Q_INVOKABLE
void
saveToFile
(
const
QString
&
filename
);
Q_INVOKABLE
bool
loadFromCurrent
();
Q_INVOKABLE
bool
loadFromCurrent
();
...
...
src/Wima/json/CircularSurvey.SettingsGroup.json
View file @
47641f63
[
[
{
{
"name"
:
"
DeltaR
"
,
"name"
:
"
TransectDistance
"
,
"shortDescription"
:
"The distance between t
wo consecutive circle
s."
,
"shortDescription"
:
"The distance between t
ransect
s."
,
"type"
:
"double"
,
"type"
:
"double"
,
"units"
:
"m"
,
"units"
:
"m"
,
"min"
:
0.3
,
"min"
:
0.3
,
...
@@ -9,18 +9,18 @@
...
@@ -9,18 +9,18 @@
"defaultValue"
:
20.0
"defaultValue"
:
20.0
},
},
{
{
"name"
:
"
Delta
Alpha"
,
"name"
:
"Alpha"
,
"shortDescription"
:
"Angle discretisation o
f the circles
."
,
"shortDescription"
:
"Angle discretisation o
r transect angle (depending on type)
."
,
"type"
:
"double"
,
"type"
:
"double"
,
"units"
:
"Deg"
,
"units"
:
"Deg"
,
"min"
:
0
.3
,
"min"
:
0
,
"max"
:
9
0
,
"max"
:
18
0
,
"decimalPlaces"
:
1
,
"decimalPlaces"
:
1
,
"defaultValue"
:
5.0
"defaultValue"
:
5.0
},
},
{
{
"name"
:
"
Transect
MinLength"
,
"name"
:
"MinLength"
,
"shortDescription"
:
"The minimal
length transects must have to be accepted
."
,
"shortDescription"
:
"The minimal
transect length
."
,
"type"
:
"double"
,
"type"
:
"double"
,
"units"
:
"m"
,
"units"
:
"m"
,
"min"
:
0.3
,
"min"
:
0.3
,
...
@@ -28,23 +28,11 @@
...
@@ -28,23 +28,11 @@
"defaultValue"
:
5.0
"defaultValue"
:
5.0
},
},
{
{
"name"
:
"FixedDirection"
,
"name"
:
"Type"
,
"shortDescription"
:
"Determines whether all transects have the same direction or not."
,
"shortDescription"
:
"Survey Type."
,
"type"
:
"bool"
,
"type"
:
"uint64"
,
"defaultValue"
:
1
"min"
:
0
,
},
"max"
:
1
,
{
"name"
:
"Reverse"
,
"shortDescription"
:
"Reverses the transect path."
,
"type"
:
"bool"
,
"defaultValue"
:
0
"defaultValue"
:
0
},
{
"name"
:
"MaxWaypoints"
,
"shortDescription"
:
"The maximum number of waypoints the circular survey can containt. To many waypoints cause a performance hit."
,
"type"
:
"uint32"
,
"defaultValue"
:
2000
,
"min"
:
1
,
"max"
:
20000
}
}
]
]
src/WimaView/CircularSurveyMapVisual.qml
View file @
47641f63
...
@@ -27,29 +27,68 @@ Item {
...
@@ -27,29 +27,68 @@ Item {
property
var
_missionItem
:
object
property
var
_missionItem
:
object
property
var
_mapPolygon
:
object
.
surveyAreaPolygon
property
var
_mapPolygon
:
object
.
surveyAreaPolygon
property
var
_
visualT
ransectsComponent
property
var
_
t
ransectsComponent
property
var
_entryCoordinate
property
var
_entryCoordinate
property
var
_exitCoordinate
property
var
_exitCoordinate
property
var
_refPoint
property
var
_refPoint
property
bool
showRefPoint
:
_missionItem
.
type
.
value
===
0
// type == Circular
signal
clicked
(
int
sequenceNumber
)
signal
clicked
(
int
sequenceNumber
)
function
_addVisualElements
()
{
function
_addTransectsComponent
(){
_visualTransectsComponent
=
visualTransectsComponent
.
createObject
(
map
)
if
(
!
_transectsComponent
){
_entryCoordinate
=
entryPointComponent
.
createObject
(
map
)
_transectsComponent
=
visualTransectsComponent
.
createObject
(
map
)
_exitCoordinate
=
exitPointComponent
.
createObject
(
map
)
map
.
addMapItem
(
_transectsComponent
)
_refPoint
=
refPointComponent
.
createObject
(
map
)
}
map
.
addMapItem
(
_visualTransectsComponent
)
}
map
.
addMapItem
(
_entryCoordinate
)
map
.
addMapItem
(
_exitCoordinate
)
function
_addExitCoordinate
(){
map
.
addMapItem
(
_refPoint
)
if
(
!
_exitCoordinate
){
_exitCoordinate
=
exitPointComponent
.
createObject
(
map
)
map
.
addMapItem
(
_exitCoordinate
)
}
}
function
_addEntryCoordinate
(){
if
(
!
_entryCoordinate
){
_entryCoordinate
=
entryPointComponent
.
createObject
(
map
)
map
.
addMapItem
(
_entryCoordinate
)
}
}
function
_addRefPoint
(){
if
(
!
_refPoint
){
_refPoint
=
refPointComponent
.
createObject
(
map
)
map
.
addMapItem
(
_refPoint
)
}
}
function
_destroyEntryCoordinate
(){
if
(
_entryCoordinate
){
_entryCoordinate
.
destroy
()
_entryCoordinate
=
undefined
}
}
function
_destroyExitCoordinate
(){
if
(
_exitCoordinate
){
_exitCoordinate
.
destroy
()
_exitCoordinate
=
undefined
}
}
}
function
_destroyVisualElements
()
{
function
_destroyRefPoint
(){
_visualTransectsComponent
.
destroy
()
if
(
_refPoint
){
_entryCoordinate
.
destroy
()
_refPoint
.
destroy
()
_exitCoordinate
.
destroy
()
_refPoint
=
undefined
_refPoint
.
destroy
()
}
}
function
_destroyTransectsComponent
(){
if
(
_transectsComponent
){
_transectsComponent
.
destroy
()
_transectsComponent
=
undefined
}
}
}
/// Add an initial 4 sided polygon if there is none
/// Add an initial 4 sided polygon if there is none
...
@@ -83,20 +122,33 @@ Item {
...
@@ -83,20 +122,33 @@ Item {
}
}
}
}
function
_setRefPoint
()
{
_missionItem
.
resetReference
();
}
Component.onCompleted
:
{
Component.onCompleted
:
{
if
(
_m
issionItem
.
visualTransectPoints
.
length
===
0
)
{
if
(
_m
apPolygon
.
count
===
0
)
{
_addInitialPolygon
()
_addInitialPolygon
()
_
setRefPoint
()
_
missionItem
.
resetReference
();
}
}
_addVisualElements
()
_addEntryCoordinate
()
_addExitCoordinate
()
if
(
showRefPoint
){
_addRefPoint
()
}
_addTransectsComponent
()
}
}
Component
.
onDestruction
:
{
Component
.
onDestruction
:
{
_destroyVisualElements
()
_destroyEntryCoordinate
()
_destroyExitCoordinate
()
_destroyRefPoint
()
_destroyTransectsComponent
()
}
onShowRefPointChanged
:
{
if
(
showRefPoint
){
_addRefPoint
()
}
else
{
_destroyRefPoint
()
}
}
}
WimaMapPolygonVisuals
{
WimaMapPolygonVisuals
{
...
@@ -117,9 +169,10 @@ Item {
...
@@ -117,9 +169,10 @@ Item {
id
:
visualTransectsComponent
id
:
visualTransectsComponent
MapPolyline
{
MapPolyline
{
property
var
transects
:
_missionItem
.
visualTransectPoints
line.color
:
"
white
"
line.color
:
"
white
"
line.width
:
2
line.width
:
2
path
:
_missionItem
.
visualTransectPoints
path
:
transects
.
length
>
0
?
transects
:
[]
}
}
}
}
...
@@ -174,20 +227,13 @@ Item {
...
@@ -174,20 +227,13 @@ Item {
checked
:
_missionItem
.
isCurrentItem
checked
:
_missionItem
.
isCurrentItem
coordinate
:
_missionItem
.
refPoint
coordinate
:
_missionItem
.
refPoint
property
var
refPoint
:
_missionItem
.
refPoint
onRefPointChanged
:
{
if
(
refPoint
!==
coordinate
)
{
coordinate
=
refPoint
}
}
onClicked
:
{
onClicked
:
{
_root
.
clicked
(
_missionItem
.
sequenceNumber
)
_root
.
clicked
(
_missionItem
.
sequenceNumber
)
}
}
onDragReleased
:
{
onDragReleased
:
{
_missionItem
.
refPoint
=
coordinate
_missionItem
.
refPoint
=
coordinate
coordinate
=
Qt
.
binding
(
function
(){
return
_missionItem
.
refPoint
})
}
}
}
}
}
}
...
...
src/WimaView/WimaServiceAreaMapVisual.qml
View file @
47641f63
...
@@ -104,7 +104,7 @@ Item {
...
@@ -104,7 +104,7 @@ Item {
Component
.
onCompleted
:
{
Component
.
onCompleted
:
{
_addInitialPolygon
()
_addInitialPolygon
()
if
(
interactive
){
if
(
showDepot
){
_addDepot
()
_addDepot
()
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment