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
58b2b82d
Commit
58b2b82d
authored
Oct 19, 2020
by
Valentin Platzgummer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
circular and linera transect generators added
parent
06e9bcab
Changes
20
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
796 additions
and
226 deletions
+796
-226
qgroundcontrol.pro
qgroundcontrol.pro
+5
-3
qgroundcontrol.qrc
qgroundcontrol.qrc
+2
-0
CircularSurvey.cc
src/Wima/CircularSurvey.cc
+5
-14
RoutingThread.cpp
src/Wima/RoutingThread.cpp
+1
-1
RoutingThread.h
src/Wima/RoutingThread.h
+2
-2
CircularGenerator.cpp
src/Wima/Snake/CircularGenerator.cpp
+195
-23
CircularGenerator.h
src/Wima/Snake/CircularGenerator.h
+40
-3
GeneratorBase.cc
src/Wima/Snake/GeneratorBase.cc
+18
-4
GeneratorBase.h
src/Wima/Snake/GeneratorBase.h
+11
-1
GeneratorData.h
src/Wima/Snake/GeneratorData.h
+0
-9
LinearGenerator.cpp
src/Wima/Snake/LinearGenerator.cpp
+332
-0
LinearGenerator.h
src/Wima/Snake/LinearGenerator.h
+47
-0
StandardData.cpp
src/Wima/Snake/StandardData.cpp
+0
-3
StandardData.h
src/Wima/Snake/StandardData.h
+0
-9
CircularGenerator.SettingsGroup.json
src/Wima/Snake/json/CircularGenerator.SettingsGroup.json
+30
-0
LinearGenerator.SettingsGroup.json
src/Wima/Snake/json/LinearGenerator.SettingsGroup.json
+30
-0
WimaController.cc
src/Wima/WimaController.cc
+31
-52
WimaPlanData.cc
src/Wima/WimaPlanData.cc
+33
-76
WimaPlanData.h
src/Wima/WimaPlanData.h
+10
-22
WimaPlaner.cc
src/Wima/WimaPlaner.cc
+4
-4
No files found.
qgroundcontrol.pro
View file @
58b2b82d
...
...
@@ -420,8 +420,7 @@ HEADERS += \
src
/
Wima
/
RoutingThread
.
h
\
src
/
Wima
/
Snake
/
CircularGenerator
.
h
\
src
/
Wima
/
Snake
/
GeneratorBase
.
h
\
src
/
Wima
/
Snake
/
GeneratorData
.
h
\
src
/
Wima
/
Snake
/
StandardData
.
h
\
src
/
Wima
/
Snake
/
LinearGenerator
.
h
\
src
/
Wima
/
Snake
/
clipper
/
clipper
.
hpp
\
src
/
Wima
/
Snake
/
mapbox
/
feature
.
hpp
\
src
/
Wima
/
Snake
/
mapbox
/
geometry
.
hpp
\
...
...
@@ -516,7 +515,7 @@ SOURCES += \
src
/
Wima
/
RoutingThread
.
cpp
\
src
/
Wima
/
Snake
/
CircularGenerator
.
cpp
\
src
/
Wima
/
Snake
/
GeneratorBase
.
cc
\
src
/
Wima
/
Snake
/
StandardData
.
cpp
\
src
/
Wima
/
Snake
/
LinearGenerator
.
cpp
\
src
/
Wima
/
Snake
/
clipper
/
clipper
.
cpp
\
src
/
Wima
/
Snake
/
snake
.
cpp
\
src
/
Wima
/
Geometry
/
GeoPoint3D
.
cpp
\
...
...
@@ -1456,5 +1455,8 @@ contains (CONFIG, QGC_DISABLE_INSTALLER_SETUP) {
}
DISTFILES
+=
\
src
/
Wima
/
Routing
/
json
/
CircularGenerator
.
SettingsGroup
.
json
\
src
/
Wima
/
Snake
/
json
/
LinearGenerator
.
SettingsGroup
.
json
\
src
/
Wima
/
json
/
CircularSurvey
.
SettingsGroup
.
json
\
src
/
WimaView
/
WimaMeasurementAreaEditor
.
qml
\
src
/
Settings
/
Wima
.
SettingsGroup
.
json
qgroundcontrol.qrc
View file @
58b2b82d
...
...
@@ -287,6 +287,8 @@
<file alias="WimaArea.SettingsGroup.json">src/Wima/Geometry/json/WimaArea.SettingsGroup.json</file>
<file alias="WimaController.SettingsGroup.json">src/Wima/json/WimaController.SettingsGroup.json</file>
<file alias="Wima.SettingsGroup.json">src/Settings/Wima.SettingsGroup.json</file>
<file alias="CircularGenerator.SettingsGroup.json">src/Wima/Snake/json/CircularGenerator.SettingsGroup.json</file>
<file alias="LinearGenerator.SettingsGroup.json">src/Wima/Snake/json/LinearGenerator.SettingsGroup.json</file>
</qresource>
<qresource prefix="/MockLink">
<file alias="APMArduCopterMockLink.params">src/comm/APMArduCopterMockLink.params</file>
...
...
src/Wima/CircularSurvey.cc
View file @
58b2b82d
...
...
@@ -9,6 +9,10 @@
#define CLIPPER_SCALE 1000000
#include "clipper/clipper.hpp"
using
namespace
ClipperLib
;
template
<>
inline
auto
get
<
0
>
(
const
IntPoint
&
p
)
{
return
p
.
X
;
}
template
<>
inline
auto
get
<
1
>
(
const
IntPoint
&
p
)
{
return
p
.
Y
;
}
#include "Geometry/GenericCircle.h"
#include "Snake/SnakeTile.h"
...
...
@@ -18,19 +22,6 @@
QGC_LOGGING_CATEGORY
(
CircularSurveyLog
,
"CircularSurveyLog"
)
using
namespace
ClipperLib
;
template
<>
auto
get
<
0
>
(
const
IntPoint
&
p
)
{
return
p
.
X
;
}
template
<>
auto
get
<
1
>
(
const
IntPoint
&
p
)
{
return
p
.
Y
;
}
template
<
class
Functor
>
class
CommandRAII
{
public:
CommandRAII
(
Functor
f
)
:
fun
(
f
)
{}
~
CommandRAII
()
{
fun
();
}
private:
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
);
...
...
@@ -456,7 +447,7 @@ void CircularSurvey::_updateWorker() {
// Routing par.
RoutingParameter
par
;
par
.
numSolutions
PerRun
=
5
;
par
.
numSolutions
=
5
;
if
(
this
->
_numRuns
.
rawValue
().
toUInt
()
<
1
)
{
disconnect
(
&
this
->
_numRuns
,
&
Fact
::
rawValueChanged
,
this
,
&
CircularSurvey
::
_rebuildTransects
);
...
...
src/Wima/RoutingThread.cpp
View file @
58b2b82d
...
...
@@ -59,7 +59,7 @@ void RoutingThread::run() {
lk
.
unlock
();
auto
safeAreaENU
=
par
.
safeArea
;
auto
numRuns
=
par
.
numRuns
;
auto
numSolutionsPerRun
=
par
.
numSolutions
PerRun
;
auto
numSolutionsPerRun
=
par
.
numSolutions
;
PtrRoutingData
pRouteData
(
new
RoutingData
());
auto
&
transectsENU
=
pRouteData
->
transects
;
...
...
src/Wima/RoutingThread.h
View file @
58b2b82d
...
...
@@ -17,9 +17,9 @@ struct RoutingData {
};
struct
RoutingParameter
{
RoutingParameter
()
:
numSolutions
PerRun
(
1
),
numRuns
(
1
)
{}
RoutingParameter
()
:
numSolutions
(
1
),
numRuns
(
1
)
{}
snake
::
FPolygon
safeArea
;
std
::
size_t
numSolutions
PerRun
;
std
::
size_t
numSolutions
;
std
::
size_t
numRuns
;
};
//!
...
...
src/Wima/Snake/CircularGenerator.cpp
View file @
58b2b82d
...
...
@@ -6,19 +6,39 @@ QGC_LOGGING_CATEGORY(CircularGeneratorLog, "CircularGeneratorLog")
#define CLIPPER_SCALE 1000000
#include "Wima/Geometry/GenericCircle.h"
#include "clipper/clipper.hpp"
// Clipper and GenericCircle
using
namespace
ClipperLib
;
template
<>
auto
get
<
0
>
(
const
IntPoint
&
p
)
{
return
p
.
X
;
}
template
<>
auto
get
<
1
>
(
const
IntPoint
&
p
)
{
return
p
.
Y
;
}
template
<>
inline
auto
get
<
0
>
(
const
IntPoint
&
p
)
{
return
p
.
X
;
}
template
<>
inline
auto
get
<
1
>
(
const
IntPoint
&
p
)
{
return
p
.
Y
;
}
#include "SnakeTile.h"
#include "Wima/RoutingThread.h"
namespace
routing
{
bool
circularTransects
(
const
snake
::
FPolygon
&
polygon
,
bool
circularTransects
(
const
snake
::
FPoint
&
reference
,
const
snake
::
FPolygon
&
polygon
,
const
std
::
vector
<
snake
::
FPolygon
>
&
tiles
,
snake
::
Length
deltaR
,
snake
::
Angle
deltaAlpha
,
snake
::
Length
minLength
,
snake
::
Transects
&
transects
);
CircularGenerator
::
CircularGenerator
(
QObject
*
parent
)
:
GeneratorBase
(
parent
)
{}
const
char
*
CircularGenerator
::
settingsGroup
=
"CircularGenerator"
;
const
char
*
CircularGenerator
::
distanceName
=
"TransectDistance"
;
const
char
*
CircularGenerator
::
deltaAlphaName
=
"DeltaAlpha"
;
const
char
*
CircularGenerator
::
minLengthName
=
"MinLength"
;
CircularGenerator
::
CircularGenerator
(
QObject
*
parent
)
:
CircularGenerator
(
nullptr
,
parent
)
{}
CircularGenerator
::
CircularGenerator
(
GeneratorBase
::
Data
d
,
QObject
*
parent
)
:
GeneratorBase
(
d
,
parent
),
_connectionsEstablished
(
false
),
_metaDataMap
(
FactMetaData
::
createMapFromJsonFile
(
QStringLiteral
(
":/json/CircularGenerator.SettingsGroup.json"
),
this
)),
_distance
(
settingsGroup
,
_metaDataMap
[
distanceName
]),
_deltaAlpha
(
settingsGroup
,
_metaDataMap
[
deltaAlphaName
]),
_minLength
(
settingsGroup
,
_metaDataMap
[
minLengthName
])
{
establishConnections
();
}
QString
CircularGenerator
::
editorQML
()
{
return
QStringLiteral
(
"CircularGeneratorEditor.qml"
);
...
...
@@ -34,18 +54,171 @@ QString CircularGenerator::name() {
QString
CircularGenerator
::
abbreviation
()
{
return
QStringLiteral
(
"C. Gen."
);
}
bool
CircularGenerator
::
get
(
const
WimaPlanData
&
data
,
GeneratorBase
&
generator
)
{
auto
generator
=
[
depot
,
pPolygon
,
pTiles
,
distance
,
alpha
,
bool
CircularGenerator
::
get
(
Generator
&
generator
)
{
if
(
this
->
_d
)
{
if
(
this
->
_d
->
isValid
())
{
// Prepare data.
const
auto
&
origin
=
this
->
_d
->
origin
();
if
(
!
origin
.
isValid
())
{
qCWarning
(
CircularGeneratorLog
)
<<
"get(): origin invalid."
<<
origin
;
return
false
;
}
const
auto
&
ref
=
this
->
_reference
;
if
(
!
ref
.
isValid
())
{
qCWarning
(
CircularGeneratorLog
)
<<
"get(): reference invalid."
<<
ref
;
return
false
;
}
snake
::
FPoint
reference
;
snake
::
toENU
(
origin
,
ref
,
reference
);
auto
geoPolygon
=
this
->
_d
->
measurementArea
().
coordinateList
();
for
(
auto
&
v
:
geoPolygon
)
{
if
(
v
.
isValid
())
{
v
.
setAltitude
(
0
);
}
else
{
qCWarning
(
CircularGeneratorLog
)
<<
"get(): measurement area invalid."
;
for
(
const
auto
&
w
:
geoPolygon
)
{
qCWarning
(
CircularGeneratorLog
)
<<
w
;
}
return
false
;
}
}
auto
pPolygon
=
std
::
make_shared
<
snake
::
FPolygon
>
();
snake
::
areaToEnu
(
origin
,
geoPolygon
,
*
pPolygon
);
// Progress and tiles.
const
auto
&
progress
=
this
->
_d
->
measurementArea
().
progress
();
const
auto
*
tiles
=
this
->
_d
->
measurementArea
().
tiles
();
auto
pTiles
=
std
::
make_shared
<
std
::
vector
<
snake
::
FPolygon
>>
();
if
(
progress
.
size
()
==
tiles
->
count
())
{
for
(
int
i
=
0
;
i
<
tiles
->
count
();
++
i
)
{
if
(
progress
[
i
]
==
100
)
{
const
auto
*
tile
=
tiles
->
value
<
const
SnakeTile
*>
(
i
);
if
(
tile
!=
nullptr
)
{
snake
::
FPolygon
tileENU
;
snake
::
areaToEnu
(
origin
,
tile
->
coordinateList
(),
tileENU
);
pTiles
->
push_back
(
std
::
move
(
tileENU
));
}
else
{
qCWarning
(
CircularGeneratorLog
)
<<
"get(): progress.size() != tiles->count()."
;
return
false
;
}
}
}
}
else
{
qCWarning
(
CircularGeneratorLog
)
<<
"get(): progress.size() != tiles->count()."
;
return
false
;
}
auto
geoDepot
=
this
->
_d
->
serviceArea
().
depot
();
if
(
!
geoDepot
.
isValid
())
{
qCWarning
(
CircularGeneratorLog
)
<<
"get(): depot invalid."
<<
geoDepot
;
return
false
;
}
snake
::
FPoint
depot
;
snake
::
toENU
(
origin
,
geoDepot
,
depot
);
// Fetch transect parameter.
auto
distance
=
snake
::
Length
(
this
->
_distance
.
rawValue
().
toDouble
()
*
bu
::
si
::
meter
);
auto
minLength
=
snake
::
Length
(
this
->
_minLength
.
rawValue
().
toDouble
()
*
bu
::
si
::
meter
);
auto
alpha
=
snake
::
Angle
(
this
->
_deltaAlpha
.
rawValue
().
toDouble
()
*
bu
::
degree
::
degree
);
generator
=
[
reference
,
depot
,
pPolygon
,
pTiles
,
distance
,
alpha
,
minLength
](
snake
::
Transects
&
transects
)
->
bool
{
bool
value
=
circularTransects
(
*
pPolygon
,
*
pTiles
,
distance
,
alpha
,
minLength
,
transects
);
bool
value
=
circularTransects
(
reference
,
*
pPolygon
,
*
pTiles
,
distance
,
alpha
,
minLength
,
transects
);
transects
.
insert
(
transects
.
begin
(),
snake
::
FLineString
{
depot
});
return
value
;
};
return
true
;
}
else
{
qCWarning
(
CircularGeneratorLog
)
<<
"get(): data invalid."
;
return
false
;
}
}
else
{
qCWarning
(
CircularGeneratorLog
)
<<
"get(): data member not set."
;
return
false
;
}
}
bool
circularTransects
(
const
snake
::
FPolygon
&
polygon
,
QGeoCoordinate
CircularGenerator
::
reference
()
const
{
return
_reference
;
}
void
CircularGenerator
::
setReference
(
const
QGeoCoordinate
&
reference
)
{
if
(
_reference
!=
reference
)
{
_reference
=
reference
;
emit
referenceChanged
();
}
}
void
CircularGenerator
::
resetReference
()
{
setReference
(
_d
->
measurementArea
().
center
());
}
void
CircularGenerator
::
establishConnections
()
{
if
(
this
->
_d
&&
!
this
->
_connectionsEstablished
)
{
connect
(
this
->
_d
.
get
(),
&
WimaPlanData
::
measurementAreaChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
_d
.
get
(),
&
WimaPlanData
::
originChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
&
this
->
_d
->
measurementArea
(),
&
WimaMeasurementAreaData
::
progressChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
&
this
->
_d
->
measurementArea
(),
&
WimaMeasurementAreaData
::
tileDataChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
&
this
->
_d
->
serviceArea
(),
&
WimaServiceAreaData
::
depotChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
distance
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
deltaAlpha
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
minLength
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
,
&
CircularGenerator
::
referenceChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
this
->
_connectionsEstablished
=
true
;
}
}
void
CircularGenerator
::
deleteConnections
()
{
if
(
this
->
_d
&&
this
->
_connectionsEstablished
)
{
disconnect
(
this
->
_d
.
get
(),
&
WimaPlanData
::
measurementAreaChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
this
->
_d
.
get
(),
&
WimaPlanData
::
originChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
&
this
->
_d
->
measurementArea
(),
&
WimaMeasurementAreaData
::
progressChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
&
this
->
_d
->
measurementArea
(),
&
WimaMeasurementAreaData
::
tileDataChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
&
this
->
_d
->
serviceArea
(),
&
WimaServiceAreaData
::
depotChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
this
->
distance
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
this
->
deltaAlpha
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
this
->
minLength
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
this
,
&
CircularGenerator
::
referenceChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
this
->
_connectionsEstablished
=
false
;
}
}
Fact
*
CircularGenerator
::
distance
()
{
return
&
_distance
;
}
Fact
*
CircularGenerator
::
deltaAlpha
()
{
return
&
_deltaAlpha
;
}
Fact
*
CircularGenerator
::
minLength
()
{
return
&
_minLength
;
}
bool
circularTransects
(
const
snake
::
FPoint
&
reference
,
const
snake
::
FPolygon
&
polygon
,
const
std
::
vector
<
snake
::
FPolygon
>
&
tiles
,
snake
::
Length
deltaR
,
snake
::
Angle
deltaAlpha
,
snake
::
Length
minLength
,
snake
::
Transects
&
transects
)
{
...
...
@@ -55,7 +228,6 @@ bool circularTransects(const snake::FPolygon &polygon,
if
(
polygon
.
outer
().
size
()
>=
3
)
{
using
namespace
boost
::
units
;
// Convert geo polygon to ENU polygon.
snake
::
FPoint
origin
{
0
,
0
};
std
::
string
error
;
// Check validity.
if
(
!
bg
::
is_valid
(
polygon
,
error
))
{
...
...
@@ -75,7 +247,7 @@ bool circularTransects(const snake::FPolygon &polygon,
// qCWarning(CircularGeneratorLog) << "circularTransects():";
//#endif
for
(
const
auto
&
p
:
polygon
.
outer
())
{
snake
::
Length
distance
=
bg
::
distance
(
origin
,
p
)
*
si
::
meter
;
snake
::
Length
distance
=
bg
::
distance
(
reference
,
p
)
*
si
::
meter
;
distances
.
push_back
(
distance
);
snake
::
Angle
alpha
=
(
std
::
atan2
(
p
.
get
<
1
>
(),
p
.
get
<
0
>
()))
*
si
::
radian
;
alpha
=
alpha
<
0
*
si
::
radian
?
alpha
+
2
*
M_PI
*
si
::
radian
:
alpha
;
...
...
@@ -95,8 +267,8 @@ bool circularTransects(const snake::FPolygon &polygon,
snake
::
Angle
alpha1
(
0
*
degree
::
degree
);
snake
::
Angle
alpha2
(
360
*
degree
::
degree
);
// Determine r_min by successive approximation
if
(
!
bg
::
within
(
origin
,
polygon
.
outer
()))
{
rMin
=
bg
::
distance
(
origin
,
polygon
)
*
si
::
meter
;
if
(
!
bg
::
within
(
reference
,
polygon
.
outer
()))
{
rMin
=
bg
::
distance
(
reference
,
polygon
)
*
si
::
meter
;
}
auto
rMax
=
(
*
std
::
max_element
(
distances
.
begin
(),
...
...
@@ -107,9 +279,9 @@ bool circularTransects(const snake::FPolygon &polygon,
ClipperLib
::
cInt
(
std
::
round
(
rMin
.
value
()
*
CLIPPER_SCALE
));
const
auto
deltaRScaled
=
ClipperLib
::
cInt
(
std
::
round
(
deltaR
.
value
()
*
CLIPPER_SCALE
));
auto
originScaled
=
ClipperLib
::
IntPoint
{
ClipperLib
::
cInt
(
std
::
round
(
origin
.
get
<
0
>
())),
ClipperLib
::
cInt
(
std
::
round
(
origin
.
get
<
1
>
()))};
auto
referenceScaled
=
ClipperLib
::
IntPoint
{
ClipperLib
::
cInt
(
std
::
round
(
reference
.
get
<
0
>
())),
ClipperLib
::
cInt
(
std
::
round
(
reference
.
get
<
1
>
()))};
// Generate circle sectors.
auto
rScaled
=
rMinScaled
;
...
...
@@ -136,7 +308,7 @@ bool circularTransects(const snake::FPolygon &polygon,
using
ClipperCircle
=
GenericCircle
<
ClipperLib
::
cInt
,
ClipperLib
::
IntPoint
>
;
for
(
auto
&
sector
:
sectors
)
{
ClipperCircle
circle
(
rScaled
,
origin
Scaled
);
ClipperCircle
circle
(
rScaled
,
reference
Scaled
);
approximate
(
circle
,
nSectors
,
sector
);
rScaled
+=
deltaRScaled
;
}
...
...
src/Wima/Snake/CircularGenerator.h
View file @
58b2b82d
#include "GeneratorBase.h"
#include "StandardData.h"
#include <QGeoCoordinate>
namespace
routing
{
class
CircularGenerator
:
public
GeneratorBase
{
Q_OBJECT
public:
CircularGenerator
(
QObject
*
parent
=
nullptr
)
override
;
CircularGenerator
(
QObject
*
parent
=
nullptr
);
CircularGenerator
(
Data
d
,
QObject
*
parent
=
nullptr
);
Q_PROPERTY
(
QGeoCoordinate
reference
READ
reference
WRITE
setReference
NOTIFY
referenceChanged
)
Q_PROPERTY
(
Fact
*
distance
READ
distance
CONSTANT
)
Q_PROPERTY
(
Fact
*
deltaAlpha
READ
deltaAlpha
CONSTANT
)
Q_PROPERTY
(
Fact
*
minLength
READ
minLength
CONSTANT
)
virtual
QString
editorQML
()
override
;
virtual
QString
mapVisualQML
()
override
;
...
...
@@ -14,7 +22,36 @@ public:
virtual
QString
name
()
override
;
virtual
QString
abbreviation
()
override
;
virtual
bool
get
(
const
WimaPlanData
&
data
,
GeneratorBase
&
generator
);
virtual
bool
get
(
Generator
&
generator
)
override
;
QGeoCoordinate
reference
()
const
;
Fact
*
distance
();
Fact
*
deltaAlpha
();
Fact
*
minLength
();
void
setReference
(
const
QGeoCoordinate
&
reference
);
void
resetReference
();
static
const
char
*
settingsGroup
;
static
const
char
*
distanceName
;
static
const
char
*
deltaAlphaName
;
static
const
char
*
minLengthName
;
signals:
void
referenceChanged
();
protected:
virtual
void
establishConnections
()
override
;
virtual
void
deleteConnections
()
override
;
private:
bool
_connectionsEstablished
;
QGeoCoordinate
_reference
;
QMap
<
QString
,
FactMetaData
*>
_metaDataMap
;
SettingsFact
_distance
;
SettingsFact
_deltaAlpha
;
SettingsFact
_minLength
;
};
}
// namespace routing
src/Wima/Snake/GeneratorBase.cc
View file @
58b2b82d
...
...
@@ -2,12 +2,26 @@
namespace
routing
{
GeneratorBase
::
GeneratorBase
(
QObject
*
parent
)
:
QObject
(
parent
)
{}
GeneratorBase
::
GeneratorBase
(
QObject
*
parent
)
:
GeneratorBase
(
nullptr
,
parent
)
{}
GeneratorBase
::
GeneratorBase
(
std
::
shared_ptr
<
GeneratorData
>
par
,
QObject
*
parent
)
:
QObject
(
parent
)
{}
GeneratorBase
::
GeneratorBase
(
GeneratorBase
::
Data
d
,
QObject
*
parent
)
:
QObject
(
parent
),
_d
(
d
)
{
establishConnections
();
}
GeneratorBase
::~
GeneratorBase
()
{}
GeneratorBase
::
Data
GeneratorBase
::
data
()
const
{
return
_d
;
}
void
GeneratorBase
::
setData
(
const
Data
&
d
)
{
deleteConnections
();
_d
=
d
;
establishConnections
();
}
void
GeneratorBase
::
establishConnections
()
{}
void
GeneratorBase
::
deleteConnections
()
{}
}
// namespace routing
src/Wima/Snake/GeneratorBase.h
View file @
58b2b82d
...
...
@@ -12,9 +12,11 @@ namespace routing {
class
GeneratorBase
:
public
QObject
{
Q_OBJECT
public:
using
Data
=
std
::
shared_ptr
<
WimaPlanData
>
;
using
Generator
=
std
::
function
<
bool
(
snake
::
Transects
&
)
>
;
explicit
GeneratorBase
(
QObject
*
parent
=
nullptr
);
explicit
GeneratorBase
(
Data
d
,
QObject
*
parent
=
nullptr
);
~
GeneratorBase
();
virtual
QString
editorQML
()
=
0
;
...
...
@@ -23,10 +25,18 @@ public:
virtual
QString
name
()
=
0
;
virtual
QString
abbreviation
()
=
0
;
virtual
bool
get
(
const
WimaPlanData
&
data
,
GeneratorBase
&
generator
)
=
0
;
virtual
bool
get
(
Generator
&
generator
)
=
0
;
Data
data
()
const
;
void
setData
(
const
Data
&
d
);
signals:
void
generatorChanged
();
protected:
virtual
void
establishConnections
();
virtual
void
deleteConnections
();
Data
_d
;
};
}
// namespace routing
src/Wima/Snake/GeneratorData.h
deleted
100644 → 0
View file @
06e9bcab
#pragma once
#include <QObject>
class
GeneratorData
:
public
QObject
{
Q_OBJECT
public:
explicit
GeneratorData
(
QObject
*
parent
=
nullptr
);
};
src/Wima/Snake/LinearGenerator.cpp
0 → 100644
View file @
58b2b82d
#include "LinearGenerator.h"
#include "QGCLoggingCategory.h"
QGC_LOGGING_CATEGORY
(
LinearGeneratorLog
,
"LinearGeneratorLog"
)
#define CLIPPER_SCALE 1000000
#include "clipper/clipper.hpp"
#include "SnakeTile.h"
#include "Wima/RoutingThread.h"
namespace
routing
{
bool
linearTransects
(
const
snake
::
FPolygon
&
polygon
,
const
std
::
vector
<
snake
::
FPolygon
>
&
tiles
,
snake
::
Length
distance
,
snake
::
Angle
angle
,
snake
::
Length
minLength
,
snake
::
Transects
&
transects
);
const
char
*
LinearGenerator
::
settingsGroup
=
"LinearGenerator"
;
const
char
*
LinearGenerator
::
distanceName
=
"TransectDistance"
;
const
char
*
LinearGenerator
::
alphaName
=
"Alpha"
;
const
char
*
LinearGenerator
::
minLengthName
=
"MinLength"
;
LinearGenerator
::
LinearGenerator
(
QObject
*
parent
)
:
LinearGenerator
(
nullptr
,
parent
)
{}
LinearGenerator
::
LinearGenerator
(
GeneratorBase
::
Data
d
,
QObject
*
parent
)
:
GeneratorBase
(
d
,
parent
),
_metaDataMap
(
FactMetaData
::
createMapFromJsonFile
(
QStringLiteral
(
":/json/LinearGenerator.SettingsGroup.json"
),
this
)),
_distance
(
settingsGroup
,
_metaDataMap
[
distanceName
]),
_alpha
(
settingsGroup
,
_metaDataMap
[
alphaName
]),
_minLength
(
settingsGroup
,
_metaDataMap
[
minLengthName
])
{
establishConnections
();
}
QString
LinearGenerator
::
editorQML
()
{
return
QStringLiteral
(
"LinearGeneratorEditor.qml"
);
}
QString
LinearGenerator
::
mapVisualQML
()
{
return
QStringLiteral
(
"LinearGeneratorMapVisual.qml"
);
}
QString
LinearGenerator
::
name
()
{
return
QStringLiteral
(
"Linear Generator"
);
}
QString
LinearGenerator
::
abbreviation
()
{
return
QStringLiteral
(
"L. Gen."
);
}
bool
LinearGenerator
::
get
(
Generator
&
generator
)
{
if
(
_d
)
{
if
(
this
->
_d
->
isValid
())
{
// Prepare data.
const
auto
&
origin
=
this
->
_d
->
origin
();
auto
geoPolygon
=
this
->
_d
->
measurementArea
().
coordinateList
();
for
(
auto
&
v
:
geoPolygon
)
{
if
(
v
.
isValid
())
{
v
.
setAltitude
(
0
);
}
else
{
qCWarning
(
LinearGeneratorLog
)
<<
"get(): measurement area invalid."
;
for
(
const
auto
&
w
:
geoPolygon
)
{
qCWarning
(
LinearGeneratorLog
)
<<
w
;
}
return
false
;
}
}
auto
pPolygon
=
std
::
make_shared
<
snake
::
FPolygon
>
();
snake
::
areaToEnu
(
origin
,
geoPolygon
,
*
pPolygon
);
// Progress and tiles.
const
auto
&
progress
=
this
->
_d
->
measurementArea
().
progress
();
const
auto
*
tiles
=
this
->
_d
->
measurementArea
().
tiles
();
auto
pTiles
=
std
::
make_shared
<
std
::
vector
<
snake
::
FPolygon
>>
();
if
(
progress
.
size
()
==
tiles
->
count
())
{
for
(
int
i
=
0
;
i
<
tiles
->
count
();
++
i
)
{
if
(
progress
[
i
]
==
100
)
{
const
auto
*
tile
=
tiles
->
value
<
const
SnakeTile
*>
(
i
);
if
(
tile
!=
nullptr
)
{
snake
::
FPolygon
tileENU
;
snake
::
areaToEnu
(
origin
,
tile
->
coordinateList
(),
tileENU
);
pTiles
->
push_back
(
std
::
move
(
tileENU
));
}
else
{
qCWarning
(
LinearGeneratorLog
)
<<
"get(): progress.size() != tiles->count()."
;
return
false
;
}
}
}
}
else
{
qCWarning
(
LinearGeneratorLog
)
<<
"get(): progress.size() != tiles->count()."
;
return
false
;
}
auto
geoDepot
=
this
->
_d
->
serviceArea
().
depot
();
if
(
!
geoDepot
.
isValid
())
{
qCWarning
(
LinearGeneratorLog
)
<<
"get(): depot invalid."
<<
geoDepot
;
return
false
;
}
snake
::
FPoint
depot
;
snake
::
toENU
(
origin
,
geoDepot
,
depot
);
// Fetch transect parameter.
auto
distance
=
snake
::
Length
(
this
->
_distance
.
rawValue
().
toDouble
()
*
bu
::
si
::
meter
);
auto
minLength
=
snake
::
Length
(
this
->
_minLength
.
rawValue
().
toDouble
()
*
bu
::
si
::
meter
);
auto
alpha
=
snake
::
Angle
(
this
->
_alpha
.
rawValue
().
toDouble
()
*
bu
::
degree
::
degree
);
generator
=
[
depot
,
pPolygon
,
pTiles
,
distance
,
alpha
,
minLength
](
snake
::
Transects
&
transects
)
->
bool
{
bool
value
=
linearTransects
(
*
pPolygon
,
*
pTiles
,
distance
,
alpha
,
minLength
,
transects
);
transects
.
insert
(
transects
.
begin
(),
snake
::
FLineString
{
depot
});
return
value
;
};
return
true
;
}
else
{
qCWarning
(
LinearGeneratorLog
)
<<
"get(): data invalid."
;
return
false
;
}
}
else
{
qCWarning
(
LinearGeneratorLog
)
<<
"get(): data member not set."
;
return
false
;
}
}
Fact
*
LinearGenerator
::
distance
()
{
return
&
_distance
;
}
Fact
*
LinearGenerator
::
alpha
()
{
return
&
_alpha
;
}
Fact
*
LinearGenerator
::
minLength
()
{
return
&
_minLength
;
}
void
LinearGenerator
::
establishConnections
()
{
if
(
this
->
_d
&&
!
this
->
_connectionsEstablished
)
{
connect
(
this
->
_d
.
get
(),
&
WimaPlanData
::
measurementAreaChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
_d
.
get
(),
&
WimaPlanData
::
originChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
&
this
->
_d
->
measurementArea
(),
&
WimaMeasurementAreaData
::
progressChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
&
this
->
_d
->
measurementArea
(),
&
WimaMeasurementAreaData
::
tileDataChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
&
this
->
_d
->
serviceArea
(),
&
WimaServiceAreaData
::
depotChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
distance
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
alpha
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
connect
(
this
->
minLength
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
this
->
_connectionsEstablished
=
true
;
}
}
void
LinearGenerator
::
deleteConnections
()
{
if
(
this
->
_d
&&
this
->
_connectionsEstablished
)
{
disconnect
(
this
->
_d
.
get
(),
&
WimaPlanData
::
measurementAreaChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
this
->
_d
.
get
(),
&
WimaPlanData
::
originChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
&
this
->
_d
->
measurementArea
(),
&
WimaMeasurementAreaData
::
progressChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
&
this
->
_d
->
measurementArea
(),
&
WimaMeasurementAreaData
::
tileDataChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
&
this
->
_d
->
serviceArea
(),
&
WimaServiceAreaData
::
depotChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
this
->
distance
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
this
->
alpha
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
disconnect
(
this
->
minLength
(),
&
Fact
::
rawValueChanged
,
this
,
&
GeneratorBase
::
generatorChanged
);
this
->
_connectionsEstablished
=
false
;
}
}
bool
linearTransects
(
const
snake
::
FPolygon
&
polygon
,
const
std
::
vector
<
snake
::
FPolygon
>
&
tiles
,
snake
::
Length
distance
,
snake
::
Angle
angle
,
snake
::
Length
minLength
,
snake
::
Transects
&
transects
)
{
namespace
tr
=
bg
::
strategy
::
transform
;
auto
s1
=
std
::
chrono
::
high_resolution_clock
::
now
();
// Check preconitions
if
(
polygon
.
outer
().
size
()
>=
3
)
{
// Convert to ENU system.
std
::
string
error
;
// Check validity.
if
(
!
bg
::
is_valid
(
polygon
,
error
))
{
std
::
stringstream
ss
;
ss
<<
bg
::
wkt
(
polygon
);
qCWarning
(
LinearGeneratorLog
)
<<
"linearTransects(): "
"invalid polygon. "
<<
error
.
c_str
()
<<
ss
.
str
().
c_str
();
}
else
{
tr
::
rotate_transformer
<
bg
::
degree
,
double
,
2
,
2
>
rotate
(
angle
.
value
()
*
180
/
M_PI
);
// Rotate polygon by angle and calculate bounding box.
snake
::
FPolygon
polygonENURotated
;
bg
::
transform
(
polygon
.
outer
(),
polygonENURotated
.
outer
(),
rotate
);
snake
::
FBox
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
::
FPoint
v1
{
x0
,
y0
+
i
*
distance
.
value
()};
snake
::
FPoint
v2
{
x1
,
y0
+
i
*
distance
.
value
()};
snake
::
FLineString
transect
;
transect
.
push_back
(
v1
);
transect
.
push_back
(
v2
);
// transform back
snake
::
FLineString
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
;
qCWarning
(
LinearGeneratorLog
)
<<
"linearTransects(): "
<<
ss
.
str
().
c_str
();
return
false
;
}
// Convert measurement area to clipper path.
snake
::
FPolygon
shrinked
;
snake
::
offsetPolygon
(
polygon
,
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
);
// Subtract holes.
if
(
tiles
.
size
()
>
0
)
{
vector
<
ClipperLib
::
Path
>
processedTiles
;
for
(
const
auto
&
tile
:
tiles
)
{
ClipperLib
::
Path
path
;
for
(
const
auto
&
v
:
tile
.
outer
())
{
path
.
push_back
(
ClipperLib
::
IntPoint
{
static_cast
<
ClipperLib
::
cInt
>
(
v
.
get
<
0
>
()
*
CLIPPER_SCALE
),
static_cast
<
ClipperLib
::
cInt
>
(
v
.
get
<
1
>
()
*
CLIPPER_SCALE
)});
}
processedTiles
.
push_back
(
std
::
move
(
path
));
}
clipper
.
Clear
();
for
(
const
auto
&
child
:
clippedTransecs
.
Childs
)
{
clipper
.
AddPath
(
child
->
Contour
,
ClipperLib
::
ptSubject
,
false
);
}
clipper
.
AddPaths
(
processedTiles
,
ClipperLib
::
ptClip
,
true
);
clippedTransecs
.
Clear
();
clipper
.
Execute
(
ClipperLib
::
ctDifference
,
clippedTransecs
,
ClipperLib
::
pftNonZero
,
ClipperLib
::
pftNonZero
);
}
// Extract transects from PolyTree and convert them to BoostLineString
for
(
const
auto
&
child
:
clippedTransecs
.
Childs
)
{
const
auto
&
clipperTransect
=
child
->
Contour
;
snake
::
FPoint
v1
{
static_cast
<
double
>
(
clipperTransect
[
0
].
X
)
/
CLIPPER_SCALE
,
static_cast
<
double
>
(
clipperTransect
[
0
].
Y
)
/
CLIPPER_SCALE
};
snake
::
FPoint
v2
{
static_cast
<
double
>
(
clipperTransect
[
1
].
X
)
/
CLIPPER_SCALE
,
static_cast
<
double
>
(
clipperTransect
[
1
].
Y
)
/
CLIPPER_SCALE
};
snake
::
FLineString
transect
{
v1
,
v2
};
if
(
bg
::
length
(
transect
)
>=
minLength
.
value
())
{
transects
.
push_back
(
transect
);
}
}
if
(
transects
.
size
()
==
0
)
{
std
::
stringstream
ss
;
ss
<<
"Not able to generatetransects. Parameter: minLength = "
<<
minLength
<<
std
::
endl
;
qCWarning
(
LinearGeneratorLog
)
<<
"linearTransects(): "
<<
ss
.
str
().
c_str
();
return
false
;
}
qCWarning
(
LinearGeneratorLog
)
<<
"linearTransects(): time: "
<<
std
::
chrono
::
duration_cast
<
std
::
chrono
::
milliseconds
>
(
std
::
chrono
::
high_resolution_clock
::
now
()
-
s1
)
.
count
()
<<
" ms"
;
return
true
;
}
}
return
false
;
}
}
// namespace routing
src/Wima/Snake/LinearGenerator.h
0 → 100644
View file @
58b2b82d
#include "GeneratorBase.h"
#include <QGeoCoordinate>
namespace
routing
{
class
LinearGenerator
:
public
GeneratorBase
{
Q_OBJECT
public:
LinearGenerator
(
QObject
*
parent
=
nullptr
);
LinearGenerator
(
Data
d
,
QObject
*
parent
=
nullptr
);
Q_PROPERTY
(
Fact
*
distance
READ
distance
CONSTANT
)
Q_PROPERTY
(
Fact
*
alpha
READ
alpha
CONSTANT
)
Q_PROPERTY
(
Fact
*
minLength
READ
minLength
CONSTANT
)
virtual
QString
editorQML
()
override
;
virtual
QString
mapVisualQML
()
override
;
virtual
QString
name
()
override
;
virtual
QString
abbreviation
()
override
;
virtual
bool
get
(
Generator
&
generator
)
override
;
Fact
*
distance
();
Fact
*
alpha
();
Fact
*
minLength
();
static
const
char
*
settingsGroup
;
static
const
char
*
distanceName
;
static
const
char
*
alphaName
;
static
const
char
*
minLengthName
;
protected:
virtual
void
establishConnections
()
override
;
virtual
void
deleteConnections
()
override
;
private:
bool
_connectionsEstablished
;
QMap
<
QString
,
FactMetaData
*>
_metaDataMap
;
SettingsFact
_distance
;
SettingsFact
_alpha
;
SettingsFact
_minLength
;
};
}
// namespace routing
src/Wima/Snake/StandardData.cpp
deleted
100644 → 0
View file @
06e9bcab
#include "StandardData.h"
StandardParameter
::
StandardParameter
()
{}
src/Wima/Snake/StandardData.h
deleted
100644 → 0
View file @
06e9bcab
#pragma once
#include "GeneratorData.h"
namespace
routing
{
class
StandardData
:
public
GeneratorData
{};
}
// namespace routing
src/Wima/Snake/json/CircularGenerator.SettingsGroup.json
0 → 100644
View file @
58b2b82d
[
{
"name"
:
"TransectDistance"
,
"shortDescription"
:
"The distance between transects."
,
"type"
:
"double"
,
"units"
:
"m"
,
"min"
:
0.3
,
"decimalPlaces"
:
1
,
"defaultValue"
:
5.0
},
{
"name"
:
"DeltaAlpha"
,
"shortDescription"
:
"Angle discretisation."
,
"type"
:
"double"
,
"units"
:
"Deg"
,
"min"
:
0.3
,
"max"
:
90
,
"decimalPlaces"
:
1
,
"defaultValue"
:
5.0
},
{
"name"
:
"MinLength"
,
"shortDescription"
:
"The minimal transect length."
,
"type"
:
"double"
,
"units"
:
"m"
,
"min"
:
0.3
,
"decimalPlaces"
:
1
,
"defaultValue"
:
5.0
}
]
src/Wima/Snake/json/LinearGenerator.SettingsGroup.json
0 → 100644
View file @
58b2b82d
[
{
"name"
:
"TransectDistance"
,
"shortDescription"
:
"The distance between transects."
,
"type"
:
"double"
,
"units"
:
"m"
,
"min"
:
0.3
,
"decimalPlaces"
:
1
,
"defaultValue"
:
5.0
},
{
"name"
:
"Alpha"
,
"shortDescription"
:
"Transect angle."
,
"type"
:
"double"
,
"units"
:
"Deg"
,
"min"
:
0
,
"max"
:
180
,
"decimalPlaces"
:
1
,
"defaultValue"
:
0.0
},
{
"name"
:
"MinLength"
,
"shortDescription"
:
"The minimal transect length."
,
"type"
:
"double"
,
"units"
:
"m"
,
"min"
:
0.3
,
"decimalPlaces"
:
1
,
"defaultValue"
:
5.0
}
]
src/Wima/WimaController.cc
View file @
58b2b82d
...
...
@@ -230,74 +230,53 @@ void WimaController::planDataChangedHandler() {
_serviceArea
=
WimaServiceAreaData
();
_corridor
=
WimaCorridorData
();
_joinedArea
=
WimaJoinedAreaData
();
_planDataValid
=
false
;
emit
visualItemsChanged
();
emit
missionItemsChanged
();
emit
waypointPathChanged
();
_planDataValid
=
false
;
// Extract areas.
auto
planData
=
WimaBridge
::
instance
()
->
planData
();
// extract list with WimaAreas
QList
<
const
WimaAreaData
*>
areaList
=
planData
.
areaList
();
int
areaCounter
=
0
;
const
int
numAreas
=
4
;
// extract only numAreas Areas, if there are more
// they are invalid and ignored
for
(
int
i
=
0
;
i
<
areaList
.
size
();
i
++
)
{
const
WimaAreaData
*
areaData
=
areaList
[
i
];
if
(
areaData
->
type
()
==
WimaServiceAreaData
::
typeString
)
{
// is it a service area?
_serviceArea
=
*
qobject_cast
<
const
WimaServiceAreaData
*>
(
areaData
);
areaCounter
++
;
_areas
.
append
(
&
_serviceArea
);
continue
;
}
if
(
areaData
->
type
()
==
WimaMeasurementAreaData
::
typeString
)
{
// is it a measurement area?
_measurementArea
=
*
qobject_cast
<
const
WimaMeasurementAreaData
*>
(
areaData
);
areaCounter
++
;
// Measurement Area.
if
(
planData
.
measurementArea
().
coordinateList
().
size
()
>=
3
)
{
_measurementArea
=
planData
.
measurementArea
();
_areas
.
append
(
&
_measurementArea
);
continue
;
}
if
(
areaData
->
type
()
==
WimaCorridorData
::
typeString
)
{
// is it a corridor?
_corridor
=
*
qobject_cast
<
const
WimaCorridorData
*>
(
areaData
);
areaCounter
++
;
//_visualItems.append(&_corridor); // not needed
// Service Area.
if
(
planData
.
serviceArea
().
coordinateList
().
size
()
>=
3
)
{
_serviceArea
=
planData
.
serviceArea
();
_areas
.
append
(
&
_serviceArea
);
continue
;
}
_WMSettings
.
setHomePosition
(
QGeoCoordinate
(
_serviceArea
.
depot
().
latitude
(),
_serviceArea
.
depot
().
longitude
(),
0
));
if
(
areaData
->
type
()
==
WimaJoinedAreaData
::
typeString
)
{
// is it a corridor?
_joinedArea
=
*
qobject_cast
<
const
WimaJoinedAreaData
*>
(
areaData
);
areaCounter
++
;
// Joined Area.
if
(
planData
.
joinedArea
().
coordinateList
().
size
()
>=
3
)
{
_joinedArea
=
planData
.
joinedArea
();
_areas
.
append
(
&
_joinedArea
);
continue
;
}
_planDataValid
=
true
;
if
(
areaCounter
>=
numAreas
)
break
;
// Corridor.
if
(
planData
.
corridor
().
coordinateList
().
size
()
>=
3
)
{
_corridor
=
planData
.
corridor
();
}
}
}
if
(
areaCounter
!=
numAreas
)
{
Q_ASSERT
(
false
);
return
;
}
if
(
_planDataValid
)
{
emit
visualItemsChanged
();
_WMSettings
.
setHomePosition
(
QGeoCoordinate
(
_serviceArea
.
depot
().
latitude
(),
_serviceArea
.
depot
().
longitude
(),
0
));
_planDataValid
=
true
;
}
else
{
_areas
.
clear
();
_measurementArea
=
WimaMeasurementAreaData
();
_serviceArea
=
WimaServiceAreaData
();
_corridor
=
WimaCorridorData
();
_joinedArea
=
WimaJoinedAreaData
();
}
}
void
WimaController
::
progressChangedHandler
()
{
...
...
src/Wima/WimaPlanData.cc
View file @
58b2b82d
#include "WimaPlanData.h"
enum
Signal
{
measuremtAreaChanged
,
serviceAreaChanged
,
joinedAreaChanged
,
corridorChanged
,
};
WimaPlanData
::
WimaPlanData
(
QObject
*
parent
)
:
QObject
(
parent
),
_editing
(
false
)
{}
WimaPlanData
::
WimaPlanData
(
QObject
*
parent
)
:
QObject
(
parent
)
{}
WimaPlanData
::
WimaPlanData
(
const
WimaPlanData
&
other
,
QObject
*
parent
)
:
QObject
(
parent
)
,
_editing
(
false
)
{
:
QObject
(
parent
)
{
*
this
=
other
;
}
WimaPlanData
&
WimaPlanData
::
operator
=
(
const
WimaPlanData
&
other
)
{
this
->
_measurementArea
=
other
.
_measurementArea
;
this
->
_serviceArea
=
other
.
_serviceArea
;
this
->
_joinedArea
=
other
.
_joinedArea
;
this
->
_corridor
=
other
.
_corridor
;
this
->
set
(
other
.
measurementArea
())
;
this
->
set
(
other
.
serviceArea
())
;
this
->
set
(
other
.
joinedArea
())
;
this
->
set
(
other
.
corridor
())
;
return
*
this
;
}
...
...
@@ -27,36 +19,44 @@ WimaPlanData &WimaPlanData::operator=(const WimaPlanData &other) {
void
WimaPlanData
::
set
(
const
WimaJoinedAreaData
&
areaData
)
{
if
(
_joinedArea
!=
areaData
)
{
_joinedArea
=
areaData
;
emit
J
oinedAreaChanged
();
emit
j
oinedAreaChanged
();
}
}
void
WimaPlanData
::
set
(
const
WimaServiceAreaData
&
areaData
)
{
if
(
_serviceArea
!=
areaData
)
{
_serviceArea
=
areaData
;
emit
S
erviceAreaChanged
();
emit
s
erviceAreaChanged
();
}
}
void
WimaPlanData
::
set
(
const
WimaCorridorData
&
areaData
)
{
if
(
_corridor
!=
areaData
)
{
_corridor
=
areaData
;
emit
C
orridorChanged
();
emit
c
orridorChanged
();
}
}
void
WimaPlanData
::
set
(
const
WimaMeasurementAreaData
&
areaData
)
{
if
(
_measurementArea
!=
areaData
)
{
_measurementArea
=
areaData
;
emitMeasurementAreaChanged
();
emit
measurementAreaChanged
();
if
(
_measurementArea
.
coordinateList
().
size
()
>
0
)
{
setOrigin
(
_measurementArea
.
coordinateList
().
first
());
}
else
{
setOrigin
(
QGeoCoordinate
());
}
}
}
void
WimaPlanData
::
clear
()
{
_joinedArea
=
WimaJoinedAreaData
();
_serviceArea
=
WimaServiceAreaData
();
_corridor
=
WimaCorridorData
();
_measurementArea
=
WimaMeasurementAreaData
();
void
WimaPlanData
::
clear
()
{
*
this
=
WimaPlanData
();
}
QGeoCoordinate
WimaPlanData
::
origin
()
{
return
_origin
;
}
bool
WimaPlanData
::
isValid
()
{
return
_measurementArea
.
coordinateList
().
size
()
>=
3
&&
_serviceArea
.
coordinateList
().
size
()
>=
3
&&
_origin
.
isValid
();
}
const
WimaJoinedAreaData
&
WimaPlanData
::
joinedArea
()
const
{
...
...
@@ -75,24 +75,14 @@ const WimaMeasurementAreaData &WimaPlanData::measurementArea() const {
return
this
->
_measurementArea
;
}
void
WimaPlanData
::
startEditing
()
{
if
(
!
this
->
_editing
)
{
this
->
_editing
=
true
;
}
}
WimaJoinedAreaData
&
WimaPlanData
::
joinedArea
()
{
return
this
->
_joinedArea
;
}
void
WimaPlanData
::
stopEditing
()
{
if
(
this
->
_editing
)
{
this
->
_editing
=
false
;
for
(
auto
&
s
:
this
->
_queuedSignals
)
{
s
.
second
();
}
this
->
_queuedSignals
.
clear
();
}
}
WimaServiceAreaData
&
WimaPlanData
::
serviceArea
()
{
return
this
->
_serviceArea
;
}
WimaPlanData
::
Guard
WimaPlanData
::
guard
()
{
return
Guard
(
std
::
bind
(
&
WimaPlanData
::
stopEditing
,
this
));
WimaCorridorData
&
WimaPlanData
::
corridor
()
{
return
this
->
_corridor
;
}
WimaMeasurementAreaData
&
WimaPlanData
::
measurementArea
()
{
return
this
->
_measurementArea
;
}
bool
WimaPlanData
::
operator
==
(
const
WimaPlanData
&
other
)
const
{
...
...
@@ -105,42 +95,9 @@ bool WimaPlanData::operator!=(const WimaPlanData &other) const {
return
!
(
*
this
==
other
);
}
void
WimaPlanData
::
emitJoinedAreaChanged
()
{
if
(
!
this
->
_editing
)
{
emit
joinedAreaChanged
();
}
else
{
this
->
_queuedSignals
.
insert
(
std
::
make_pair
(
Signal
::
joinedAreaChanged
,
std
::
bind
(
&
WimaPlanData
::
joinedAreaChanged
,
this
)));
}
}
void
WimaPlanData
::
emitMeasurementAreaChanged
()
{
if
(
!
this
->
_editing
)
{
emit
measurementAreaChanged
();
}
else
{
this
->
_queuedSignals
.
insert
(
std
::
make_pair
(
Signal
::
measuremtAreaChanged
,
std
::
bind
(
&
WimaPlanData
::
measurementAreaChanged
,
this
)));
}
}
void
WimaPlanData
::
emitServiceAreaChanged
()
{
if
(
!
this
->
_editing
)
{
emit
serviceAreaChanged
();
}
else
{
this
->
_queuedSignals
.
insert
(
std
::
make_pair
(
Signal
::
serviceAreaChanged
,
std
::
bind
(
&
WimaPlanData
::
serviceAreaChanged
,
this
)));
}
}
void
WimaPlanData
::
emitCorridorChanged
()
{
if
(
!
this
->
_editing
)
{
emit
corridorChanged
();
}
else
{
this
->
_queuedSignals
.
insert
(
std
::
make_pair
(
Signal
::
corridorChanged
,
std
::
bind
(
&
WimaPlanData
::
corridorChanged
,
this
)));
void
WimaPlanData
::
setOrigin
(
const
QGeoCoordinate
&
origin
)
{
if
(
this
->
_origin
!=
origin
)
{
this
->
_origin
=
origin
;
emit
originChanged
();
}
}
src/Wima/WimaPlanData.h
View file @
58b2b82d
#pragma once
#include <functional>
#include <map>
#include <QGeoCoordinate>
#include <QObject>
...
...
@@ -16,15 +13,6 @@
class
WimaPlanData
:
public
QObject
{
Q_OBJECT
public:
class
Guard
{
public:
Guard
(
std
::
function
<
void
(
void
)
>
fun
)
:
fun_
(
fun
)
{}
~
Guard
()
{
fun_
();
}
private:
std
::
function
<
void
(
void
)
>
fun_
;
};
WimaPlanData
(
QObject
*
parent
=
nullptr
);
WimaPlanData
(
const
WimaPlanData
&
other
,
QObject
*
parent
=
nullptr
);
WimaPlanData
&
operator
=
(
const
WimaPlanData
&
other
);
...
...
@@ -41,9 +29,13 @@ public:
const
WimaCorridorData
&
corridor
()
const
;
const
WimaMeasurementAreaData
&
measurementArea
()
const
;
void
startEditing
();
void
stopEditing
();
Guard
guard
();
WimaJoinedAreaData
&
joinedArea
();
WimaServiceAreaData
&
serviceArea
();
WimaCorridorData
&
corridor
();
WimaMeasurementAreaData
&
measurementArea
();
QGeoCoordinate
origin
();
bool
isValid
();
bool
operator
==
(
const
WimaPlanData
&
other
)
const
;
bool
operator
!=
(
const
WimaPlanData
&
other
)
const
;
...
...
@@ -53,19 +45,15 @@ signals:
void
serviceAreaChanged
();
void
corridorChanged
();
void
measurementAreaChanged
();
void
originChanged
();
private:
void
emitJoinedAreaChanged
();
void
emitServiceAreaChanged
();
void
emitCorridorChanged
();
void
emitMeasurementAreaChanged
();
void
setOrigin
(
const
QGeoCoordinate
&
origin
);
WimaJoinedAreaData
_joinedArea
;
WimaServiceAreaData
_serviceArea
;
WimaCorridorData
_corridor
;
WimaMeasurementAreaData
_measurementArea
;
std
::
map
<
int
,
std
::
function
<
void
(
void
)
>>
_queuedSignals
;
bool
_editing
;
QGeoCoordinate
_origin
;
};
src/Wima/WimaPlaner.cc
View file @
58b2b82d
...
...
@@ -955,10 +955,10 @@ void WimaPlaner::setInteractive() {
bool
WimaPlaner
::
toPlanData
(
WimaPlanData
&
planData
)
{
// store areas
planData
.
append
(
WimaMeasurementAreaData
(
_measurementArea
));
planData
.
append
(
WimaServiceAreaData
(
_serviceArea
));
planData
.
append
(
WimaCorridorData
(
_corridor
));
planData
.
append
(
WimaJoinedAreaData
(
_joinedArea
));
planData
.
set
(
WimaMeasurementAreaData
(
_measurementArea
));
planData
.
set
(
WimaServiceAreaData
(
_serviceArea
));
planData
.
set
(
WimaCorridorData
(
_corridor
));
planData
.
set
(
WimaJoinedAreaData
(
_joinedArea
));
return
true
;
}
...
...
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