Commit 6ac2e382 authored by Valentin Platzgummer's avatar Valentin Platzgummer

circular survey edited

parent 89e1c7a3
error when loading wima file
......@@ -220,6 +220,7 @@
<file alias="QGroundControl/Controls/WimaMeasurementAreaMapVisual.qml">src/WimaView/WimaMeasurementAreaMapVisual.qml</file>
<file alias="QGroundControl/Controls/WimaCorridorMapVisual.qml">src/WimaView/WimaCorridorMapVisual.qml</file>
<file alias="QGroundControl/Controls/WimaMeasurementAreaEditor.qml">src/WimaView/WimaMeasurementAreaEditor.qml</file>
<file alias="QGroundControl/Controls/SpericalSurveyMapVisual.qml">src/WimaView/SphericalSurveyMapVisual.qml</file>
</qresource>
<qresource prefix="/json">
<file alias="APMMavlinkStreamRate.SettingsGroup.json">src/Settings/APMMavlinkStreamRate.SettingsGroup.json</file>
......
......@@ -31,6 +31,8 @@
#include "KML.h"
#include "QGCCorePlugin.h"
#include "src/Wima/CircularSurveyComplexItem.h"
#ifndef __mobile__
#include "MainWindow.h"
#include "QGCQFileDialog.h"
......@@ -61,19 +63,20 @@ const QString MissionController::patternStructureScanName (QT_TRANSLATE_NOOP("M
const QString MissionController::patternCorridorScanName (QT_TRANSLATE_NOOP("MissionController", "Corridor Scan"));
MissionController::MissionController(PlanMasterController* masterController, QObject *parent)
: PlanElementController (masterController, parent)
, _missionManager (_managerVehicle->missionManager())
, _missionItemCount (0)
, _visualItems (nullptr)
, _settingsItem (nullptr)
, _firstItemsFromVehicle (false)
, _itemsRequested (false)
, _inRecalcSequence (false)
, _surveyMissionItemName (tr("Survey"))
, _appSettings (qgcApp()->toolbox()->settingsManager()->appSettings())
, _progressPct (0)
, _currentPlanViewIndex (-1)
, _currentPlanViewItem (nullptr)
: PlanElementController (masterController, parent)
, _missionManager (_managerVehicle->missionManager())
, _missionItemCount (0)
, _visualItems (nullptr)
, _settingsItem (nullptr)
, _firstItemsFromVehicle (false)
, _itemsRequested (false)
, _inRecalcSequence (false)
, _surveyMissionItemName (tr("Survey"))
, _circularSurveyMissionItemName(tr("Circular Survey"))
, _appSettings (qgcApp()->toolbox()->settingsManager()->appSettings())
, _progressPct (0)
, _currentPlanViewIndex (-1)
, _currentPlanViewItem (nullptr)
{
_resetMissionFlightStatus();
managerVehicleChanged(_managerVehicle);
......@@ -254,7 +257,7 @@ void MissionController::sendToVehicle(void)
}
/// Converts from visual items to MissionItems
/// @param missionItemParent QObject parent for newly allocated MissionItems
/// @param missionItemParent QObject parent for newly allocated MissionItems, _surveyMissionItemName (tr("Survey"))
/// @return true: Mission end action was added to end of list
bool MissionController::_convertToMissionItems(QmlObjectListModel* visualMissionItems, QList<MissionItem*>& rgMissionItems, QObject* missionItemParent)
{
......@@ -422,6 +425,8 @@ int MissionController::insertComplexMissionItem(QString itemName, QGeoCoordinate
newItem = new StructureScanComplexItem(_controllerVehicle, _flyView, QString() /* kmlFile */, _visualItems /* parent */);
} else if (itemName == patternCorridorScanName) {
newItem = new CorridorScanComplexItem(_controllerVehicle, _flyView, QString() /* kmlFile */, _visualItems /* parent */);
} else if (itemName == _circularSurveyMissionItemName) {
newItem = new CircularSurveyComplexItem(_controllerVehicle, _flyView, QString() /* kmlFile */, _visualItems /* parent */);
} else {
qWarning() << "Internal error: Unknown complex item:" << itemName;
return sequenceNumber;
......@@ -436,6 +441,8 @@ int MissionController::insertComplexMissionItemFromKMLOrSHP(QString itemName, QS
if (itemName == _surveyMissionItemName) {
newItem = new SurveyComplexItem(_controllerVehicle, _flyView, file, _visualItems);
} else if (itemName == _circularSurveyMissionItemName) {
newItem = new CircularSurveyComplexItem(_controllerVehicle, _flyView, file, _visualItems);
} else if (itemName == patternStructureScanName) {
newItem = new StructureScanComplexItem(_controllerVehicle, _flyView, file, _visualItems);
} else if (itemName == patternCorridorScanName) {
......@@ -1952,6 +1959,7 @@ QStringList MissionController::complexMissionItemNames(void) const
{
QStringList complexItems;
complexItems.append(_circularSurveyMissionItemName);
complexItems.append(_surveyMissionItemName);
complexItems.append(patternCorridorScanName);
if (_controllerVehicle->fixedWing()) {
......
......@@ -20,6 +20,8 @@
#include <QHash>
class CoordinateVector;
class VisualMissionItem;
class MissionItem;
......@@ -168,16 +170,17 @@ public:
// Property accessors
QmlObjectListModel* visualItems (void) { return _visualItems; }
QmlObjectListModel* waypointLines (void) { return &_waypointLines; }
QVariantList waypointPath (void) { return _waypointPath; }
QStringList complexMissionItemNames (void) const;
QGeoCoordinate plannedHomePosition (void) const;
VisualMissionItem* currentPlanViewItem (void) const;
double progressPct (void) const { return _progressPct; }
QString surveyComplexItemName (void) const { return _surveyMissionItemName; }
QString corridorScanComplexItemName (void) const { return patternCorridorScanName; }
QString structureScanComplexItemName(void) const { return patternStructureScanName; }
QmlObjectListModel* visualItems (void) { return _visualItems; }
QmlObjectListModel* waypointLines (void) { return &_waypointLines; }
QVariantList waypointPath (void) { return _waypointPath; }
QStringList complexMissionItemNames (void) const;
QGeoCoordinate plannedHomePosition (void) const;
VisualMissionItem* currentPlanViewItem (void) const;
double progressPct (void) const { return _progressPct; }
QString surveyComplexItemName (void) const { return _surveyMissionItemName; }
QString circularSurveyComplexItemName (void) const { return _circularSurveyMissionItemName; }
QString corridorScanComplexItemName (void) const { return patternCorridorScanName; }
QString structureScanComplexItemName (void) const { return patternStructureScanName; }
int missionItemCount (void) const { return _missionItemCount; }
int currentMissionIndex (void) const;
......@@ -292,6 +295,7 @@ private:
bool _inRecalcSequence;
MissionFlightStatus_t _missionFlightStatus;
QString _surveyMissionItemName;
QString _circularSurveyMissionItemName;
AppSettings* _appSettings;
double _progressPct;
int _currentPlanViewIndex;
......
......@@ -1245,7 +1245,6 @@ void SurveyComplexItem::_rebuildTransectsFromPolygon(bool refly, const QPolygonF
while (transectX < transectXMax) {
double transectYTop = boundingCenter.y() - halfWidth;
double transectYBottom = boundingCenter.y() + halfWidth;
lineList += QLineF(_rotatePoint(QPointF(transectX, transectYTop), boundingCenter, gridAngle), _rotatePoint(QPointF(transectX, transectYBottom), boundingCenter, gridAngle));
transectX += gridSpacing;
}
......
......@@ -95,4 +95,6 @@ WimaCorridorMapVisual 1.0 WimaCorridorMapVisual.qml
WimaItemEditor 1.0 WimaItemEditor.qml
WimaMapPolygonVisuals 1.0 WimaMapPolygonVisuals.qml
WimaMapPolylineVisuals 1.0 WimaMapPolylineVisuals.qml
SphericalSurveyMapVisual 1.0 SphericalSurveyMapVisual.qml
......@@ -97,7 +97,7 @@ QList<QPointF> Circle::approximate(int numberOfCorners) const
{
if ( numberOfCorners < 3)
return QList<QPointF>();
return approximateSektor(numberOfCorners, 0, 2*M_PI);
return approximateSektor(numberOfCorners+1, 0, 2*M_PI);
}
QList<QPointF> Circle::approximate(double angleDiscretisation) const
......@@ -107,37 +107,39 @@ QList<QPointF> Circle::approximate(double angleDiscretisation) const
QList<QPointF> Circle::approximateSektor(int numberOfCorners, double alpha1, double alpha2) const
{
if ( numberOfCorners < 3)
return QList<QPointF>();
return approximateSektor((alpha2-alpha1)/double(numberOfCorners-1), alpha1, alpha2);
}
QList<QPointF> Circle::approximateSektor(double angleDiscretisation, double alpha1, double alpha2) const
{
using namespace PlanimetryCalculus;
// truncate alpha1 to [0, 2*pi], fmod() does not work in this case
alpha1 = PlanimetryCalculus::truncateAngle(alpha1);
alpha2 = PlanimetryCalculus::truncateAngle(alpha2);
double deltaAlpha = PlanimetryCalculus::truncateAngle(alpha2 - alpha1);
angleDiscretisation = PlanimetryCalculus::truncateAngle(angleDiscretisation);
alpha1 = truncateAngle(alpha1);
alpha2 = truncateAngle(alpha2);
double deltaAlpha = truncateAngle(alpha2 - alpha1);
angleDiscretisation = truncateAngle(angleDiscretisation)*signum(angleDiscretisation);
if (angleDiscretisation > deltaAlpha || qFuzzyIsNull(angleDiscretisation))
if (fabs(angleDiscretisation) > deltaAlpha || qFuzzyIsNull(angleDiscretisation))
return QList<QPointF>();
QList<QPointF> sector;
QPointF vertex(-_circleRadius,0); // initial vertex
QPointF vertex0(_circleRadius,0); // initial vertex
double currentAngle = alpha1;
// rotate the vertex numberOfCorners-1 times add the origin and append to the polygon.
while(currentAngle < alpha2) {
PlanimetryCalculus::rotateReference(vertex, currentAngle);
sector.append(vertex + _circleOrigin);
do {
QPointF currentVertex = rotateReturn(vertex0, currentAngle);
sector.append(currentVertex + _circleOrigin);
currentAngle = PlanimetryCalculus::truncateAngle(currentAngle + angleDiscretisation);
}
}while(currentAngle < alpha2);
// append last point if necessarry
PlanimetryCalculus::rotateReference(vertex, alpha2);
vertex = vertex + _circleOrigin;
if ( !qFuzzyIsNull(PlanimetryCalculus::distance(sector.first(), vertex))
&& !qFuzzyIsNull(PlanimetryCalculus::distance(sector.last(), vertex )) ){
sector.append(vertex);
QPointF currentVertex = rotateReturn(vertex0, alpha2) + _circleOrigin;
if ( !qFuzzyIsNull(PlanimetryCalculus::distance(sector.first(), currentVertex))
&& !qFuzzyIsNull(PlanimetryCalculus::distance(sector.last(), currentVertex )) ){
sector.append(currentVertex);
}
return sector;
......
......@@ -4,9 +4,25 @@
const char* CircularSurveyComplexItem::settingsGroup = "Survey";
CircularSurveyComplexItem::CircularSurveyComplexItem(Vehicle *vehicle, bool flyView, const QString &kmlOrShpFile, QObject *parent)
: TransectStyleComplexItem (vehicle, flyView, settingsGroup, parent)
: TransectStyleComplexItem (vehicle, flyView, settingsGroup, parent)
, _referencePoint(QGeoCoordinate(47.770859, 16.531076,0))
{
}
void CircularSurveyComplexItem::setRefPoint(const QGeoCoordinate &refPt)
{
if (refPt != _referencePoint){
_referencePoint = refPt;
emit refPointChanged();
}
}
QGeoCoordinate CircularSurveyComplexItem::refPoint() const
{
return _referencePoint;
}
bool CircularSurveyComplexItem::load(const QJsonObject &complexObject, int sequenceNumber, QString &errorString)
......@@ -50,78 +66,120 @@ void CircularSurveyComplexItem::_rebuildTransectsPhase1()
using namespace PolygonCalculus;
using namespace PlanimetryCalculus;
if ( _surveyAreaPolygon.count() < 3)
return;
_transects.clear();
QPolygonF surveyPolygon = toQPolygonF(toCartesian2D(_surveyAreaPolygon.coordinateList(), _referencePoint));
QPolygonF boundingPolygon = surveyPolygon.boundingRect();
QVector<double> distances;
for (const QPointF &p : boundingPolygon) distances.append(norm(p));
QVector<double> angles;
for (const QPointF &p : boundingPolygon) angles.append(truncateAngle(angle(p)));
for (const QPointF &p : surveyPolygon) distances.append(norm(p));
double alpha1 = 0.95*(*std::min_element(angles.begin(), angles.end()));; // radiants
double alpha2 = 1.05*(*std::max_element(angles.begin(), angles.end())); // radiants; // radiants
double dalpha = 0.5/180*M_PI; // radiants
double r0 = 0.9*(*std::min_element(distances.begin(), distances.end())); // meter
double r1 = 1.1*(*std::max_element(distances.begin(), distances.end())); // meter
double dr = 1; // meter
double dr = 30; // meter
double r_min = dr; // meter
double r_max = (*std::max_element(distances.begin(), distances.end())); // meter
QPointF origin(0, 0);
IntersectType type;
if (!contains(surveyPolygon, origin, type)) {
QVector<double> angles;
for (const QPointF &p : surveyPolygon) angles.append(truncateAngle(angle(p)));
// determine r_min by successive approximation
double r = r_max;
while ( r > r_min) {
Circle circle(r, origin);
if (!intersects(circle, surveyPolygon)) {
r_min = r;
break;
}
r -= dr;
}
}
qWarning("r_min, r_max:");
qWarning() << r_min;
qWarning() << r_max;
QList<QPolygonF> convexPolygons;
decomposeToConvex(surveyPolygon, convexPolygons);
QPointF origin(0, 0);
QList<QPointF> fullPath;
QList<QList<QPointF>> fullPath;
for (int i = 0; i < convexPolygons.size(); i++){
const QPolygonF &polygon = convexPolygons[i];
double r = r0;
double r = r_min;
QList<QPointF> currPolyPath;
QList<QList<QPointF>> currPolyPath;
bool currentPolyPathUpdated = false;
int direction = 1;
while (r < r1) {
while (r < r_max) {
Circle circle(r, origin);
QList<QPointF> sector = circle.approximateSektor(dalpha, alpha1, alpha2);
QList<QPointF> sectorPath;
for ( const QPointF &p : sector) {
if (polygon.containsPoint(p, Qt::FillRule::OddEvenFill))
sectorPath.append(p);
QList<QPointFList> intersectPoints;
QList<IntersectType> typeList;
if (intersects(circle, polygon, intersectPoints, typeList)) {
if (intersectPoints.size() >= 1) {
// continue here
QPointF p1 = intersectPoints.first()[0];
QPointF p2 = intersectPoints.first()[1];
double beta1 = angle(p1);
double beta2 = angle(p2);
double alpha1 = fmin(beta1, beta2);
double alpha2 = fmax(beta1, beta2);
QList<QPointF> sector = circle.approximateSektor(direction*dalpha, alpha1, alpha2);
QList<QPointF> sectorPath;
for ( const QPointF &p : sector) {
if (polygon.containsPoint(p, Qt::FillRule::OddEvenFill))
sectorPath.append(p);
}
if (sectorPath.size() > 0 ) {
if (direction == -1){
direction = 1;
} else
direction = -1;
// use shortestPath() here if necessary, could be a problem if dr >>
currPolyPath.append(sectorPath);
currentPolyPathUpdated = true;
}
}
}
if (direction == -1){
reversePath(sectorPath);
direction = 1;
} else
direction = -1;;
// use shortestPath() here if necessary, could be a problem if dr >>
currPolyPath.append(sectorPath);
r += dr;
}
if (i > 0) {
QPointF start = fullPath.last();
QPointF end = currPolyPath.first();
QList<QPointF> path;
if(!shortestPath(surveyPolygon, start, end, path))
return;
path.removeFirst();
path.removeLast();
fullPath.append(path);
fullPath.append(fullPath);
if (currentPolyPathUpdated) {
if (fullPath.size() > 1) {
QPointF start = fullPath.last().last();
QPointF end = currPolyPath.last().first();
QList<QPointF> path;
if(!shortestPath(surveyPolygon, start, end, path))
return;
path.removeFirst();
path.removeLast();
currPolyPath.last().append(path);
}
fullPath.append(currPolyPath);
}
}
QList<QGeoCoordinate> geoPath = toGeo(fullPath, _referencePoint);
for ( const QGeoCoordinate &coordinate : geoPath) {
CoordInfo_t coordinfo = {coordinate, CoordTypeInterior};
_transects.append(coordinfo);
}
for ( const QList<QPointF> &transect : fullPath) {
QList<QGeoCoordinate> geoPath = toGeo(transect, _referencePoint);
QList<CoordInfo_t> transectList;
for ( const QGeoCoordinate &coordinate : geoPath) {
CoordInfo_t coordinfo = {coordinate, CoordTypeInterior};
transectList.append(coordinfo);
}
_transects.append(transectList);
}
}
......
......@@ -17,6 +17,14 @@ public:
/// @param kmlOrShpFile Polygon comes from this file, empty for default polygon
CircularSurveyComplexItem(Vehicle* vehicle, bool flyView, const QString& kmlOrShpFile, QObject* parent);
Q_PROPERTY(QGeoCoordinate refPoint READ refPoint WRITE setRefPoint NOTIFY refPointChanged)
// Property setters
void setRefPoint(const QGeoCoordinate &refPt);
// Property getters
QGeoCoordinate refPoint() const;
// Overrides from ComplexMissionItem
bool load (const QJsonObject& complexObject, int sequenceNumber, QString& errorString) final;
QString mapVisualQML (void) const final { return QStringLiteral("SpericalSurveyMapVisual.qml"); }
......@@ -29,20 +37,24 @@ public:
double timeBetweenShots (void) final;
// Overrides from VisualMissionionItem
QString commandDescription (void) const final { return tr("Spherical Survey"); }
QString commandName (void) const final { return tr("SphericalSurvey"); }
QString abbreviation (void) const final { return tr("Sph.S"); }
QString commandDescription (void) const final { return tr("Circular Survey"); }
QString commandName (void) const final { return tr("Circular Survey"); }
QString abbreviation (void) const final { return tr("C.S."); }
bool readyForSave (void) const final;
double additionalTimeDelay (void) const final;
static const char* settingsGroup;
signals:
void refPointChanged();
private slots:
// Overrides from TransectStyleComplexItem
void _rebuildTransectsPhase1 (void) final;
void _recalcComplexDistance (void) final;
void _recalcCameraShots (void) final;
private:
QGeoCoordinate _referencePoint; // center of the circular lanes, e.g. base station
};
......
add refpt gui and edit constructor
......@@ -17,84 +17,6 @@ namespace OptimisationTools {
* \sa QList
*/
template <class T>
bool dijkstraAlgorithm(const QList<T> &elements, int startIndex, int endIndex, QList<T> &elementPath, std::function<double(const T &, const T &)> distance) // don't seperate parameters with new lines or documentation will break
{
if ( elements.isEmpty() || startIndex < 0
|| startIndex >= elements.size() || endIndex < 0
|| endIndex >= elements.size()) {
return false;
}
//qWarning("optitools");
// Each element of type T gets stuff into a Node
/// @param distance is the distance between the Node and it's predecessor
struct Node{
T element;
double distance = std::numeric_limits<qreal>::infinity();
Node* predecessorNode = nullptr;
};
bool dijkstraAlgorithm(const QList<T> &elements, int startIndex, int endIndex, QList<T> &elementPath, std::function<double(const T &, const T &)> distance); // don't seperate parameters with new lines or documentation will break
// The list with all Nodes (elements)
QList<Node> nodeList;
// This list will be initalized with (pointer to) all elements of nodeList.
// Elements will be successively remove during the execution of the Dijkstra Algorithm.
QList<Node*> workingSet;
//append elements to node list
for (int i = 0; i < elements.size(); i++) {
Node node;
node.element = elements[i];
nodeList.append(node);
workingSet.append(&nodeList[i]);
}
nodeList[startIndex].distance = 0;
// Dijkstra Algorithm
// https://de.wikipedia.org/wiki/Dijkstra-Algorithmus
while (workingSet.size() > 0) {
// serach Node with minimal distance
double minDist = std::numeric_limits<qreal>::infinity();
int minDistIndex = 0;
for (int i = 0; i < workingSet.size(); i++) {
Node* node = workingSet.value(i);
double dist = node->distance;
if (dist < minDist) {
minDist = dist;
minDistIndex = i;
}
}
Node* u = workingSet.takeAt(minDistIndex);
//update distance
for (int i = 0; i < workingSet.size(); i++) {
Node* v = workingSet[i];
double dist = distance(u->element, v->element);
// is ther a alternative path which is shorter?
double alternative = u->distance + dist;
if (alternative < v->distance) {
v->distance = alternative;
v->predecessorNode = u;
}
}
}
// end Djikstra Algorithm
// reverse assemble path
Node* node = &nodeList[endIndex];
while (1) {
if (node == nullptr) {
if (elementPath[0] == elements[startIndex])// check if starting point was reached
break;
return false;
}
elementPath.prepend(node->element);
//Update Node
node = node->predecessorNode;
}
return true;
}
} // end OptimisationTools namespace
......@@ -5,8 +5,97 @@
#include <QPointF>
namespace OptimisationTools {
/*!
* \fn bool dijkstraAlgorithm(int startIndex, int endIndex, const QList<T> elements, QList<T> &elementPath, double(*distance)(const T &t1, const T &t2))
* Calculates the shortest path between the elements stored in \a elements.
* The \l {Dijkstra Algorithm} is used to find the shorest path.
* Stores the result inside \a elementPath when sucessfull.
* The function handle \a distance is used to calculate the distance between two elements. The distance must be positive.
* Returns \c true if successful, \c false else.
*
* \sa QList
*/
template <class T>
bool dijkstraAlgorithm(const QList<T> &elements, int startIndex, int endIndex, QList<T> &elementPath, std::function<double(const T &, const T &)> distance);
bool dijkstraAlgorithm(const QList<T> &elements, int startIndex, int endIndex, QList<T> &elementPath, std::function<double(const T &, const T &)> distance)
{
if ( elements.isEmpty() || startIndex < 0
|| startIndex >= elements.size() || endIndex < 0
|| endIndex >= elements.size()) {
return false;
}
//qWarning("optitools");
// Each element of type T gets stuff into a Node
/// @param distance is the distance between the Node and it's predecessor
struct Node{
T element;
double distance = std::numeric_limits<qreal>::infinity();
Node* predecessorNode = nullptr;
};
// The list with all Nodes (elements)
QList<Node> nodeList;
// This list will be initalized with (pointer to) all elements of nodeList.
// Elements will be successively remove during the execution of the Dijkstra Algorithm.
QList<Node*> workingSet;
//append elements to node list
for (int i = 0; i < elements.size(); i++) {
Node node;
node.element = elements[i];
nodeList.append(node);
workingSet.append(&nodeList[i]);
}
nodeList[startIndex].distance = 0;
// Dijkstra Algorithm
// https://de.wikipedia.org/wiki/Dijkstra-Algorithmus
while (workingSet.size() > 0) {
// serach Node with minimal distance
double minDist = std::numeric_limits<qreal>::infinity();
int minDistIndex = 0;
for (int i = 0; i < workingSet.size(); i++) {
Node* node = workingSet.value(i);
double dist = node->distance;
if (dist < minDist) {
minDist = dist;
minDistIndex = i;
}
}
Node* u = workingSet.takeAt(minDistIndex);
//update distance
for (int i = 0; i < workingSet.size(); i++) {
Node* v = workingSet[i];
double dist = distance(u->element, v->element);
// is ther a alternative path which is shorter?
double alternative = u->distance + dist;
if (alternative < v->distance) {
v->distance = alternative;
v->predecessorNode = u;
}
}
}
// end Djikstra Algorithm
// reverse assemble path
Node* node = &nodeList[endIndex];
while (1) {
if (node == nullptr) {
if (elementPath[0] == elements[startIndex])// check if starting point was reached
break;
return false;
}
elementPath.prepend(node->element);
//Update Node
node = node->predecessorNode;
}
return true;
}
}
......@@ -480,16 +480,7 @@ angle
return line;
}
/*!
* \fntemplate <typename T> int signum(T val)
* Returns the signum of a value \a val.
*
* \sa QPair, QList
*/
template <typename T> int signum(T val)
{
return (T(0) < val) - (val < T(0));
}
bool intersects(const QLineF &line1, const QLineF &line2, QPointF &intersectionPt)
{
......@@ -632,6 +623,70 @@ angle
return qAtan2(p1.y(), p1.x());
}
bool intersects(const Circle &circle, const QPolygonF &polygon, QList<QPointFList> &intersectionPoints, NeighbourList &neighbourList, IntersectList &typeList)
{
using namespace PolygonCalculus;
for (int i = 0; i < polygon.size(); i++) {
QPointF p1 = polygon[i];
int j = nextVertexIndex(polygon.size(), i);
QPointF p2 = polygon[j];
QLineF line(p1, p2);
QPointFList lineIntersecPts;
IntersectType type;
if (intersects(circle, line, lineIntersecPts, type)) {
QPair<int, int> neigbours;
neigbours.first = i;
neigbours.second = j;
neighbourList.append(neigbours);
typeList.append(type);
intersectionPoints.append(lineIntersecPts);
}
}
if (intersectionPoints.size() > 0)
return true;
else {
return false;
}
}
bool intersects(const Circle &circle, const QPolygonF &polygon, QList<QPointFList> &intersectionPoints, NeighbourList &neighbourList)
{
QList<IntersectType> types;
return intersects(circle, polygon, intersectionPoints, neighbourList, types);
}
bool intersects(const Circle &circle, const QPolygonF &polygon, QList<QPointFList> &intersectionPoints, IntersectList &typeList)
{
NeighbourList neighbourList;
return intersects(circle, polygon, intersectionPoints, neighbourList, typeList);
}