275 lines
9.0 KiB
C++
Executable File
275 lines
9.0 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* GraphicalObjectPath
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
*/
|
|
|
|
// Own
|
|
#include "graphical_object_path.h"
|
|
#include <Map/situation_map_utils.h> // operator<<
|
|
|
|
|
|
// ESRI
|
|
#include <GraphicsOverlay.h>
|
|
#include <PolygonBuilder.h>
|
|
#include <PolylineBuilder.h>
|
|
#include <SimpleLineSymbol.h>
|
|
#include <SimpleFillSymbol.h>
|
|
#include <GeoView.h>
|
|
#include <GeometryEngine.h>
|
|
#include <SpatialReference.h>
|
|
#include <Polyline.h>
|
|
#include <Polygon.h>
|
|
#include <Graphic.h>
|
|
#include <LinearUnit.h>
|
|
#include <AngularUnit.h>
|
|
|
|
// Qt
|
|
|
|
|
|
namespace SituationMap
|
|
{
|
|
|
|
QLatin1String toString(const GraphicalObjectPathType subType)
|
|
{
|
|
switch (subType)
|
|
{
|
|
case GraphicalObjectPathType::Polyline:
|
|
return QLatin1String("Polyline");
|
|
break;
|
|
case GraphicalObjectPathType::Polygon:
|
|
return QLatin1String("Polygon");
|
|
break;
|
|
} // switch
|
|
return QLatin1String("GraphicalObjectPathTypeERROR");
|
|
}
|
|
|
|
|
|
GraphicalObjectPath::GraphicalObjectPath(const GraphicalObjectPathType type
|
|
, const Esri::ArcGISRuntime::GeoView *geoView
|
|
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
|
|
, const QString &debugInfo
|
|
, const UniqueMapId &uniqueMapId)
|
|
: BaseClass(geoView, graphicsLayer, debugInfo, uniqueMapId)
|
|
, m_pathType(type)
|
|
, m_logger(getLogger("GraphicalObjectPath"))
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
|
|
<< " m_pathType=" << m_pathType;
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
|
|
<< " m_pathType=" << m_pathType;
|
|
}
|
|
|
|
GraphicalObjectPath::~GraphicalObjectPath()
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
|
|
<< " m_pathType=" << m_pathType;
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
|
|
<< " m_pathType=" << m_pathType;
|
|
}
|
|
|
|
bool GraphicalObjectPath::create()
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
|
|
|
|
bool success = BaseClass::create();
|
|
if (!success)
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
|
|
<< " create failed";
|
|
return false;
|
|
}
|
|
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
|
|
<< " success = " << success
|
|
// << " drawOrder = " << m_graphic->drawOrder()
|
|
;
|
|
return success;
|
|
}
|
|
|
|
|
|
bool GraphicalObjectPath::updateViewImpl()
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
|
|
<< " m_positions= " << m_positions.value()
|
|
<< ", m_maxSegmentLength=" << m_maxSegmentLength;
|
|
|
|
QSharedPointer<Esri::ArcGISRuntime::MultipartBuilder> builder;
|
|
|
|
// some checks:
|
|
switch (m_pathType)
|
|
{
|
|
case GraphicalObjectPathType::Polyline:
|
|
if (!this->isMultiPoint())
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " incorrect number of positions"
|
|
<< " (" << this->positions().count() << ")";
|
|
return false;
|
|
}
|
|
builder = QSharedPointer<Esri::ArcGISRuntime::PolylineBuilder>(new Esri::ArcGISRuntime::PolylineBuilder(spatialReference()));
|
|
|
|
break;
|
|
case GraphicalObjectPathType::Polygon:
|
|
if (!this->isArea())
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " incorrect number of positions"
|
|
<< " (" << this->positions().count() << ")";
|
|
return false;
|
|
}
|
|
builder = QSharedPointer<Esri::ArcGISRuntime::PolygonBuilder>(new Esri::ArcGISRuntime::PolygonBuilder(spatialReference()));
|
|
break;
|
|
} // switch
|
|
|
|
|
|
if (! builder)
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
|
|
<< " no builder";
|
|
return false;
|
|
}
|
|
|
|
bool success = create();
|
|
if (!success)
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
|
|
<< " create failed";
|
|
return false;
|
|
}
|
|
|
|
success = BaseClass::updateViewImpl();
|
|
if (!success)
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
|
|
<< " updateView failed";
|
|
return false;
|
|
}
|
|
|
|
|
|
// real work:
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
|
|
<< " update geometry";
|
|
|
|
|
|
const PositionCont &posCont = m_positions.value();
|
|
for (const Point3D &pos : posCont)
|
|
builder->addPoint(pos.x(), pos.y(), pos.z());
|
|
|
|
if (! builder->isSketchValid())
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
|
|
<< " builder -> sketch invalid";
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// apply attributes:
|
|
//
|
|
|
|
// N. Thoden, 13.02.2018
|
|
// Case #02062713 [BOS] BasicSceneView_lineNotComplete
|
|
// If a line has a line of ~10km (Borderline)
|
|
// the line may 'move' on the ground (3D, RenderMode::Dynamic, SurfarcePlacement::Draped)
|
|
// To avoid these kind of effect, the advice is to densify the geometry
|
|
// [similar: Case #02054233 [BOS] LineArtefacts in 3D ->
|
|
// BUG-000111565 : Lines created on the GraphicsOverlay with "Dynamic" Rendering mode on 3D doesn't render completely when zooming in]
|
|
|
|
//
|
|
// N. Thoden, 29.03.2018
|
|
// Consulting with Luke Smallwood / using the V100.2.1. debug libs:
|
|
// densify leads to an assert, so avoid densify
|
|
// (until now densify does not lead to an improvement..)
|
|
|
|
//
|
|
// N. Thoden, 19.04.2021
|
|
// [GUEZE-495]: 3D Lagedarstellung Trefferlinien
|
|
// Linie fehlt teilweise
|
|
// jetzt (typeweise) per m_maxSegmentLength aktivierbar
|
|
|
|
switch (m_pathType)
|
|
{
|
|
case GraphicalObjectPathType::Polyline:
|
|
{
|
|
const Esri::ArcGISRuntime::Polyline &polyline =
|
|
static_cast<Esri::ArcGISRuntime::PolylineBuilder *>(builder.data())->toPolyline();
|
|
if (m_maxSegmentLength > 0)
|
|
{
|
|
m_graphic->setGeometry(Esri::ArcGISRuntime::GeometryEngine::densifyGeodetic(polyline,
|
|
m_maxSegmentLength,
|
|
Esri::ArcGISRuntime::LinearUnit::meters(),
|
|
Esri::ArcGISRuntime::GeodeticCurveType::Geodesic));
|
|
} else {
|
|
m_graphic->setGeometry(polyline);
|
|
} // if (densify)
|
|
assignLineStyleToGraphic();
|
|
}
|
|
break;
|
|
case GraphicalObjectPathType::Polygon:
|
|
{
|
|
const Esri::ArcGISRuntime::Polygon &polygon =
|
|
static_cast<Esri::ArcGISRuntime::PolygonBuilder *>(builder.data())->toPolygon();
|
|
|
|
if (m_maxSegmentLength > 0)
|
|
{
|
|
m_graphic->setGeometry(Esri::ArcGISRuntime::GeometryEngine::densifyGeodetic(polygon,
|
|
m_maxSegmentLength,
|
|
Esri::ArcGISRuntime::LinearUnit::meters(),
|
|
Esri::ArcGISRuntime::GeodeticCurveType::Geodesic));
|
|
} else {
|
|
m_graphic->setGeometry(polygon);
|
|
}
|
|
assignFillStyleToGraphic();
|
|
}
|
|
break;
|
|
} // switch
|
|
|
|
// Cast geometry to Multipart for vertex count check
|
|
const Esri::ArcGISRuntime::Geometry geom = m_graphic->geometry();
|
|
const Esri::ArcGISRuntime::Multipart* multipart = nullptr;
|
|
if (geom.geometryType() == Esri::ArcGISRuntime::GeometryType::Polyline)
|
|
multipart = static_cast<const Esri::ArcGISRuntime::Polyline*>(&geom);
|
|
else if (geom.geometryType() == Esri::ArcGISRuntime::GeometryType::Polygon)
|
|
multipart = static_cast<const Esri::ArcGISRuntime::Polygon*>(&geom);
|
|
|
|
const int count = multipart ? AbstractGraphicalObject::countOfPolygonFirstPart(*multipart) : 0;
|
|
if (count > 1000)
|
|
WARNING_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
|
|
<< ", huge amount of vertices, countOfPolygonFirstPart = " << count;
|
|
else
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
|
|
<< ", amount of vertices, countOfPolygonFirstPart = " << count;
|
|
|
|
success = addUpdateGraphic();
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
|
|
<< " success = " << success
|
|
<< " drawOrder = " << m_graphic->zIndex();
|
|
return success;
|
|
}
|
|
|
|
double GraphicalObjectPath::maxSegmentLength() const
|
|
{
|
|
return m_maxSegmentLength;
|
|
}
|
|
|
|
void GraphicalObjectPath::setMaxSegmentLength(double maxSegmentLength)
|
|
{
|
|
m_maxSegmentLength = maxSegmentLength;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// output operator:
|
|
//-----------------------------------------------------------------------------
|
|
std::ostream &operator<<(std::ostream &stream,
|
|
const GraphicalObjectPathType &value)
|
|
{
|
|
stream << toString(value).latin1();
|
|
return stream;
|
|
}
|
|
|
|
} // namespace SituationMap
|