21 #include <Qt3DRender/QCamera> 
   26 namespace QgsRayCastingUtils
 
   34     : m_direction( 0.0f, 0.0f, 1.0f )
 
   38   Ray3D::Ray3D( QVector3D origin, QVector3D direction, 
float distance )
 
   40     , m_direction( direction )
 
   41     , m_distance( distance )
 
   44   QVector3D Ray3D::origin()
 const 
   49   void Ray3D::setOrigin( QVector3D value )
 
   54   QVector3D Ray3D::direction()
 const 
   59   void Ray3D::setDirection( QVector3D value )
 
   67   float Ray3D::distance()
 const 
   72   void Ray3D::setDistance( 
float distance )
 
   74     m_distance = distance;
 
   77   QVector3D Ray3D::point( 
float t )
 const 
   79     return m_origin + t * m_direction;
 
   82   Ray3D &Ray3D::transform( 
const QMatrix4x4 &matrix )
 
   84     m_origin = matrix * m_origin;
 
   85     m_direction = matrix.mapVector( m_direction );
 
   90   Ray3D Ray3D::transformed( 
const QMatrix4x4 &matrix )
 const 
   92     return Ray3D( matrix * m_origin, matrix.mapVector( m_direction ) );
 
   97     return m_origin == other.origin() && m_direction == other.direction();
 
  102     return !( *
this == other );
 
  105   bool Ray3D::contains( QVector3D point )
 const 
  107     QVector3D ppVec( point - m_origin );
 
  108     if ( ppVec.isNull() ) 
 
  110     const float dot = QVector3D::dotProduct( ppVec, m_direction );
 
  111     if ( qFuzzyIsNull( dot ) )
 
  113     return qFuzzyCompare( dot * dot, ppVec.lengthSquared() * m_direction.lengthSquared() );
 
  116   bool Ray3D::contains( 
const Ray3D &ray )
 const 
  118     const float dot = QVector3D::dotProduct( m_direction, ray.direction() );
 
  119     if ( !qFuzzyCompare( dot * dot, m_direction.lengthSquared() * ray.direction().lengthSquared() ) )
 
  121     return contains( ray.origin() );
 
  124   float Ray3D::projectedDistance( QVector3D point )
 const 
  126     Q_ASSERT( !m_direction.isNull() );
 
  128     return QVector3D::dotProduct( point - m_origin, m_direction ) /
 
  129            m_direction.lengthSquared();
 
  132   QVector3D Ray3D::project( QVector3D vector )
 const 
  134     QVector3D norm = m_direction.normalized();
 
  135     return QVector3D::dotProduct( vector, norm ) * norm;
 
  139   float Ray3D::distance( QVector3D point )
 const 
  141     float t = projectedDistance( point );
 
  142     return ( point - ( m_origin + t * m_direction ) ).length();
 
  145   QDebug 
operator<<( QDebug dbg, 
const Ray3D &ray )
 
  147     QDebugStateSaver saver( dbg );
 
  148     dbg.nospace() << 
"QRay3D(origin(" 
  149                   << ray.origin().x() << 
", " << ray.origin().y() << 
", " 
  150                   << ray.origin().z() << 
") - direction(" 
  151                   << ray.direction().x() << 
", " << ray.direction().y() << 
", " 
  152                   << ray.direction().z() << 
"))";
 
  175   ray( 
double xO, 
double yO, 
double zO, 
double xD, 
double yD, 
double zD )
 
  177     origin[0] = xO; origin[1] = yO; origin[2] = zO;
 
  178     dir[0] = xD; dir[1] = yD; dir[2] = zD;
 
  179     dir_inv[0] = 1 / dir[0]; dir_inv[1] = 1 / dir[1]; dir_inv[2] = 1 / dir[2];
 
  181   ray( 
const QgsRayCastingUtils::Ray3D &r )
 
  184     origin[0] = r.origin().x(); origin[1] = r.origin().y(); origin[2] = r.origin().z();
 
  185     dir[0] = r.direction().x(); dir[1] = r.direction().y(); dir[2] = r.direction().z();
 
  186     dir_inv[0] = 1 / dir[0]; dir_inv[1] = 1 / dir[1]; dir_inv[2] = 1 / dir[2];
 
  196 bool intersection( 
const box &b, 
const ray &r )
 
  198   double t1 = ( b.min[0] - r.origin[0] ) * r.dir_inv[0];
 
  199   double t2 = ( b.max[0] - r.origin[0] ) * r.dir_inv[0];
 
  201   double tmin = std::min( t1, t2 );
 
  202   double tmax = std::max( t1, t2 );
 
  204   for ( 
int i = 1; i < 3; ++i )
 
  206     t1 = ( b.min[i] - r.origin[i] ) * r.dir_inv[i];
 
  207     t2 = ( b.max[i] - r.origin[i] ) * r.dir_inv[i];
 
  209     tmin = std::max( tmin, std::min( std::min( t1, t2 ), tmax ) );
 
  210     tmax = std::min( tmax, std::max( std::max( t1, t2 ), tmin ) );
 
  213   return tmax > std::max( tmin, 0.0 );
 
  217 namespace QgsRayCastingUtils
 
  220   bool rayBoxIntersection( 
const Ray3D &r, 
const QgsAABB &aabb )
 
  225     if ( b.min[0] == b.max[0] ) b.max[0] += 0.1;
 
  226     if ( b.min[1] == b.max[1] ) b.max[1] += 0.1;
 
  227     if ( b.min[2] == b.max[2] ) b.max[2] += 0.1;
 
  229     return intersection( b, ray( r ) );
 
  233   bool rayPlaneIntersection( 
const Ray3D &r, 
const Plane3D &plane, QVector3D &pt )
 
  235     float denom = QVector3D::dotProduct( plane.normal, r.direction() );
 
  236     if ( std::abs( denom ) > 0.0001f ) 
 
  238       float t = QVector3D::dotProduct( plane.center - r.origin(), plane.normal ) / denom;
 
  250   bool rayTriangleIntersection( 
const Ray3D &ray,
 
  260     const QVector3D ab = b - a;
 
  261     const QVector3D ac = 
c - a;
 
  262     const QVector3D qp = ( ray.origin() - ray.point( ray.distance() ) );
 
  264     const QVector3D n = QVector3D::crossProduct( ab, ac );
 
  265     const float d = QVector3D::dotProduct( qp, n );
 
  270     const QVector3D ap = ray.origin() - a;
 
  271     t = QVector3D::dotProduct( ap, n );
 
  273     if ( t < 0.0f || t > d )
 
  276     const QVector3D e = QVector3D::crossProduct( qp, ap );
 
  277     uvw.setY( QVector3D::dotProduct( ac, e ) );
 
  279     if ( uvw.y() < 0.0f || uvw.y() > d )
 
  282     uvw.setZ( -QVector3D::dotProduct( ab, e ) );
 
  284     if ( uvw.z() < 0.0f || uvw.y() + uvw.z() > d )
 
  287     const float ood = 1.0f / d;
 
  289     uvw.setY( uvw.y() * ood );
 
  290     uvw.setZ( uvw.z() * ood );
 
  291     uvw.setX( 1.0f - uvw.y() - uvw.z() );
 
  303 static QRect windowViewport( QSize area, 
const QRectF &relativeViewport )
 
  305   if ( area.isValid() )
 
  307     const int areaWidth = area.width();
 
  308     const int areaHeight = area.height();
 
  309     return QRect( relativeViewport.x() * areaWidth,
 
  310                   ( 1.0 - relativeViewport.y() - relativeViewport.height() ) * areaHeight,
 
  311                   relativeViewport.width() * areaWidth,
 
  312                   relativeViewport.height() * areaHeight );
 
  314   return relativeViewport.toRect();
 
  318 static QgsRayCastingUtils::Ray3D intersectionRay( QPointF pos, 
const QMatrix4x4 &viewMatrix,
 
  319     const QMatrix4x4 &projectionMatrix, QRect viewport )
 
  326   QVector3D nearPos = QVector3D( pos.x(), pos.y(), 0.0f );
 
  327   nearPos = nearPos.unproject( viewMatrix, projectionMatrix, viewport );
 
  328   QVector3D farPos = QVector3D( pos.x(), pos.y(), 1.0f );
 
  329   farPos = farPos.unproject( viewMatrix, projectionMatrix, viewport );
 
  331   return QgsRayCastingUtils::Ray3D( nearPos,
 
  332                                     ( farPos - nearPos ).normalized(),
 
  333                                     ( farPos - nearPos ).length() );
 
  337 namespace QgsRayCastingUtils
 
  340   Ray3D rayForViewportAndCamera( QSize area,
 
  342                                  const QRectF &relativeViewport,
 
  343                                  const Qt3DRender::QCamera *camera )
 
  345     QMatrix4x4 viewMatrix = camera->viewMatrix();
 
  346     QMatrix4x4 projectionMatrix = camera->projectionMatrix();
 
  347     const QRect viewport = windowViewport( area, relativeViewport );
 
  350     const QPointF glCorrectPos = QPointF( pos.x(), area.isValid() ? area.height() - pos.y() : pos.y() );
 
  351     const auto ray = intersectionRay( glCorrectPos, viewMatrix, projectionMatrix, viewport );
 
  355   Ray3D rayForCameraCenter( 
const Qt3DRender::QCamera *camera )
 
  357     QMatrix4x4 inverse = QMatrix4x4( camera->projectionMatrix() * camera->viewMatrix() ).inverted();
 
  359     QVector4D vNear( 0.0, 0.0, -1.0, 1.0 );
 
  360     QVector4D vFar( 0.0, 0.0, 1.0, 1.0 );
 
  361     QVector4D nearPos4D = inverse * vNear;
 
  362     QVector4D farPos4D = inverse * vFar;
 
  371     QVector3D nearPos( ( nearPos4D / nearPos4D.w() ).toVector3D() );
 
  372     QVector3D farPos( ( farPos4D / farPos4D.w() ).toVector3D() );
 
  374     return QgsRayCastingUtils::Ray3D( nearPos,
 
  375                                       ( farPos - nearPos ).normalized(),
 
  376                                       ( farPos - nearPos ).length() );
 
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsFloatNear(float a, float b, float epsilon=4 *FLT_EPSILON)
Compare two floats (but allow some difference)
QDataStream & operator<<(QDataStream &out, const QgsFeature &feature)
Writes the feature to stream out. QGIS version compatibility is not guaranteed.
bool operator==(const QgsFeatureIterator &fi1, const QgsFeatureIterator &fi2)
bool operator!=(const QgsFeatureIterator &fi1, const QgsFeatureIterator &fi2)