Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions images/images.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,7 @@
<file>themes/default/mIconSnappingAllLayers.svg</file>
<file>themes/default/mIconSnappingArea.svg</file>
<file>themes/default/mIconSnappingCentroid.svg</file>
<file>themes/default/mIconSnappingDisabled.svg</file>
<file>themes/default/mIconSnappingMiddle.svg</file>
<file>themes/default/mIconSnappingOnScale.svg</file>
<file>themes/default/mIconSnappingVertex.svg</file>
Expand Down
7 changes: 7 additions & 0 deletions images/themes/default/mIconSnappingDisabled.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions python/3d/auto_generated/qgsraycasthit.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ Sets the hit ``point`` position in 3d map coordinates
%Docstring
Sets the point cloud point ``attributes``, empty map if hit was not on a
point cloud point
%End

void addProperty( const QString &key, const QVariant &value );
%Docstring
Adds a property to the hit
%End

};
Expand Down
5 changes: 5 additions & 0 deletions python/PyQt6/3d/auto_generated/qgsraycasthit.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ Sets the hit ``point`` position in 3d map coordinates
%Docstring
Sets the point cloud point ``attributes``, empty map if hit was not on a
point cloud point
%End

void addProperty( const QString &key, const QVariant &value );
%Docstring
Adds a property to the hit
%End

};
Expand Down
2 changes: 1 addition & 1 deletion src/3d/qgs3dmapcanvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ void Qgs3DMapCanvas::highlightFeature( const QgsFeature &feature, QgsMapLayer *l
const QgsSettings settings;
const QColor color = QColor( settings.value( u"Map/highlight/color"_s, Qgis::DEFAULT_HIGHLIGHT_COLOR.name() ).toString() );
band->setColor( color );
band->setMarkerType( QgsRubberBand3D::MarkerType::Square );
band->setMarkerShape( Qgis::MarkerShape::Square );
if ( QgsPointCloudLayer3DRenderer *pcRenderer = dynamic_cast<QgsPointCloudLayer3DRenderer *>( layer->renderer3D() ) )
{
band->setWidth( pcRenderer->symbol()->pointSize() + 1 );
Expand Down
2 changes: 1 addition & 1 deletion src/3d/qgsglobechunkedentity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ QList<QgsRayCastHit> QgsGlobeEntity::rayIntersection( const QgsRay3D &ray, const
{
QVector3D nodeIntPoint;
int triangleIndex = -1;
bool success = QgsRayCastingUtils::rayMeshIntersection( rend, ray, context.maximumDistance(), nodeGeoTransform->matrix(), nodeIntPoint, triangleIndex );
bool success = QgsRayCastingUtils::rayMeshIntersection( rend, ray, context, nodeGeoTransform->matrix(), nodeIntPoint, triangleIndex );
if ( success )
{
float dist = ( ray.origin() - nodeIntPoint ).length();
Expand Down
5 changes: 5 additions & 0 deletions src/3d/qgsraycasthit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,8 @@ void QgsRayCastHit::setProperties( const QVariantMap &attributes )
{
mAttributes = attributes;
}

void QgsRayCastHit::addProperty( const QString &key, const QVariant &value )
{
mAttributes[key] = value;
}
3 changes: 3 additions & 0 deletions src/3d/qgsraycasthit.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ class _3D_EXPORT QgsRayCastHit
//! Sets the point cloud point \a attributes, empty map if hit was not on a point cloud point
void setProperties( const QVariantMap &attributes );

//! Adds a property to the hit
void addProperty( const QString &key, const QVariant &value );

private:
double mDistance = -1.; //!< Distance from ray's origin
QgsVector3D mPos; //!< Hit position in 3d map coordinates
Expand Down
52 changes: 39 additions & 13 deletions src/3d/qgsraycastingutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "qgsaabb.h"
#include "qgslogger.h"
#include "qgsray3d.h"
#include "qgsraycastcontext.h"

#include <Qt3DCore/QAttribute>
#include <Qt3DCore/QBuffer>
Expand Down Expand Up @@ -111,7 +112,22 @@ namespace QgsRayCastingUtils
return true;
}

bool rayMeshIntersection( Qt3DRender::QGeometryRenderer *geometryRenderer, const QgsRay3D &r, float maxDist, const QMatrix4x4 &worldTransform, QVector3D &intPt, int &triangleIndex )
double rayTriangleMinAngle( const QgsRay3D &ray, const QList<QVector3D> &pointList, QVector3D &minPoint )
{
double minAngle = 999999;
for ( const QVector3D point : pointList )
{
double angle = ray.angleToPoint( point );
if ( angle < minAngle )
{
minAngle = angle;
minPoint = point;
}
}
return minAngle;
}

bool rayMeshIntersection( Qt3DRender::QGeometryRenderer *geometryRenderer, const QgsRay3D &r, const QgsRayCastContext &context, const QMatrix4x4 &worldTransform, QVector3D &intPt, int &triangleIndex )
{
if ( geometryRenderer->primitiveType() != Qt3DRender::QGeometryRenderer::Triangles )
{
Expand Down Expand Up @@ -198,7 +214,7 @@ namespace QgsRayCastingUtils
vertexCount = positionAttr->count();
}

QVector3D intersectionPt, minIntersectionPt;
QVector3D intersectionPt, minIntersectionPt, minAnglePt;
float minDistance = -1;

for ( int i = 0; i < vertexCount; i += 3 )
Expand Down Expand Up @@ -252,18 +268,28 @@ namespace QgsRayCastingUtils
// We're testing both triangle orientations here and ignoring the culling mode.
// We should probably respect the culling mode used for the entity and perform a
// single test using the properly oriented triangle.
if ( QgsRayCastingUtils::rayTriangleIntersection( r, maxDist, tA, tB, tC, uvw, t ) || QgsRayCastingUtils::rayTriangleIntersection( r, maxDist, tA, tC, tB, uvw, t ) )
if ( QgsRayCastingUtils::rayTriangleIntersection( r, context.maximumDistance(), tA, tB, tC, uvw, t ) || QgsRayCastingUtils::rayTriangleIntersection( r, context.maximumDistance(), tA, tC, tB, uvw, t ) )
{
intersectionPt = r.point( t * context.maximumDistance() );
}
else if ( ( minDistance == -1 ) && QgsRayCastingUtils::rayTriangleMinAngle( r, { tA, tB, tC }, minAnglePt ) < context.angleThreshold() )
{
// Do not use angle Threshold if an intersection point has already been found
intersectionPt = minAnglePt;
}
else
{
continue;
}

const float distance = r.projectedDistance( intersectionPt );

// we only want the first intersection of the ray with the mesh (closest to the ray origin)
if ( minDistance == -1 || distance < minDistance )
{
intersectionPt = r.point( t * maxDist );
const float distance = r.projectedDistance( intersectionPt );

// we only want the first intersection of the ray with the mesh (closest to the ray origin)
if ( minDistance == -1 || distance < minDistance )
{
triangleIndex = static_cast<int>( i / 3 );
minDistance = distance;
minIntersectionPt = intersectionPt;
}
triangleIndex = static_cast<int>( i / 3 );
minDistance = distance;
minIntersectionPt = intersectionPt;
}
}

Expand Down
9 changes: 8 additions & 1 deletion src/3d/qgsraycastingutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

class QgsAABB;
class QgsRay3D;
class QgsRayCastContext;

namespace Qt3DRender
{
Expand All @@ -44,13 +45,19 @@ namespace QgsRayCastingUtils
*/
bool rayTriangleIntersection( const QgsRay3D &ray, float maxDist, const QVector3D &a, const QVector3D &b, const QVector3D &c, QVector3D &uvw, float &t );

/**
* Returns the minimum angle between a ray and a list of point
* \since QGIS 4.0
*/
double rayTriangleMinAngle( const QgsRay3D &ray, const QList<QVector3D> &pointList, QVector3D &minPoint );

/**
* Tests whether a triangular mesh is intersected by a ray. Returns whether an intersection
* was found. If found, it outputs the point at which the intersection happened in world coordinates and
* the index of the intersecting triangle.
* \since QGIS 4.0
*/
bool rayMeshIntersection( Qt3DRender::QGeometryRenderer *geometryRenderer, const QgsRay3D &r, float maxDist, const QMatrix4x4 &worldTransform, QVector3D &intPt, int &triangleIndex );
bool rayMeshIntersection( Qt3DRender::QGeometryRenderer *geometryRenderer, const QgsRay3D &r, const QgsRayCastContext &context, const QMatrix4x4 &worldTransform, QVector3D &intPt, int &triangleIndex );

} // namespace QgsRayCastingUtils

Expand Down
14 changes: 12 additions & 2 deletions src/3d/qgsraycastresult.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,12 @@ QList<QgsRayCastHit> QgsRayCastResult::allHits() const

void QgsRayCastResult::addLayerHits( QgsMapLayer *layer, const QList<QgsRayCastHit> &hits )
{
mLayerResults[layer].append( hits );
for ( auto hit : hits )
{
QgsRayCastHit hitWithLayerId = hit;
hitWithLayerId.addProperty( u"layerId"_s, layer->id() );
mLayerResults[layer].append( hitWithLayerId );
}
if ( !mLayerPointers.contains( layer ) )
{
mLayerPointers[layer] = layer;
Expand All @@ -86,5 +91,10 @@ void QgsRayCastResult::addLayerHits( QgsMapLayer *layer, const QList<QgsRayCastH

void QgsRayCastResult::addTerrainHits( const QList<QgsRayCastHit> &hits )
{
mTerrainResults.append( hits );
for ( auto hit : hits )
{
QgsRayCastHit hitWithLayerId = hit;
hitWithLayerId.addProperty( u"layerId"_s, "terrain" );
mTerrainResults.append( hitWithLayerId );
}
}
44 changes: 40 additions & 4 deletions src/3d/qgsrubberband3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "qgslinestring.h"
#include "qgslinevertexdata_p.h"
#include "qgsmarkersymbol.h"
#include "qgsmarkersymbollayer.h"
#include "qgsmessagelog.h"
#include "qgspoint3dbillboardmaterial.h"
#include "qgspolygon.h"
Expand Down Expand Up @@ -78,7 +79,7 @@ void QgsRubberBand3D::setupMarker( Qt3DCore::QEntity *parentEntity )
mMarkerGeometryRenderer->setGeometry( mMarkerGeometry );
mMarkerGeometryRenderer->setVertexCount( mMarkerGeometry->count() );

setMarkerType( mMarkerType );
setMarkerShape( mMarkerType );
mMarkerEntity->addComponent( mMarkerGeometryRenderer );

mMarkerTransform = new QgsGeoTransform;
Expand Down Expand Up @@ -272,6 +273,14 @@ void QgsRubberBand3D::setOutlineColor( const QColor color )
}

void QgsRubberBand3D::setMarkerType( const MarkerType marker )
{
if ( marker == QgsRubberBand3D::Square )
setMarkerShape( Qgis::MarkerShape::Square );
else
setMarkerShape( Qgis::MarkerShape::Circle );
}

void QgsRubberBand3D::setMarkerShape( const Qgis::MarkerShape marker )
{
mMarkerType = marker;

Expand All @@ -284,22 +293,30 @@ void QgsRubberBand3D::setMarkerType( const MarkerType marker )
{ u"outline_color"_s, mOutlineColor.value() ? mOutlineColor.name() : mColor.name() },
{ u"outline_style"_s, QgsSymbolLayerUtils::encodePenStyle( mMarkerOutlineStyle ) },
{ u"outline_width"_s, QString::number( lineOrPolygon ? 0.5 : 1 ) },
{ u"name"_s, mMarkerType == Square ? u"square"_s : u"circle"_s }
{ u"name"_s, QgsSimpleMarkerSymbolLayerBase::encodeShape( mMarkerType ) }
};

mMarkerSymbol = QgsMarkerSymbol::createSimple( props );
updateMarkerMaterial();
}

QgsRubberBand3D::MarkerType QgsRubberBand3D::markerType() const
Qgis::MarkerShape QgsRubberBand3D::markerShape() const
{
return mMarkerType;
}

QgsRubberBand3D::MarkerType QgsRubberBand3D::markerType() const
{
if ( mMarkerType == Qgis::MarkerShape::Square )
return QgsRubberBand3D::Square;

return QgsRubberBand3D::Circle;
}

void QgsRubberBand3D::setMarkerOutlineStyle( const Qt::PenStyle style )
{
mMarkerOutlineStyle = style;
setMarkerType( markerType() );
setMarkerShape( markerShape() );
}

Qt::PenStyle QgsRubberBand3D::markerOutlineStyle() const
Expand Down Expand Up @@ -503,4 +520,23 @@ void QgsRubberBand3D::updateMarkerMaterial()
mMarkerMaterial = nullptr;
}
}

void QgsRubberBand3D::setEnabled( bool enabled )
{
if ( mMarkerEntity )
{
mMarkerEntity->setEnabled( enabled );
}

if ( mLineEntity )
{
mLineEntity->setEnabled( enabled );
}

if ( mPolygonEntity )
{
mPolygonEntity->setEnabled( enabled );
}
}

/// @endcond
34 changes: 30 additions & 4 deletions src/3d/qgsrubberband3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,10 @@ namespace Qt3DRender
class _3D_EXPORT QgsRubberBand3D
{
public:
//! Icons
/**
* \brief Icons enum
* \deprecated QGIS 4.0. Use Qgis::MarkerShape instead.
*/
enum MarkerType
{

Expand Down Expand Up @@ -121,13 +124,29 @@ class _3D_EXPORT QgsRubberBand3D

/**
* Sets the \a marker type to highlight point geometries and line vertices.
* \deprecated QGIS 4.0. Use setMarkerShape(Qgis::MarkerShape) instead.
*/
Q_DECL_DEPRECATED void setMarkerType( MarkerType marker );

/**
* Sets the \a marker type to highlight point geometries and line vertices.
*
* \since QGIS 4.0
*/
void setMarkerShape( Qgis::MarkerShape marker );

/**
* Returns the current marker type to highlight point geometries and line vertices.
* \deprecated QGIS 4.0. Use markerShape().
*/
void setMarkerType( MarkerType marker );
Q_DECL_DEPRECATED MarkerType markerType() const;

/**
* Returns the current marker type to highlight point geometries and line vertices.
*
* \since QGIS 4.0
*/
MarkerType markerType() const;
Qgis::MarkerShape markerShape() const;

/**
* Sets the marker outline style
Expand Down Expand Up @@ -203,6 +222,13 @@ class _3D_EXPORT QgsRubberBand3D

bool isEmpty() const { return mGeometry.isEmpty(); }

/**
* Sets whether the rubberband is enabled.
*
* \since QGIS 4.0
*/
void setEnabled( bool enabled );

private:
void updateGeometry();
void updateMarkerMaterial();
Expand All @@ -222,7 +248,7 @@ class _3D_EXPORT QgsRubberBand3D
Qgis::GeometryType mGeometryType = Qgis::GeometryType::Line;

//! point and vertex marker type
MarkerType mMarkerType = Circle;
Qgis::MarkerShape mMarkerType = Qgis::MarkerShape::Circle;
float mWidth = 3.f;
QColor mColor = Qt::red;
QColor mOutlineColor;
Expand Down
13 changes: 12 additions & 1 deletion src/3d/qgstessellatedpolygongeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,19 @@ static int binary_search( uint v, const uint *data, int count )
}


QgsFeatureId QgsTessellatedPolygonGeometry::triangleIndexToFeatureId( uint triangleIndex ) const
QgsFeatureId QgsTessellatedPolygonGeometry::triangleIndexToFeatureId( uint triangleIndex, QVector3D ( *facePoints )[3] ) const
{
const int i = binary_search( triangleIndex, mTriangleIndexStartingIndices.constData(), mTriangleIndexStartingIndices.count() );
if ( i != -1 && facePoints )
{
for ( int idx = 0; idx < 3; idx++ )
{
const unsigned int vertexOffsetBytes = ( idx + 3 * triangleIndex ) * mPositionAttribute->byteStride();
const float *vertPtr = reinterpret_cast<const float *>( mVertexBuffer->data() + vertexOffsetBytes );
( *facePoints )[idx].setX( vertPtr[0] );
( *facePoints )[idx].setY( vertPtr[1] );
( *facePoints )[idx].setZ( vertPtr[2] );
}
}
return i != -1 ? mTriangleIndexFids[i] : FID_NULL;
}
Loading