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
a0c951cb
Commit
a0c951cb
authored
Sep 15, 2020
by
Valentin Platzgummer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
234
parent
0510d157
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
5600 additions
and
743 deletions
+5600
-743
KlingenbachTest.wima
Paths/KlingenbachTest.wima
+5144
-253
WimaMeasurementArea.cc
src/Wima/Geometry/WimaMeasurementArea.cc
+146
-71
WimaMeasurementArea.h
src/Wima/Geometry/WimaMeasurementArea.h
+31
-9
WimaMeasurementArea.SettingsGroup.json
...Wima/Geometry/json/WimaMeasurementArea.SettingsGroup.json
+35
-11
SnakeThread.cc
src/Wima/Snake/SnakeThread.cc
+92
-104
SnakeTile.cpp
src/Wima/Snake/SnakeTile.cpp
+1
-1
SnakeTile.h
src/Wima/Snake/SnakeTile.h
+1
-1
snake.cpp
src/Wima/Snake/snake.cpp
+75
-186
snake.h
src/Wima/Snake/snake.h
+28
-91
WimaMeasurementAreaEditor.qml
src/WimaView/WimaMeasurementAreaEditor.qml
+47
-16
No files found.
Paths/KlingenbachTest.wima
View file @
a0c951cb
This source diff could not be displayed because it is too large. You can
view the blob
instead.
src/Wima/Geometry/WimaMeasurementArea.cc
View file @
a0c951cb
#include "WimaMeasurementArea.h"
#include "SnakeTile.h"
#include "snake.h"
#include <boost/units/systems/si.hpp>
const
char
*
WimaMeasurementArea
::
settingsGroup
=
"MeasurementArea"
;
const
char
*
WimaMeasurementArea
::
bottomLayerAltitudeName
=
"BottomLayerAltitude"
;
const
char
*
WimaMeasurementArea
::
numberOfLayersName
=
"NumberOfLayers"
;
const
char
*
WimaMeasurementArea
::
layerDistanceName
=
"LayerDistance"
;
const
char
*
WimaMeasurementArea
::
tileHeightName
=
"TileHeight"
;
const
char
*
WimaMeasurementArea
::
tileWidthName
=
"TileWidth"
;
const
char
*
WimaMeasurementArea
::
minTileAreaName
=
"MinTileArea"
;
const
char
*
WimaMeasurementArea
::
transectDistanceName
=
"TransectDistance"
;
const
char
*
WimaMeasurementArea
::
minTransectLengthName
=
"MinTransectLength"
;
const
char
*
WimaMeasurementArea
::
showTilesName
=
"ShowTiles"
;
const
char
*
WimaMeasurementArea
::
WimaMeasurementAreaName
=
"Measurement Area"
;
WimaMeasurementArea
::
WimaMeasurementArea
(
QObject
*
parent
)
...
...
@@ -12,15 +18,21 @@ WimaMeasurementArea::WimaMeasurementArea(QObject *parent)
_metaDataMap
(
FactMetaData
::
createMapFromJsonFile
(
QStringLiteral
(
":/json/WimaMeasurementArea.SettingsGroup.json"
),
this
/* QObject parent */
)),
_bottomLayerAltitude
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
bottomLayerAltitudeName
],
this
/* QObject parent */
)),
_numberOfLayers
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
numberOfLayersName
],
this
/* QObject parent */
)),
_layerDistance
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
layerDistanceName
],
this
/* QObject parent */
))
{
_tileHeight
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
tileHeightName
],
this
/* QObject parent */
)),
_tileWidth
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
tileWidthName
],
this
/* QObject parent */
)),
_minTileArea
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
minTileAreaName
],
this
/* QObject parent */
)),
_transectDistance
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
transectDistanceName
],
this
/* QObject parent */
)),
_minTransectLength
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
minTransectLengthName
],
this
/* QObject parent */
)),
_showTiles
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
showTilesName
],
this
/* QObject parent */
)),
_calculating
(
false
)
{
init
();
}
...
...
@@ -30,15 +42,21 @@ WimaMeasurementArea::WimaMeasurementArea(const WimaMeasurementArea &other,
_metaDataMap
(
FactMetaData
::
createMapFromJsonFile
(
QStringLiteral
(
":/json/WimaMeasurementArea.SettingsGroup.json"
),
this
/* QObject parent */
)),
_bottomLayerAltitude
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
bottomLayerAltitudeName
],
this
/* QObject parent */
)),
_numberOfLayers
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
numberOfLayersName
],
this
/* QObject parent */
)),
_layerDistance
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
layerDistanceName
],
this
/* QObject parent */
))
{
_tileHeight
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
tileHeightName
],
this
/* QObject parent */
)),
_tileWidth
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
tileWidthName
],
this
/* QObject parent */
)),
_minTileArea
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
minTileAreaName
],
this
/* QObject parent */
)),
_transectDistance
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
transectDistanceName
],
this
/* QObject parent */
)),
_minTransectLength
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
minTransectLengthName
],
this
/* QObject parent */
)),
_showTiles
(
SettingsFact
(
settingsGroup
,
_metaDataMap
[
showTilesName
],
this
/* QObject parent */
)),
_calculating
(
false
)
{
init
();
}
...
...
@@ -54,6 +72,10 @@ operator=(const WimaMeasurementArea &other) {
return
*
this
;
}
WimaMeasurementArea
::~
WimaMeasurementArea
()
{
this
->
_tiles
.
clearAndDeleteContents
();
}
QString
WimaMeasurementArea
::
mapVisualQML
()
const
{
return
"WimaMeasurementAreaMapVisual.qml"
;
}
...
...
@@ -64,11 +86,24 @@ QString WimaMeasurementArea::editorQML() const {
Fact
*
WimaMeasurementArea
::
tileHeight
()
{
return
&
_tileHeight
;
}
Fact
*
WimaMeasurementArea
::
tileWidth
()
{
return
&
_tileWidth
;
}
Fact
*
WimaMeasurementArea
::
minTileArea
()
{
return
&
_minTileArea
;
}
Fact
*
WimaMeasurementArea
::
transectDistance
()
{
return
&
_transectDistance
;
}
Fact
*
WimaMeasurementArea
::
minTransectLength
()
{
return
&
_minTransectLength
;
}
Fact
*
WimaMeasurementArea
::
showTiles
()
{
return
&
_showTiles
;
}
void
WimaMeasurementArea
::
saveToJson
(
QJsonObject
&
json
)
{
this
->
WimaArea
::
saveToJson
(
json
);
json
[
bottomLayerAltitudeName
]
=
_bottomLayerAltitude
.
rawValue
().
toDouble
();
json
[
numberOfLayersName
]
=
_numberOfLayers
.
rawValue
().
toInt
();
json
[
layerDistanceName
]
=
_layerDistance
.
rawValue
().
toDouble
();
json
[
tileHeightName
]
=
_tileHeight
.
rawValue
().
toDouble
();
json
[
tileWidthName
]
=
_tileWidth
.
rawValue
().
toDouble
();
json
[
minTileAreaName
]
=
_minTileArea
.
rawValue
().
toDouble
();
json
[
transectDistanceName
]
=
_transectDistance
.
rawValue
().
toDouble
();
json
[
minTransectLengthName
]
=
_minTransectLength
.
rawValue
().
toDouble
();
json
[
showTilesName
]
=
_showTiles
.
rawValue
().
toBool
();
json
[
areaTypeName
]
=
WimaMeasurementAreaName
;
}
...
...
@@ -77,79 +112,119 @@ bool WimaMeasurementArea::loadFromJson(const QJsonObject &json,
if
(
this
->
WimaArea
::
loadFromJson
(
json
,
errorString
))
{
bool
retVal
=
true
;
if
(
json
.
contains
(
bottomLayerAltitudeName
)
&&
json
[
bottomLayerAltitudeName
].
isDouble
())
{
_bottomLayerAltitude
.
setRawValue
(
json
[
bottomLayerAltitudeName
].
toDouble
());
if
(
json
.
contains
(
tileHeightName
)
&&
json
[
tileHeightName
].
isDouble
())
{
_tileHeight
.
setRawValue
(
json
[
tileHeightName
].
toDouble
());
}
else
{
errorString
.
append
(
tr
(
"Could not load
Bottom Layer Altitude
!
\n
"
));
errorString
.
append
(
tr
(
"Could not load
tile height
!
\n
"
));
retVal
=
false
;
}
if
(
json
.
contains
(
numberOfLayersName
)
&&
json
[
numberOfLayersName
].
isDouble
())
{
_numberOfLayers
.
setRawValue
(
json
[
numberOfLayersName
].
toInt
());
if
(
json
.
contains
(
tileWidthName
)
&&
json
[
tileWidthName
].
isDouble
())
{
_tileHeight
.
setRawValue
(
json
[
tileWidthName
].
toDouble
());
}
else
{
errorString
.
append
(
tr
(
"Could not load
Number of Layers
!
\n
"
));
errorString
.
append
(
tr
(
"Could not load
tile width
!
\n
"
));
retVal
=
false
;
}
if
(
json
.
contains
(
layerDistanceName
)
&&
json
[
layerDistanceName
].
isDouble
())
{
_layerDistance
.
setRawValue
(
json
[
layerDistanceName
].
toDouble
());
if
(
json
.
contains
(
minTileAreaName
)
&&
json
[
minTileAreaName
].
isDouble
())
{
_tileHeight
.
setRawValue
(
json
[
minTileAreaName
].
toDouble
());
}
else
{
errorString
.
append
(
tr
(
"Could not load
Layer Distance
!
\n
"
));
errorString
.
append
(
tr
(
"Could not load
minimal tile area
!
\n
"
));
retVal
=
false
;
}
if
(
json
.
contains
(
transectDistanceName
)
&&
json
[
transectDistanceName
].
isDouble
())
{
_tileHeight
.
setRawValue
(
json
[
transectDistanceName
].
toDouble
());
}
else
{
errorString
.
append
(
tr
(
"Could not load transect distance!
\n
"
));
retVal
=
false
;
}
if
(
json
.
contains
(
minTransectLengthName
)
&&
json
[
minTransectLengthName
].
isDouble
())
{
_tileHeight
.
setRawValue
(
json
[
minTransectLengthName
].
toDouble
());
}
else
{
errorString
.
append
(
tr
(
"Could not load minimal transect length!
\n
"
));
retVal
=
false
;
}
if
(
json
.
contains
(
showTilesName
)
&&
json
[
showTilesName
].
isBool
())
{
_tileHeight
.
setRawValue
(
json
[
showTilesName
].
toDouble
());
}
else
{
errorString
.
append
(
tr
(
"Could not load show tiles !
\n
"
));
retVal
=
false
;
}
return
retVal
;
}
else
{
return
false
;
}
}
void
WimaMeasurementArea
::
setBottomLayerAltitude
(
double
altitude
)
{
if
(
!
qFuzzyCompare
(
_bottomLayerAltitude
.
rawValue
().
toDouble
(),
altitude
))
{
_bottomLayerAltitude
.
setRawValue
(
altitude
);
emit
bottomLayerAltitudeChanged
();
void
WimaMeasurementArea
::
doUpdate
()
{
using
namespace
snake
;
using
namespace
boost
::
units
;
#ifdef SNAKE_SHOW_TIME
auto
start
=
std
::
chrono
::
high_resolution_clock
::
now
();
#endif
auto
polygon
=
this
->
coordinateList
();
for
(
auto
&
v
:
polygon
)
{
v
.
setAltitude
(
0
);
}
}
void
WimaMeasurementArea
::
setNumberOfLayers
(
double
numLayers
)
{
if
(
!
qFuzzyCompare
(
_numberOfLayers
.
rawValue
().
toDouble
(),
numLayers
))
{
_numberOfLayers
.
setRawValue
(
numLayers
);
emit
numberOfLayersChanged
();
if
(
polygon
.
size
()
>
3
)
{
QGeoCoordinate
origin
=
polygon
.
first
();
BoostPolygon
polygonENU
;
areaToEnu
(
origin
,
polygon
,
polygonENU
);
Length
height
=
this
->
_tileHeight
.
rawValue
().
toDouble
()
*
si
::
meter
;
Length
width
=
this
->
_tileWidth
.
rawValue
().
toDouble
()
*
si
::
meter
;
Area
minArea
=
this
->
_minTileArea
.
rawValue
().
toDouble
()
*
si
::
meter
*
si
::
meter
;
std
::
vector
<
BoostPolygon
>
tilesENU
;
BoundingBox
bbox
;
std
::
string
errorString
;
if
(
snake
::
tiles
(
polygonENU
,
height
,
width
,
minArea
,
tilesENU
,
bbox
,
errorString
))
{
this
->
_tiles
.
clearAndDeleteContents
();
for
(
const
auto
&
t
:
tilesENU
)
{
auto
geoTile
=
new
SnakeTile
(
&
this
->
_tiles
);
for
(
const
auto
&
v
:
t
.
outer
())
{
QGeoCoordinate
geoVertex
;
fromENU
(
origin
,
v
,
geoVertex
);
geoTile
->
push_back
(
geoVertex
);
}
this
->
_tiles
.
append
(
geoTile
);
}
}
}
#ifdef SNAKE_SHOW_TIME
qDebug
()
<<
"WimaMeasurementArea::doUpdate execution time: "
<<
std
::
chrono
::
duration_cast
<
std
::
chrono
::
milliseconds
>
(
std
::
chrono
::
high_resolution_clock
::
now
()
-
start
)
.
count
()
<<
" ms"
;
#endif
}
void
WimaMeasurementArea
::
setLayerDistance
(
double
layerDistance
)
{
if
(
!
qFuzzyCompare
(
_layerDistance
.
rawValue
().
toDouble
(),
layerDistance
))
{
_layerDistance
.
setRawValue
(
layerDistance
);
emit
layerDistanceChanged
();
void
WimaMeasurementArea
::
deferUpdate
()
{
if
(
this
->
_timer
.
isActive
())
{
this
->
_timer
.
stop
();
}
}
void
print
(
const
WimaMeasurementArea
&
area
)
{
QString
message
;
print
(
area
,
message
);
qWarning
()
<<
message
;
}
void
print
(
const
WimaMeasurementArea
&
area
,
QString
outputStr
)
{
print
(
static_cast
<
const
WimaArea
&>
(
area
),
outputStr
);
outputStr
.
append
(
QString
(
"Bottom Layer Altitude: %1
\n
"
)
.
arg
(
area
.
_bottomLayerAltitude
.
rawValue
().
toDouble
()));
outputStr
.
append
(
QString
(
"Number of Layers: %1
\n
"
)
.
arg
(
area
.
_numberOfLayers
.
rawValue
().
toInt
()));
outputStr
.
append
(
QString
(
"Layer Distance: %1
\n
"
)
.
arg
(
area
.
_layerDistance
.
rawValue
().
toDouble
()));
this
->
_timer
.
start
(
100
);
}
void
WimaMeasurementArea
::
init
()
{
this
->
setObjectName
(
WimaMeasurementAreaName
);
connect
(
&
this
->
_tileHeight
,
&
Fact
::
rawValueChanged
,
this
,
&
WimaMeasurementArea
::
deferUpdate
);
connect
(
&
this
->
_tileWidth
,
&
Fact
::
rawValueChanged
,
this
,
&
WimaMeasurementArea
::
deferUpdate
);
connect
(
&
this
->
_minTileArea
,
&
Fact
::
rawValueChanged
,
this
,
&
WimaMeasurementArea
::
deferUpdate
);
connect
(
this
,
&
WimaArea
::
pathChanged
,
this
,
&
WimaMeasurementArea
::
deferUpdate
);
this
->
_timer
.
setSingleShot
(
true
);
connect
(
&
this
->
_timer
,
&
QTimer
::
timeout
,
this
,
&
WimaMeasurementArea
::
doUpdate
);
}
/*!
...
...
src/Wima/Geometry/WimaMeasurementArea.h
View file @
a0c951cb
#pragma once
#include "QScopedPointer"
#include <QObject>
#include <QTimer>
#include "WimaArea.h"
...
...
@@ -14,14 +14,25 @@ public:
WimaMeasurementArea
(
const
WimaMeasurementArea
&
other
,
QObject
*
parent
=
nullptr
);
WimaMeasurementArea
&
operator
=
(
const
WimaMeasurementArea
&
other
);
~
WimaMeasurementArea
();
Q_PROPERTY
(
Fact
*
borderPolygonOffset
READ
borderPolygonOffsetFact
CONSTANT
)
Q_PROPERTY
(
Fact
*
tileHeight
READ
tileHeight
CONSTANT
)
Q_PROPERTY
(
Fact
*
tileWidth
READ
tileWidth
CONSTANT
)
Q_PROPERTY
(
Fact
*
minTileArea
READ
minTileArea
CONSTANT
)
Q_PROPERTY
(
Fact
*
transectDistance
READ
transectDistance
CONSTANT
)
Q_PROPERTY
(
Fact
*
minTransectLength
READ
minTransectLength
CONSTANT
)
Q_PROPERTY
(
Fact
*
showTiles
READ
showTiles
CONSTANT
)
// Overrides from WimaPolygon
QString
mapVisualQML
(
void
)
const
{
return
"WimaMeasurementAreaMapVisual.qml"
;
}
QString
editorQML
(
void
)
const
{
return
"WimaMeasurementAreaEditor.qml"
;
}
QString
mapVisualQML
(
void
)
const
;
QString
editorQML
(
void
)
const
;
Fact
*
tileHeight
();
Fact
*
tileWidth
();
Fact
*
minTileArea
();
Fact
*
transectDistance
();
Fact
*
minTransectLength
();
Fact
*
showTiles
();
// Member Methodes
void
saveToJson
(
QJsonObject
&
json
);
...
...
@@ -36,14 +47,19 @@ public:
static
const
char
*
tileHeightName
;
static
const
char
*
tileWidthName
;
static
const
char
*
minTileAreaName
;
static
const
char
*
transcetDistanceName
;
static
const
char
*
minTransectLength
;
static
const
char
*
transectDistanceName
;
static
const
char
*
minTransectLengthName
;
static
const
char
*
showTilesName
;
static
const
char
*
WimaMeasurementAreaName
;
signals:
public
slots
:
private
slots
:
void
doUpdate
();
void
deferUpdate
();
private:
// Member Methodes
void
init
();
...
...
@@ -51,9 +67,15 @@ private:
// Members
QMap
<
QString
,
FactMetaData
*>
_metaDataMap
;
SettingsFact
_tileWidth
;
SettingsFact
_tileHeight
;
SettingsFact
_tileWidth
;
SettingsFact
_minTileArea
;
SettingsFact
_transectDistance
;
SettingsFact
_minTransectLength
;
SettingsFact
_showTiles
;
// Tile stuff.
QTimer
_timer
;
std
::
atomic_bool
_calculating
;
QmlObjectListModel
_tiles
;
};
src/Wima/Geometry/json/WimaMeasurementArea.SettingsGroup.json
View file @
a0c951cb
[
{
"name"
:
"
BottomLayerAltitude
"
,
"shortDescription"
:
"The
distance between the terrain and the first layer of the measurement path.
"
,
"name"
:
"
TileHeight
"
,
"shortDescription"
:
"The
height of a tile
"
,
"type"
:
"double"
,
"units"
:
"m"
,
"min"
:
1
,
"min"
:
0.3
,
"decimalPlaces"
:
2
,
"defaultValue"
:
5
},
{
"name"
:
"
NumberOfLayers
"
,
"shortDescription"
:
"The
number of layers.
"
,
"type"
:
"
uint32
"
,
"name"
:
"
TileWidth
"
,
"shortDescription"
:
"The
height of a tile
"
,
"type"
:
"
double
"
,
"units"
:
"m"
,
"min"
:
1
,
"decimalPlaces"
:
0
,
"defaultValue"
:
1
"min"
:
0.3
,
"decimalPlaces"
:
2
,
"defaultValue"
:
5
},
{
"name"
:
"LayerDistance"
,
"shortDescription"
:
"Specify the time between each photo"
,
"name"
:
"MinTileArea"
,
"shortDescription"
:
"The minimal allowed area of a tile"
,
"type"
:
"double"
,
"units"
:
"m^2"
,
"min"
:
0
,
"decimalPlaces"
:
2
,
"defaultValue"
:
5
},
{
"name"
:
"TransectDistance"
,
"shortDescription"
:
"The transect distance"
,
"type"
:
"double"
,
"units"
:
"m"
,
"min"
:
0.3
,
"decimalPlaces"
:
2
,
"defaultValue"
:
2
},
{
"name"
:
"MinTransectLength"
,
"shortDescription"
:
"The minimal transect length"
,
"type"
:
"double"
,
"units"
:
"m"
,
"min"
:
0
,
"decimalPlaces"
:
2
,
"defaultValue"
:
1
},
{
"name"
:
"ShowTiles"
,
"shortDescription"
:
"Show tiles"
,
"type"
:
"bool"
,
"defaultValue"
:
true
},
{
"name"
:
"BorderPolygonOffset"
,
"shortDescription"
:
"The distance between the measurement area and it's enclosing polygon"
,
...
...
src/Wima/Snake/SnakeThread.cc
View file @
a0c951cb
...
...
@@ -97,7 +97,12 @@ public:
bool
doTopicServiceSetup
();
// Internal data.
snake
::
Scenario
scenario
;
snake
::
BoostPolygon
mAreaENU
;
snake
::
BoostPolygon
sAreaENU
;
snake
::
BoostPolygon
corridorENU
;
snake
::
BoostPolygon
jAreaENU
;
std
::
vector
<
snake
::
BoostPolygon
>
tilesENU
;
QGeoCoordinate
ENUOrigin
;
SnakeThread
*
parent
;
// Input
...
...
@@ -225,36 +230,35 @@ void SnakeThread::setLineDistance(Length lineDistance) {
Area
SnakeThread
::
minTileArea
()
const
{
SharedLock
lk
(
this
->
pImpl
->
input
.
mutex
);
return
this
->
pImpl
->
scenario
.
minTileArea
()
;
return
this
->
pImpl
->
input
.
minTileArea
;
}
void
SnakeThread
::
setMinTileArea
(
Area
minTileArea
)
{
this
->
pImpl
->
input
.
scenarioChanged
=
true
;
this
->
pImpl
->
input
.
scenarioChanged
=
true
;
UniqueLock
lk
(
this
->
pImpl
->
input
.
mutex
);
this
->
pImpl
->
scenario
.
setMinTileArea
(
minTileArea
)
;
this
->
pImpl
->
input
.
minTileArea
=
minTileArea
;
}
Length
SnakeThread
::
tileHeight
()
const
{
SharedLock
lk
(
this
->
pImpl
->
input
.
mutex
);
return
this
->
pImpl
->
scenario
.
tileHeight
()
;
return
this
->
pImpl
->
input
.
tileHeight
;
}
void
SnakeThread
::
setTileHeight
(
Length
tileHeight
)
{
this
->
pImpl
->
input
.
scenarioChanged
=
true
;
UniqueLock
lk
(
this
->
pImpl
->
input
.
mutex
);
this
->
pImpl
->
scenario
.
setTileHeight
(
tileHeight
)
;
this
->
pImpl
->
input
.
tileHeight
=
tileHeight
;
}
Length
SnakeThread
::
tileWidth
()
const
{
SharedLock
lk
(
this
->
pImpl
->
input
.
mutex
);
return
this
->
pImpl
->
scenario
.
tileWidth
()
;
return
this
->
pImpl
->
input
.
tileWidth
;
}
void
SnakeThread
::
setTileWidth
(
Length
tileWidth
)
{
this
->
pImpl
->
input
.
scenarioChanged
=
true
;
UniqueLock
lk
(
this
->
pImpl
->
input
.
mutex
);
this
->
pImpl
->
scenario
.
setTileWidth
(
tileWidth
)
;
this
->
pImpl
->
input
.
tileWidth
=
tileWidth
;
}
void
SnakeThread
::
run
()
{
...
...
@@ -279,10 +283,13 @@ void SnakeThread::run() {
this
->
pImpl
->
output
.
calcInProgress
.
store
(
false
);
emit
calcInProgressChanged
(
this
->
pImpl
->
output
.
calcInProgress
.
load
());
};
CommandRAII
<
decltype
(
onExit
)
>
onExit
RAII
(
onExit
);
CommandRAII
<
decltype
(
onExit
)
>
command
RAII
(
onExit
);
bool
tilesValid
=
true
;
QGeoCoordinate
origin
;
bool
progressValid
=
false
;
snake
::
Length
lineDistance
;
snake
::
Length
minTransectLength
;
std
::
vector
<
int
>
progress
;
{
// Check preconditions.
SharedLock
lk
(
this
->
pImpl
->
input
.
mutex
);
...
...
@@ -295,118 +302,100 @@ void SnakeThread::run() {
this
->
pImpl
->
output
.
errorMessage
=
"Service area invalid: size < 3."
;
tilesValid
=
false
;
}
else
{
// Set Origin
origin
=
this
->
pImpl
->
input
.
mArea
.
front
();
// Update Scenario if necessary
if
(
this
->
pImpl
->
input
.
scenarioChanged
)
{
// Set Origin
this
->
pImpl
->
ENUOrigin
=
this
->
pImpl
->
input
.
mArea
.
front
();
// Update measurement area.
auto
&
mAreaEnu
=
this
->
pImpl
->
scenario
.
measurementArea
();
auto
&
mArea
=
this
->
pImpl
->
input
.
mArea
;
mAreaEnu
.
clear
();
for
(
auto
geoVertex
:
mArea
)
{
snake
::
BoostPoint
p
;
snake
::
toENU
(
origin
,
geoVertex
,
p
);
mAreaEnu
.
outer
().
push_back
(
p
);
}
this
->
pImpl
->
mAreaENU
.
clear
();
snake
::
areaToEnu
(
this
->
pImpl
->
ENUOrigin
,
this
->
pImpl
->
input
.
mArea
,
this
->
pImpl
->
mAreaENU
);
// Update service area.
auto
&
sAreaEnu
=
this
->
pImpl
->
scenario
.
serviceArea
();
auto
&
sArea
=
this
->
pImpl
->
input
.
sArea
;
sAreaEnu
.
clear
();
for
(
auto
geoVertex
:
sArea
)
{
snake
::
BoostPoint
p
;
snake
::
toENU
(
origin
,
geoVertex
,
p
);
sAreaEnu
.
outer
().
push_back
(
p
);
}
this
->
pImpl
->
sAreaENU
.
clear
();
snake
::
areaToEnu
(
this
->
pImpl
->
ENUOrigin
,
this
->
pImpl
->
input
.
sArea
,
this
->
pImpl
->
sAreaENU
);
// Update corridor.
auto
&
corridorEnu
=
this
->
pImpl
->
scenario
.
corridor
();
auto
&
corridor
=
this
->
pImpl
->
input
.
corridor
;
corridorEnu
.
clear
();
for
(
auto
geoVertex
:
corridor
)
{
snake
::
BoostPoint
p
;
snake
::
toENU
(
origin
,
geoVertex
,
p
);
corridorEnu
.
outer
().
push_back
(
p
);
}
// Update parametes.
this
->
pImpl
->
scenario
.
setTileHeight
(
this
->
pImpl
->
input
.
tileHeight
);
this
->
pImpl
->
scenario
.
setTileWidth
(
this
->
pImpl
->
input
.
tileWidth
);
this
->
pImpl
->
scenario
.
setMinTileArea
(
this
->
pImpl
->
input
.
minTileArea
);
if
(
!
this
->
pImpl
->
scenario
.
update
())
{
this
->
pImpl
->
output
.
errorMessage
=
this
->
pImpl
->
scenario
.
errorString
.
c_str
();
this
->
pImpl
->
corridorENU
.
clear
();
snake
::
areaToEnu
(
this
->
pImpl
->
ENUOrigin
,
this
->
pImpl
->
input
.
corridor
,
this
->
pImpl
->
corridorENU
);
// Fetch parametes.
auto
tileHeight
=
this
->
pImpl
->
input
.
tileHeight
;
auto
tileWidth
=
this
->
pImpl
->
input
.
tileWidth
;
auto
minTileArea
=
this
->
pImpl
->
input
.
minTileArea
;
// Update tiles.
this
->
pImpl
->
tilesENU
.
clear
();
this
->
pImpl
->
jAreaENU
.
clear
();
std
::
string
errorString
;
snake
::
BoundingBox
bbox
;
if
(
!
snake
::
joinedArea
(
this
->
pImpl
->
mAreaENU
,
this
->
pImpl
->
sAreaENU
,
this
->
pImpl
->
corridorENU
,
this
->
pImpl
->
jAreaENU
,
errorString
)
||
!
snake
::
tiles
(
this
->
pImpl
->
mAreaENU
,
tileHeight
,
tileWidth
,
minTileArea
,
this
->
pImpl
->
tilesENU
,
bbox
,
errorString
))
{
UniqueLock
uLock
(
this
->
pImpl
->
output
.
mutex
);
this
->
pImpl
->
output
.
errorMessage
=
errorString
.
c_str
();
tilesValid
=
false
;
}
}
if
(
tilesValid
)
{
// Sample data
lineDistance
=
this
->
pImpl
->
input
.
lineDistance
;
minTransectLength
=
this
->
pImpl
->
input
.
minTransectLength
;
// Verify progress.
size_t
nTiles
=
this
->
pImpl
->
tilesENU
.
size
();
if
(
size_t
(
this
->
pImpl
->
input
.
progress
.
progress
().
size
())
!=
nTiles
)
{
for
(
size_t
i
=
0
;
i
<
nTiles
;
++
i
)
{
progress
.
push_back
(
0
);
}
}
else
{
for
(
size_t
i
=
0
;
i
<
nTiles
;
++
i
)
{
progress
.
push_back
(
this
->
pImpl
->
input
.
progress
.
progress
()[
i
]);
}
}
progressValid
=
tilesValid
;
}
}
}
bool
waypointsValid
=
tilesValid
;
bool
progressValid
=
tilesValid
;
snake
::
flight_plan
::
Transects
transects
;
snake
::
flight_plan
::
Transects
transectsRouted
;
snake
::
flight_plan
::
Route
route
;
std
::
vector
<
int
>
progress
;
bool
waypointsValid
=
true
;
snake
::
Transects
transects
;
snake
::
Transects
transectsRouted
;
snake
::
Route
route
;
bool
needWaypointUpdate
=
this
->
pImpl
->
input
.
scenarioChanged
||
this
->
pImpl
->
input
.
routeParametersChanged
||
this
->
pImpl
->
input
.
progressChanged
;
if
(
tilesValid
)
{
if
(
needWaypointUpdate
)
{
// Sample data
SharedLock
inputLock
(
this
->
pImpl
->
input
.
mutex
);
// Verify progress.
size_t
nTiles
=
this
->
pImpl
->
scenario
.
tiles
().
size
();
if
(
size_t
(
this
->
pImpl
->
input
.
progress
.
progress
().
size
())
!=
nTiles
)
{
for
(
size_t
i
=
0
;
i
<
nTiles
;
++
i
)
{
progress
.
push_back
(
0
);
}
}
else
{
for
(
size_t
i
=
0
;
i
<
nTiles
;
++
i
)
{
progress
.
push_back
(
this
->
pImpl
->
input
.
progress
.
progress
()[
i
]);
}
}
// Copy remaining parameters and release lock.
const
auto
&
scenario
=
this
->
pImpl
->
scenario
;
const
auto
lineDistance
=
this
->
pImpl
->
input
.
lineDistance
;
const
auto
minTransectLength
=
this
->
pImpl
->
input
.
minTransectLength
;
inputLock
.
unlock
();
// Create transects.
// Data needed for transects.
std
::
string
errorString
;
snake
::
Angle
alpha
(
scenario
.
mAreaBoundingBox
().
angle
*
si
::
radian
);
std
::
cout
<<
"Transects angle: "
<<
alpha
<<
std
::
endl
;
transects
.
push_back
(
bg
::
model
::
linestring
<
snake
::
BoostPoint
>
{
scenario
.
homePositon
()});
bool
success
=
snake
::
flight_plan
::
transectsFromScenario
(
lineDistance
,
minTransectLength
,
alpha
,
scenario
,
progress
,
transects
,
errorString
);
snake
::
BoundingBox
bbox
;
snake
::
minimalBoundingBox
(
this
->
pImpl
->
mAreaENU
,
bbox
);
snake
::
Angle
alpha
(
bbox
.
angle
*
si
::
radian
);
snake
::
BoostPoint
home
;
snake
::
polygonCenter
(
this
->
pImpl
->
sAreaENU
,
home
);
transects
.
push_back
(
bg
::
model
::
linestring
<
snake
::
BoostPoint
>
{
home
});
// Create transects.
bool
success
=
snake
::
transectsFromScenario
(
lineDistance
,
minTransectLength
,
alpha
,
this
->
pImpl
->
mAreaENU
,
this
->
pImpl
->
tilesENU
,
progress
,
transects
,
errorString
);
if
(
!
success
)
{
UniqueLock
lk
(
this
->
pImpl
->
output
.
mutex
);
this
->
pImpl
->
output
.
errorMessage
=
errorString
.
c_str
();
waypointsValid
=
false
;
progressValid
=
true
;
}
else
if
(
transects
.
size
()
>
1
)
{
success
=
snake
::
flight_plan
::
route
(
scenario
.
joinedArea
()
,
transects
,
transectsRouted
,
route
,
errorString
);
// Route transects.
success
=
snake
::
route
(
this
->
pImpl
->
jAreaENU
,
transects
,
transectsRouted
,
route
,
errorString
);
if
(
!
success
)
{
UniqueLock
lk
(
this
->
pImpl
->
output
.
mutex
);
this
->
pImpl
->
output
.
errorMessage
=
errorString
.
c_str
();
waypointsValid
=
false
;
progressValid
=
true
;
}
else
{
waypointsValid
=
true
;
progressValid
=
true
;
}
}
else
{
// No transects
waypointsValid
=
false
;
progressValid
=
true
;
}
}
else
{
// No update necessary
waypointsValid
=
true
;
progressValid
=
true
;
}
}
...
...
@@ -428,26 +417,25 @@ void SnakeThread::run() {
this
->
pImpl
->
output
.
tileCenterPoints
.
clear
();
this
->
pImpl
->
output
.
tilesENU
.
polygons
().
clear
();
this
->
pImpl
->
output
.
tileCenterPointsENU
.
clear
();
this
->
pImpl
->
output
.
ENUOrigin
=
origin
;
// Convert and store scenario data.
const
auto
&
tiles
=
this
->
pImpl
->
scenario
.
tiles
();
const
auto
&
centerPoints
=
this
->
pImpl
->
scenario
.
tileCenterPoints
();
const
auto
&
tiles
=
this
->
pImpl
->
tilesENU
;
for
(
unsigned
int
i
=
0
;
i
<
tiles
.
size
();
++
i
)
{
const
auto
&
tile
=
tiles
[
i
];
SnakeTile
geoTile
;
SnakeTileLocal
enuTile
;
for
(
size_t
i
=
0
;
i
<
tile
.
outer
().
size
()
-
1
;
++
i
)
{
auto
&
p
=
tile
.
outer
()[
i
];
QPointF
enuVertex
(
p
.
get
<
0
>
(),
p
.
get
<
1
>
())
;
const
auto
&
p
=
tile
.
outer
()[
i
];
QPointF
enuVertex
{
p
.
get
<
0
>
(),
p
.
get
<
1
>
()}
;
QGeoCoordinate
geoVertex
;
snake
::
fromENU
(
o
rigin
,
p
,
geoVertex
);
snake
::
fromENU
(
this
->
pImpl
->
ENUO
rigin
,
p
,
geoVertex
);
enuTile
.
polygon
().
points
().
push_back
(
enuVertex
);
geoTile
.
push_back
(
geoVertex
);
}
const
auto
&
boostPoint
=
centerPoints
[
i
];
QPointF
enuVertex
(
boostPoint
.
get
<
0
>
(),
boostPoint
.
get
<
1
>
());
snake
::
BoostPoint
centerPoint
;
snake
::
polygonCenter
(
tile
,
centerPoint
);
QPointF
enuVertex
(
centerPoint
.
get
<
0
>
(),
centerPoint
.
get
<
1
>
());
QGeoCoordinate
geoVertex
;
snake
::
fromENU
(
origin
,
boost
Point
,
geoVertex
);
snake
::
fromENU
(
this
->
pImpl
->
ENUOrigin
,
center
Point
,
geoVertex
);
geoTile
.
setCenter
(
geoVertex
);
this
->
pImpl
->
output
.
tiles
.
polygons
().
push_back
(
geoTile
);
this
->
pImpl
->
output
.
tileCenterPoints
.
push_back
(
...
...
@@ -463,7 +451,7 @@ void SnakeThread::run() {
this
->
pImpl
->
input
.
progress
.
progress
().
clear
();
this
->
pImpl
->
output
.
progressUpdated
=
true
;
}
else
if
(
this
->
pImpl
->
input
.
progressChanged
)
{
if
(
progress
.
size
()
==
this
->
pImpl
->
scenario
.
tiles
()
.
size
())
{
if
(
progress
.
size
()
==
this
->
pImpl
->
tilesENU
.
size
())
{
auto
&
qProgress
=
this
->
pImpl
->
input
.
progress
;
qProgress
.
progress
().
clear
();
for
(
const
auto
&
p
:
progress
)
{
...
...
@@ -501,7 +489,7 @@ void SnakeThread::run() {
}
QPointF
enuVertex
{
boostVertex
.
get
<
0
>
(),
boostVertex
.
get
<
1
>
()};
QGeoCoordinate
geoVertex
;
snake
::
fromENU
(
o
rigin
,
boostVertex
,
geoVertex
);
snake
::
fromENU
(
this
->
pImpl
->
ENUO
rigin
,
boostVertex
,
geoVertex
);
this
->
pImpl
->
output
.
arrivalPathENU
.
push_back
(
enuVertex
);
this
->
pImpl
->
output
.
arrivalPath
.
push_back
(
geoVertex
);
}
...
...
@@ -516,7 +504,7 @@ void SnakeThread::run() {
}
QPointF
enuVertex
{
boostVertex
.
get
<
0
>
(),
boostVertex
.
get
<
1
>
()};
QGeoCoordinate
geoVertex
;
snake
::
fromENU
(
o
rigin
,
boostVertex
,
geoVertex
);
snake
::
fromENU
(
this
->
pImpl
->
ENUO
rigin
,
boostVertex
,
geoVertex
);
this
->
pImpl
->
output
.
returnPathENU
.
push_back
(
enuVertex
);
this
->
pImpl
->
output
.
returnPath
.
push_back
(
geoVertex
);
}
...
...
@@ -525,7 +513,7 @@ void SnakeThread::run() {
const
auto
&
boostVertex
=
route
[
i
];
QPointF
enuVertex
{
boostVertex
.
get
<
0
>
(),
boostVertex
.
get
<
1
>
()};
QGeoCoordinate
geoVertex
;
snake
::
fromENU
(
o
rigin
,
boostVertex
,
geoVertex
);
snake
::
fromENU
(
this
->
pImpl
->
ENUO
rigin
,
boostVertex
,
geoVertex
);
this
->
pImpl
->
output
.
waypointsENU
.
push_back
(
enuVertex
);
this
->
pImpl
->
output
.
waypoints
.
push_back
(
geoVertex
);
}
...
...
src/Wima/Snake/SnakeTile.cpp
View file @
a0c951cb
#include "SnakeTile.h"
SnakeTile
::
SnakeTile
(
)
:
WimaAreaData
(
)
{}
SnakeTile
::
SnakeTile
(
QObject
*
parent
)
:
WimaAreaData
(
parent
)
{}
SnakeTile
::
SnakeTile
(
const
SnakeTile
&
other
,
QObject
*
parent
)
:
WimaAreaData
(
parent
)
{
...
...
src/Wima/Snake/SnakeTile.h
View file @
a0c951cb
...
...
@@ -4,7 +4,7 @@
class
SnakeTile
:
public
WimaAreaData
{
public:
SnakeTile
();
SnakeTile
(
QObject
*
parent
=
nullptr
);
SnakeTile
(
const
SnakeTile
&
other
,
QObject
*
parent
=
nullptr
);
QString
type
()
const
{
return
"Tile"
;
}
...
...
src/Wima/Snake/snake.cpp
View file @
a0c951cb
...
...
@@ -375,160 +375,71 @@ void shortestPathFromGraph(const Matrix<double> &graph, size_t startIndex,
assert
(
ret
);
(
void
)
ret
;
}
//=========================================================================
// Scenario calculation.
//=========================================================================
}
Scenario
::
Scenario
()
:
_tileWidth
(
5
*
bu
::
si
::
meter
),
_tileHeight
(
5
*
bu
::
si
::
meter
),
_minTileArea
(
0
*
bu
::
si
::
meter
*
bu
::
si
::
meter
),
_needsUpdate
(
true
)
{}
void
Scenario
::
setMeasurementArea
(
const
BoostPolygon
&
area
)
{
_needsUpdate
=
true
;
_mArea
=
area
;
}
void
Scenario
::
setServiceArea
(
const
BoostPolygon
&
area
)
{
_needsUpdate
=
true
;
_sArea
=
area
;
}
void
Scenario
::
setCorridor
(
const
BoostPolygon
&
area
)
{
_needsUpdate
=
true
;
_corridor
=
area
;
}
BoostPolygon
&
Scenario
::
measurementArea
()
{
_needsUpdate
=
true
;
return
_mArea
;
}
BoostPolygon
&
Scenario
::
serviceArea
()
{
_needsUpdate
=
true
;
return
_sArea
;
}
BoostPolygon
&
Scenario
::
corridor
()
{
_needsUpdate
=
true
;
return
_corridor
;
}
const
BoundingBox
&
Scenario
::
mAreaBoundingBox
()
const
{
return
_mAreaBoundingBox
;
}
const
BoostPolygon
&
Scenario
::
measurementArea
()
const
{
return
_mArea
;
}
const
BoostPolygon
&
Scenario
::
serviceArea
()
const
{
return
_sArea
;
}
const
BoostPolygon
&
Scenario
::
corridor
()
const
{
return
_corridor
;
}
const
BoostPolygon
&
Scenario
::
joinedArea
()
const
{
return
_jArea
;
}
const
vector
<
BoostPolygon
>
&
Scenario
::
tiles
()
const
{
return
_tiles
;
}
const
BoostLineString
&
Scenario
::
tileCenterPoints
()
const
{
return
_tileCenterPoints
;
}
const
BoundingBox
&
Scenario
::
measurementAreaBBox
()
const
{
return
_mAreaBoundingBox
;
}
const
BoostPoint
&
Scenario
::
homePositon
()
const
{
return
_homePosition
;
}
bool
Scenario
::
update
()
{
if
(
!
_needsUpdate
)
return
true
;
bg
::
correct
(
_mArea
);
bg
::
correct
(
_sArea
);
bg
::
correct
(
_corridor
);
polygonCenter
(
_sArea
,
_homePosition
);
if
(
!
_calculateJoinedArea
())
return
false
;
if
(
!
_calculateBoundingBox
())
bool
tiles
(
const
BoostPolygon
&
area
,
Length
tileHeight
,
Length
tileWidth
,
Area
minTileArea
,
std
::
vector
<
BoostPolygon
>
&
tiles
,
BoundingBox
&
bbox
,
string
&
errorString
)
{
if
(
area
.
outer
().
empty
()
||
area
.
outer
().
size
()
<
4
)
{
errorString
=
"Area has to few vertices."
;
return
false
;
if
(
!
_calculateTiles
())
return
false
;
_needsUpdate
=
false
;
return
true
;
}
bool
Scenario
::
_calculateBoundingBox
()
const
{
return
minimalBoundingBox
(
_mArea
,
_mAreaBoundingBox
);
}
}
/**
* Devides the (measurement area) bounding box into tiles and clips it to the
* measurement area.
*
* Devides the (measurement area) bounding box into tiles of width \p tileWidth
* and height \p tileHeight. Clips the resulting tiles to the measurement area.
* Tiles are rejected, if their area is smaller than \p minTileArea. The
* function assumes that \a _mArea and \a _mAreaBoundingBox have correct values.
* \see \ref Scenario::_areas2enu() and \ref Scenario::_calculateBoundingBox().
*
* @param tileWidth The width (>0) of a tile.
* @param tileHeight The heigth (>0) of a tile.
* @param minTileArea The minimal area (>0) of a tile.
*
* @return Returns true if successful.
*/
bool
Scenario
::
_calculateTiles
()
const
{
_tiles
.
clear
();
_tileCenterPoints
.
clear
();
if
(
_tileWidth
<=
0
*
bu
::
si
::
meter
||
_tileHeight
<=
0
*
bu
::
si
::
meter
||
_minTileArea
<
0
*
bu
::
si
::
meter
*
bu
::
si
::
meter
)
{
if
(
tileWidth
<=
0
*
bu
::
si
::
meter
||
tileHeight
<=
0
*
bu
::
si
::
meter
||
minTileArea
<
0
*
bu
::
si
::
meter
*
bu
::
si
::
meter
)
{
std
::
stringstream
ss
;
ss
<<
"Parameters tileWidth ("
<<
_
tileWidth
<<
"), tileHeight ("
<<
_tileHeight
<<
"), minTileArea ("
<<
_
minTileArea
ss
<<
"Parameters tileWidth ("
<<
tileWidth
<<
"), tileHeight ("
<<
tileHeight
<<
"), minTileArea ("
<<
minTileArea
<<
") must be positive."
;
errorString
=
ss
.
str
();
return
false
;
}
double
bboxWidth
=
_mAreaBoundingBox
.
width
;
double
bboxHeight
=
_mAreaBoundingBox
.
height
;
if
(
bbox
.
corners
.
outer
().
size
()
!=
5
)
{
bbox
.
corners
.
clear
();
minimalBoundingBox
(
area
,
bbox
);
}
BoostPoint
origin
=
_mAreaBoundingBox
.
corners
.
outer
()[
0
];
if
(
bbox
.
corners
.
outer
().
size
()
<
5
)
return
false
;
double
bboxWidth
=
bbox
.
width
;
double
bboxHeight
=
bbox
.
height
;
BoostPoint
origin
=
bbox
.
corners
.
outer
()[
0
];
// cout << "Origin: " << origin[0] << " " << origin[1] << endl;
// Transform _mArea polygon to bounding box coordinate system.
trans
::
rotate_transformer
<
boost
::
geometry
::
degree
,
double
,
2
,
2
>
rotate
(
_mAreaBoundingB
ox
.
angle
*
180
/
M_PI
);
bb
ox
.
angle
*
180
/
M_PI
);
trans
::
translate_transformer
<
double
,
2
,
2
>
translate
(
-
origin
.
get
<
0
>
(),
-
origin
.
get
<
1
>
());
BoostPolygon
translated_polygon
;
BoostPolygon
rotated_polygon
;
boost
::
geometry
::
transform
(
_mA
rea
,
translated_polygon
,
translate
);
boost
::
geometry
::
transform
(
a
rea
,
translated_polygon
,
translate
);
boost
::
geometry
::
transform
(
translated_polygon
,
rotated_polygon
,
rotate
);
bg
::
correct
(
rotated_polygon
);
// cout << bg::wkt<BoostPolygon2D>(rotated_polygon) << endl;
size_t
iMax
=
ceil
(
bboxWidth
/
_
tileWidth
.
value
());
size_t
jMax
=
ceil
(
bboxHeight
/
_
tileHeight
.
value
());
size_t
iMax
=
ceil
(
bboxWidth
/
tileWidth
.
value
());
size_t
jMax
=
ceil
(
bboxHeight
/
tileHeight
.
value
());
if
(
iMax
<
1
||
jMax
<
1
)
{
std
::
stringstream
ss
;
ss
<<
"Tile width ("
<<
_tileWidth
<<
") or tile height ("
<<
_
tileHeight
ss
<<
"Tile width ("
<<
tileWidth
<<
") or tile height ("
<<
tileHeight
<<
") to large for measurement area."
;
errorString
=
ss
.
str
();
return
false
;
}
trans
::
rotate_transformer
<
boost
::
geometry
::
degree
,
double
,
2
,
2
>
rotate_back
(
-
_mAreaBoundingB
ox
.
angle
*
180
/
M_PI
);
-
bb
ox
.
angle
*
180
/
M_PI
);
trans
::
translate_transformer
<
double
,
2
,
2
>
translate_back
(
origin
.
get
<
0
>
(),
origin
.
get
<
1
>
());
for
(
size_t
i
=
0
;
i
<
iMax
;
++
i
)
{
double
x_min
=
_
tileWidth
.
value
()
*
i
;
double
x_max
=
x_min
+
_
tileWidth
.
value
();
double
x_min
=
tileWidth
.
value
()
*
i
;
double
x_max
=
x_min
+
tileWidth
.
value
();
for
(
size_t
j
=
0
;
j
<
jMax
;
++
j
)
{
double
y_min
=
_
tileHeight
.
value
()
*
j
;
double
y_max
=
y_min
+
_
tileHeight
.
value
();
double
y_min
=
tileHeight
.
value
()
*
j
;
double
y_max
=
y_min
+
tileHeight
.
value
();
BoostPolygon
tile_unclipped
;
tile_unclipped
.
outer
().
push_back
(
BoostPoint
{
x_min
,
y_min
});
...
...
@@ -543,7 +454,7 @@ bool Scenario::_calculateTiles() const {
continue
;
for
(
BoostPolygon
t
:
boost_tiles
)
{
if
(
bg
::
area
(
t
)
>
_
minTileArea
.
value
())
{
if
(
bg
::
area
(
t
)
>
minTileArea
.
value
())
{
// Transform boost_tile to world coordinate system.
BoostPolygon
rotated_tile
;
BoostPolygon
translated_tile
;
...
...
@@ -552,18 +463,15 @@ bool Scenario::_calculateTiles() const {
translate_back
);
// Store tile and calculate center point.
_tiles
.
push_back
(
translated_tile
);
BoostPoint
tile_center
;
polygonCenter
(
translated_tile
,
tile_center
);
_tileCenterPoints
.
push_back
(
tile_center
);
tiles
.
push_back
(
translated_tile
);
}
}
}
}
if
(
_
tiles
.
size
()
<
1
)
{
if
(
tiles
.
size
()
<
1
)
{
std
::
stringstream
ss
;
ss
<<
"No tiles calculated. Is the minTileArea ("
<<
_
minTileArea
ss
<<
"No tiles calculated. Is the minTileArea ("
<<
minTileArea
<<
") parameter large enough?"
;
errorString
=
ss
.
str
();
return
false
;
...
...
@@ -572,19 +480,20 @@ bool Scenario::_calculateTiles() const {
return
true
;
}
bool
Scenario
::
_calculateJoinedArea
()
const
{
_jArea
.
clear
();
bool
joinedArea
(
const
BoostPolygon
&
mArea
,
const
BoostPolygon
&
sArea
,
const
BoostPolygon
&
corridor
,
BoostPolygon
&
jArea
,
std
::
string
&
errorString
)
{
// Measurement area and service area overlapping?
bool
overlapingSerMeas
=
bg
::
intersects
(
_mArea
,
_
sArea
)
?
true
:
false
;
bool
corridorValid
=
_
corridor
.
outer
().
size
()
>
0
?
true
:
false
;
bool
overlapingSerMeas
=
bg
::
intersects
(
mArea
,
sArea
)
?
true
:
false
;
bool
corridorValid
=
corridor
.
outer
().
size
()
>
0
?
true
:
false
;
// Check if corridor is connecting measurement area and service area.
bool
corridor_is_connection
=
false
;
if
(
corridorValid
)
{
// Corridor overlaping with measurement area?
if
(
bg
::
intersects
(
_corridor
,
_
mArea
))
{
if
(
bg
::
intersects
(
corridor
,
mArea
))
{
// Corridor overlaping with service area?
if
(
bg
::
intersects
(
_corridor
,
_
sArea
))
{
if
(
bg
::
intersects
(
corridor
,
sArea
))
{
corridor_is_connection
=
true
;
}
}
...
...
@@ -592,13 +501,13 @@ bool Scenario::_calculateJoinedArea() const {
// Are areas joinable?
std
::
deque
<
BoostPolygon
>
sol
;
BoostPolygon
partialArea
=
_
mArea
;
BoostPolygon
partialArea
=
mArea
;
if
(
overlapingSerMeas
)
{
if
(
corridor_is_connection
)
{
bg
::
union_
(
partialArea
,
_
corridor
,
sol
);
bg
::
union_
(
partialArea
,
corridor
,
sol
);
}
}
else
if
(
corridor_is_connection
)
{
bg
::
union_
(
partialArea
,
_
corridor
,
sol
);
bg
::
union_
(
partialArea
,
corridor
,
sol
);
}
else
{
std
::
stringstream
ss
;
auto
printPoint
=
[
&
ss
](
const
BoostPoint
&
p
)
{
...
...
@@ -606,13 +515,13 @@ bool Scenario::_calculateJoinedArea() const {
};
ss
<<
"Areas are not overlapping."
<<
std
::
endl
;
ss
<<
"Measurement area:"
;
bg
::
for_each_point
(
_
mArea
,
printPoint
);
bg
::
for_each_point
(
mArea
,
printPoint
);
ss
<<
std
::
endl
;
ss
<<
"Service area:"
;
bg
::
for_each_point
(
_
sArea
,
printPoint
);
bg
::
for_each_point
(
sArea
,
printPoint
);
ss
<<
std
::
endl
;
ss
<<
"Corridor:"
;
bg
::
for_each_point
(
_
corridor
,
printPoint
);
bg
::
for_each_point
(
corridor
,
printPoint
);
ss
<<
std
::
endl
;
errorString
=
ss
.
str
();
return
false
;
...
...
@@ -624,62 +533,46 @@ bool Scenario::_calculateJoinedArea() const {
}
// Join areas.
bg
::
union_
(
partialArea
,
_
sArea
,
sol
);
bg
::
union_
(
partialArea
,
sArea
,
sol
);
if
(
sol
.
size
()
>
0
)
{
_
jArea
=
sol
[
0
];
jArea
=
sol
[
0
];
}
else
{
std
::
stringstream
ss
;
auto
printPoint
=
[
&
ss
](
const
BoostPoint
&
p
)
{
ss
<<
" ("
<<
p
.
get
<
0
>
()
<<
", "
<<
p
.
get
<
1
>
()
<<
")"
;
};
ss
<<
"Areas not joinable."
<<
std
::
endl
;
ss
<<
"Measurement area:"
;
bg
::
for_each_point
(
mArea
,
printPoint
);
ss
<<
std
::
endl
;
ss
<<
"Service area:"
;
bg
::
for_each_point
(
sArea
,
printPoint
);
ss
<<
std
::
endl
;
ss
<<
"Corridor:"
;
bg
::
for_each_point
(
corridor
,
printPoint
);
ss
<<
std
::
endl
;
errorString
=
ss
.
str
();
return
false
;
}
return
true
;
}
Area
Scenario
::
minTileArea
()
const
{
return
_minTileArea
;
}
void
Scenario
::
setMinTileArea
(
Area
minTileArea
)
{
if
(
minTileArea
>=
0
*
bu
::
si
::
meter
*
bu
::
si
::
meter
)
{
_needsUpdate
=
true
;
_minTileArea
=
minTileArea
;
}
}
Length
Scenario
::
tileHeight
()
const
{
return
_tileHeight
;
}
void
Scenario
::
setTileHeight
(
Length
tileHeight
)
{
if
(
tileHeight
>
0
*
bu
::
si
::
meter
)
{
_needsUpdate
=
true
;
_tileHeight
=
tileHeight
;
}
}
Length
Scenario
::
tileWidth
()
const
{
return
_tileWidth
;
}
void
Scenario
::
setTileWidth
(
Length
tileWidth
)
{
if
(
tileWidth
>
0
*
bu
::
si
::
meter
)
{
_needsUpdate
=
true
;
_tileWidth
=
tileWidth
;
}
}
//=========================================================================
// Tile calculation.
//=========================================================================
bool
joinAreas
(
const
std
::
vector
<
BoostPolygon
>
&
areas
,
BoostPolygon
&
joinedArea
)
{
bool
joinedArea
(
const
std
::
vector
<
BoostPolygon
*>
&
areas
,
BoostPolygon
&
joinedArea
)
{
if
(
areas
.
size
()
<
1
)
return
false
;
joinedArea
=
*
areas
[
0
];
std
::
deque
<
std
::
size_t
>
idxList
;
for
(
size_t
i
=
1
;
i
<
areas
.
size
();
++
i
)
idxList
.
push_back
(
i
);
joinedArea
=
areas
[
0
];
std
::
deque
<
BoostPolygon
>
sol
;
while
(
idxList
.
size
()
>
0
)
{
bool
success
=
false
;
for
(
auto
it
=
idxList
.
begin
();
it
!=
idxList
.
end
();
++
it
)
{
bg
::
union_
(
joinedArea
,
areas
[
*
it
],
sol
);
bg
::
union_
(
joinedArea
,
*
areas
[
*
it
],
sol
);
if
(
sol
.
size
()
>
0
)
{
joinedArea
=
sol
[
0
];
sol
.
clear
();
...
...
@@ -704,13 +597,12 @@ void BoundingBox::clear() {
corners
.
clear
();
}
bool
flight_plan
::
transectsFromScenario
(
Length
distance
,
Length
minLength
,
Angle
angle
,
const
Scenario
&
scenario
,
const
Progress
&
p
,
flight_plan
::
Transects
&
t
,
string
&
errorString
)
{
bool
transectsFromScenario
(
Length
distance
,
Length
minLength
,
Angle
angle
,
const
BoostPolygon
&
mArea
,
const
std
::
vector
<
BoostPolygon
>
&
tiles
,
const
Progress
&
p
,
Transects
&
t
,
string
&
errorString
)
{
// Rotate measurement area by angle and calculate bounding box.
auto
&
mArea
=
scenario
.
measurementArea
();
BoostPolygon
mAreaRotated
;
trans
::
rotate_transformer
<
bg
::
degree
,
double
,
2
,
2
>
rotate
(
angle
.
value
()
*
180
/
M_PI
);
...
...
@@ -778,14 +670,13 @@ bool flight_plan::transectsFromScenario(Length distance, Length minLength,
ClipperLib
::
pftNonZero
,
ClipperLib
::
pftNonZero
);
const
auto
*
transects
=
&
clippedTransecs
;
bool
ignoreProgress
=
p
.
size
()
!=
scenario
.
tiles
()
.
size
();
bool
ignoreProgress
=
p
.
size
()
!=
tiles
.
size
();
ClipperLib
::
PolyTree
clippedTransecs2
;
if
(
!
ignoreProgress
)
{
// Calculate processed tiles (_progress[i] == 100) and subtract them from
// measurement area.
size_t
numTiles
=
p
.
size
();
vector
<
BoostPolygon
>
processedTiles
;
const
auto
&
tiles
=
scenario
.
tiles
();
for
(
size_t
i
=
0
;
i
<
numTiles
;
++
i
)
{
if
(
p
[
i
]
==
100
)
{
processedTiles
.
push_back
(
tiles
[
i
]);
...
...
@@ -889,10 +780,8 @@ void generateRoutingModel(const BoostLineString &vertices,
dataModel
.
depot
=
0
;
}
bool
flight_plan
::
route
(
const
BoostPolygon
&
area
,
const
flight_plan
::
Transects
&
transects
,
Transects
&
transectsRouted
,
flight_plan
::
Route
&
route
,
string
&
errorString
)
{
bool
route
(
const
BoostPolygon
&
area
,
const
Transects
&
transects
,
Transects
&
transectsRouted
,
Route
&
route
,
string
&
errorString
)
{
//=======================================
// Route Transects using Google or-tools.
//=======================================
...
...
src/Wima/Snake/snake.h
View file @
a0c951cb
...
...
@@ -103,6 +103,7 @@ void toENU(const GeoPoint &origin, const GeoPoint &in, BoostPoint &out) {
out
.
set
<
1
>
(
y
);
(
void
)
z
;
}
template
<
class
GeoPoint
>
void
fromENU
(
const
GeoPoint
&
origin
,
const
BoostPoint
&
in
,
GeoPoint
&
out
)
{
GeographicLib
::
Geocentric
earth
(
GeographicLib
::
Constants
::
WGS84_a
(),
...
...
@@ -117,88 +118,6 @@ void fromENU(const GeoPoint &origin, const BoostPoint &in, GeoPoint &out) {
out
.
setAltitude
(
alt
);
}
void
polygonCenter
(
const
BoostPolygon
&
polygon
,
BoostPoint
&
center
);
bool
minimalBoundingBox
(
const
BoostPolygon
&
polygon
,
BoundingBox
&
minBBox
);
void
offsetPolygon
(
const
BoostPolygon
&
polygon
,
BoostPolygon
&
polygonOffset
,
double
offset
);
void
graphFromPolygon
(
const
BoostPolygon
&
polygon
,
const
BoostLineString
&
vertices
,
Matrix
<
double
>
&
graph
);
void
toDistanceMatrix
(
Matrix
<
double
>
&
graph
);
bool
dijkstraAlgorithm
(
const
size_t
numElements
,
size_t
startIndex
,
size_t
endIndex
,
std
::
vector
<
size_t
>
&
elementPath
,
std
::
function
<
double
(
const
size_t
,
const
size_t
)
>
distanceDij
);
void
shortestPathFromGraph
(
const
Matrix
<
double
>
&
graph
,
size_t
startIndex
,
size_t
endIndex
,
std
::
vector
<
size_t
>
&
pathIdx
);
//=========================================================================
// Scenario.
//=========================================================================
typedef
bu
::
quantity
<
bu
::
si
::
length
>
Length
;
typedef
bu
::
quantity
<
bu
::
si
::
area
>
Area
;
typedef
bu
::
quantity
<
bu
::
si
::
plane_angle
>
Angle
;
class
Scenario
{
public:
Scenario
();
void
setMeasurementArea
(
const
BoostPolygon
&
area
);
void
setServiceArea
(
const
BoostPolygon
&
area
);
void
setCorridor
(
const
BoostPolygon
&
area
);
const
BoundingBox
&
mAreaBoundingBox
()
const
;
const
BoostPolygon
&
measurementArea
()
const
;
const
BoostPolygon
&
serviceArea
()
const
;
const
BoostPolygon
&
corridor
()
const
;
BoostPolygon
&
measurementArea
();
BoostPolygon
&
serviceArea
();
BoostPolygon
&
corridor
();
Length
tileWidth
()
const
;
void
setTileWidth
(
Length
tileWidth
);
Length
tileHeight
()
const
;
void
setTileHeight
(
Length
tileHeight
);
Area
minTileArea
()
const
;
void
setMinTileArea
(
Area
minTileArea
);
const
BoostPolygon
&
joinedArea
()
const
;
const
vector
<
BoostPolygon
>
&
tiles
()
const
;
const
BoostLineString
&
tileCenterPoints
()
const
;
const
BoundingBox
&
measurementAreaBBox
()
const
;
const
BoostPoint
&
homePositon
()
const
;
bool
update
();
mutable
string
errorString
;
private:
bool
_calculateBoundingBox
()
const
;
bool
_calculateTiles
()
const
;
bool
_calculateJoinedArea
()
const
;
Length
_tileWidth
;
Length
_tileHeight
;
Area
_minTileArea
;
mutable
bool
_needsUpdate
;
BoostPolygon
_mArea
;
BoostPolygon
_sArea
;
BoostPolygon
_corridor
;
mutable
BoostPolygon
_jArea
;
mutable
BoundingBox
_mAreaBoundingBox
;
mutable
vector
<
BoostPolygon
>
_tiles
;
mutable
BoostLineString
_tileCenterPoints
;
mutable
BoostPoint
_homePosition
;
};
template
<
class
GeoPoint
,
template
<
class
,
class
...
>
class
Container
>
void
areaToEnu
(
const
GeoPoint
&
origin
,
const
Container
<
GeoPoint
>
&
in
,
BoostPolygon
&
out
)
{
...
...
@@ -220,25 +139,43 @@ void areaFromEnu(const GeoPoint &origin, BoostPolygon &in,
}
}
bool
joinAreas
(
const
std
::
vector
<
BoostPolygon
>
&
areas
,
BoostPolygon
&
joinedArea
);
void
polygonCenter
(
const
BoostPolygon
&
polygon
,
BoostPoint
&
center
);
bool
minimalBoundingBox
(
const
BoostPolygon
&
polygon
,
BoundingBox
&
minBBox
);
void
offsetPolygon
(
const
BoostPolygon
&
polygon
,
BoostPolygon
&
polygonOffset
,
double
offset
);
void
graphFromPolygon
(
const
BoostPolygon
&
polygon
,
const
BoostLineString
&
vertices
,
Matrix
<
double
>
&
graph
);
void
toDistanceMatrix
(
Matrix
<
double
>
&
graph
);
bool
dijkstraAlgorithm
(
const
size_t
numElements
,
size_t
startIndex
,
size_t
endIndex
,
std
::
vector
<
size_t
>
&
elementPath
,
std
::
function
<
double
(
const
size_t
,
const
size_t
)
>
distanceDij
);
void
shortestPathFromGraph
(
const
Matrix
<
double
>
&
graph
,
size_t
startIndex
,
size_t
endIndex
,
std
::
vector
<
size_t
>
&
pathIdx
);
//========================================================================================
// flight_plan
//========================================================================================
typedef
bu
::
quantity
<
bu
::
si
::
length
>
Length
;
typedef
bu
::
quantity
<
bu
::
si
::
area
>
Area
;
typedef
bu
::
quantity
<
bu
::
si
::
plane_angle
>
Angle
;
namespace
flight_plan
{
bool
joinedArea
(
const
std
::
vector
<
BoostPolygon
*>
&
areas
,
BoostPolygon
&
jArea
);
bool
joinedArea
(
const
BoostPolygon
&
mArea
,
const
BoostPolygon
&
sArea
,
const
BoostPolygon
&
corridor
,
BoostPolygon
&
jArea
,
std
::
string
&
errorString
);
bool
tiles
(
const
BoostPolygon
&
area
,
Length
tileHeight
,
Length
tileWidth
,
Area
minTileArea
,
std
::
vector
<
BoostPolygon
>
&
tiles
,
BoundingBox
&
bbox
,
std
::
string
&
errorString
);
using
Transects
=
vector
<
BoostLineString
>
;
using
Progress
=
vector
<
int
>
;
using
Route
=
vector
<
BoostPoint
>
;
bool
transectsFromScenario
(
Length
distance
,
Length
minLength
,
Angle
angle
,
const
Scenario
&
scenario
,
const
Progress
&
p
,
Transects
&
t
,
string
&
errorString
);
const
BoostPolygon
&
mArea
,
const
std
::
vector
<
BoostPolygon
>
&
tiles
,
const
Progress
&
p
,
Transects
&
t
,
string
&
errorString
);
bool
route
(
const
BoostPolygon
&
area
,
const
Transects
&
transects
,
Transects
&
transectsRouted
,
Route
&
route
,
string
&
errorString
);
}
// namespace flight_plan
namespace
detail
{
const
double
offsetConstant
=
...
...
src/WimaView/WimaMeasurementAreaEditor.qml
View file @
a0c951cb
...
...
@@ -43,7 +43,7 @@ Rectangle {
SectionHeader
{
id
:
settingsHeader
text
:
qsTr
(
"
Settings
"
)
text
:
qsTr
(
"
General
"
)
}
Column
{
...
...
@@ -79,12 +79,18 @@ Rectangle {
}
}
// Column - Settings
SectionHeader
{
id
:
snake
Header
text
:
qsTr
(
"
Snake
"
)
id
:
tiles
Header
text
:
qsTr
(
"
Tiles
"
)
}
Column
{
anchors.left
:
parent
.
left
anchors.right
:
parent
.
right
spacing
:
_margin
visible
:
tilesHeader
.
checked
GridLayout
{
anchors.left
:
parent
.
left
anchors.right
:
parent
.
right
...
...
@@ -92,44 +98,69 @@ Rectangle {
rowSpacing
:
_margin
columns
:
2
QGCLabel
{
text
:
qsTr
(
"
Tile
Height
"
)
}
QGCLabel
{
text
:
qsTr
(
"
Height
"
)
}
FactTextField
{
//fact: areaItem.borderPolygonOffse
t
fact
:
areaItem
.
tileHeigh
t
Layout.fillWidth
:
true
}
QGCLabel
{
text
:
qsTr
(
"
Tile
Width
"
)
}
QGCLabel
{
text
:
qsTr
(
"
Width
"
)
}
FactTextField
{
//fact: areaItem.borderPolygonOffset
fact
:
areaItem
.
tileWidth
Layout.fillWidth
:
true
}
QGCLabel
{
text
:
qsTr
(
"
Min.
Tile
Area
"
)
}
QGCLabel
{
text
:
qsTr
(
"
Min. Area
"
)
}
FactTextField
{
//fact: areaItem.borderPolygonOffset
fact
:
areaItem
.
minTileArea
Layout.fillWidth
:
true
}
QGCLabel
{
text
:
qsTr
(
"
Transect Distance
"
)
}
FactCheckBox
{
text
:
qsTr
(
"
Show Tiles
"
)
fact
:
areaItem
.
showTiles
}
}
// Tile GridLayout
}
// Tile Column
SectionHeader
{
id
:
transectsHeader
text
:
qsTr
(
"
Transects
"
)
}
Column
{
anchors.left
:
parent
.
left
anchors.right
:
parent
.
right
spacing
:
_margin
visible
:
transectsHeader
.
checked
GridLayout
{
anchors.left
:
parent
.
left
anchors.right
:
parent
.
right
columnSpacing
:
_margin
rowSpacing
:
_margin
columns
:
2
QGCLabel
{
text
:
qsTr
(
"
Distance
"
)
}
FactTextField
{
//fact: areaItem.borderPolygonOffset
fact
:
areaItem
.
transectDistance
Layout.fillWidth
:
true
}
QGCLabel
{
text
:
qsTr
(
"
Min.
Transect
Length
"
)
}
QGCLabel
{
text
:
qsTr
(
"
Min. Length
"
)
}
FactTextField
{
//fact: areaItem.borderPolygonOffset
fact
:
areaItem
.
minTransectLength
Layout.fillWidth
:
true
}
}
}
// Transects GridLayout
}
// Transects Column
}
// Snake
SectionHeader
{
id
:
statsHeader
...
...
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