QGIS API Documentation 4.1.0-Master (cbdd823d36a)
Loading...
Searching...
No Matches
qgssfcgalgeometry.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgssfcgalGeometry.cpp
3 ----------------
4 begin : May 2025
5 copyright : (C) 2025 by Oslandia
6 email : benoit dot de dot mezzo at oslandia dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#ifdef WITH_SFCGAL
19
20#include "qgssfcgalgeometry.h"
21
22#include "qgsvector3d.h"
23#include "qgswkbptr.h"
24
25#include <QByteArray>
26#include <QString>
27
28using namespace Qt::StringLiterals;
29
30QgsSfcgalGeometry::QgsSfcgalGeometry()
31 : mIsPrimitive( false )
32{}
33
34QgsSfcgalGeometry::QgsSfcgalGeometry( const QgsAbstractGeometry *qgsGeom )
35 : mIsPrimitive( false )
36{
37 if ( qgsGeom )
38 {
39 QString errorMsg;
40 sfcgal::errorHandler()->clearText( &errorMsg );
41 mSfcgalGeom = QgsSfcgalEngine::fromAbstractGeometry( qgsGeom, &errorMsg );
42 THROW_ON_ERROR( &errorMsg );
43 }
44}
45
46QgsSfcgalGeometry::QgsSfcgalGeometry( const QgsAbstractGeometry &qgsGeom )
47 : mIsPrimitive( false )
48{
49 QString errorMsg;
50 sfcgal::errorHandler()->clearText( &errorMsg );
51 mSfcgalGeom = QgsSfcgalEngine::fromAbstractGeometry( &qgsGeom, &errorMsg );
52 THROW_ON_ERROR( &errorMsg );
53}
54
55QgsSfcgalGeometry::QgsSfcgalGeometry( sfcgal::shared_geom sfcgalGeom )
56 : mSfcgalGeom( sfcgalGeom )
57 , mIsPrimitive( false )
58{}
59
60QgsSfcgalGeometry::QgsSfcgalGeometry( sfcgal::shared_prim sfcgalPrim, sfcgal::primitiveType type )
61 : mIsPrimitive( true )
62{
63#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
64 mSfcgalPrim = sfcgalPrim;
65 mPrimType = type;
66#else
67 ( void ) sfcgalPrim;
68 ( void ) type;
69 throw QgsNotSupportedException( QObject::tr( "This operation requires a QGIS build based on SFCGAL 2.3 or later" ) );
70#endif
71}
72
73QgsSfcgalGeometry::QgsSfcgalGeometry( const QgsGeometry &qgsGeom )
74{
75 QString errorMsg;
76 sfcgal::errorHandler()->clearText( &errorMsg );
77 mSfcgalGeom = QgsSfcgalEngine::fromAbstractGeometry( qgsGeom.constGet(), &errorMsg );
78 THROW_ON_ERROR( &errorMsg );
79}
80
81QgsSfcgalGeometry::QgsSfcgalGeometry( const QgsSfcgalGeometry &otherGeom )
82{
83 QString errorMsg;
84 sfcgal::errorHandler()->clearText( &errorMsg );
85 mIsPrimitive = otherGeom.mIsPrimitive;
86#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
87 mPrimType = otherGeom.mPrimType;
88 if ( mIsPrimitive )
89 mSfcgalPrim = QgsSfcgalEngine::primitiveClone( otherGeom.mSfcgalPrim.get(), &errorMsg );
90 else
91#endif
92 mSfcgalGeom = QgsSfcgalEngine::cloneGeometry( otherGeom.mSfcgalGeom.get(), &errorMsg );
93 THROW_ON_ERROR( &errorMsg );
94}
95
96QgsSfcgalGeometry::QgsSfcgalGeometry( const QString &wkt )
97{
98 QString errorMsg;
99 sfcgal::errorHandler()->clearText( &errorMsg );
100 mSfcgalGeom = QgsSfcgalEngine::fromWkt( wkt, &errorMsg );
101 THROW_ON_ERROR( &errorMsg );
102}
103
104sfcgal::shared_geom QgsSfcgalGeometry::workingGeom() const
105{
106 sfcgal::shared_geom geom;
107
108#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
109 if ( mIsPrimitive )
110 {
111 QString errorMsg;
112 geom = QgsSfcgalEngine::primitiveAsPolyhedral( mSfcgalPrim.get(), &errorMsg );
113 THROW_ON_ERROR( &errorMsg );
114 }
115 else
116#endif
117 geom = mSfcgalGeom;
118
119 return geom;
120}
121
122
123Qgis::WkbType QgsSfcgalGeometry::wkbType() const
124{
125 QString errorMsg;
126 sfcgal::errorHandler()->clearText( &errorMsg );
127
128#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
129 if ( mIsPrimitive )
131#endif
132
133 Qgis::WkbType out = QgsSfcgalEngine::wkbType( mSfcgalGeom.get(), &errorMsg );
134 THROW_ON_ERROR( &errorMsg );
135 return out;
136}
137
138QString QgsSfcgalGeometry::geometryType() const
139{
140 QString errorMsg;
141 sfcgal::errorHandler()->clearText( &errorMsg );
142
143 QString out;
144#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
145 if ( mIsPrimitive )
146 {
147 switch ( mPrimType )
148 {
149 case sfcgal::primitiveType::SFCGAL_TYPE_CYLINDER:
150 out = "cylinder";
151 break;
152 case sfcgal::primitiveType::SFCGAL_TYPE_SPHERE:
153 out = "sphere";
154 break;
155 case sfcgal::primitiveType::SFCGAL_TYPE_TORUS:
156 out = "torus";
157 break;
158 case sfcgal::primitiveType::SFCGAL_TYPE_BOX:
159 out = "box";
160 break;
161 case sfcgal::primitiveType::SFCGAL_TYPE_CUBE:
162 out = "cube";
163 break;
164 case sfcgal::primitiveType::SFCGAL_TYPE_CONE:
165 out = "cone";
166 break;
167 default:
168 sfcgal::errorHandler()->addText( u"Type '%1' is unknown."_s.arg( mPrimType ) );
169 }
170 }
171 else
172#endif
173 {
174 out = QgsSfcgalEngine::geometryType( mSfcgalGeom.get(), &errorMsg );
175 THROW_ON_ERROR( &errorMsg );
176 }
177 return out;
178}
179
180std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::clone() const
181{
182 return std::make_unique<QgsSfcgalGeometry>( *this );
183}
184
185std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::fromWkb( const QgsConstWkbPtr &wkbPtr )
186{
187 if ( !wkbPtr )
188 {
189 return nullptr;
190 }
191
192 QString errorMsg;
193 sfcgal::shared_geom sfcgalGeom = QgsSfcgalEngine::fromWkb( wkbPtr, &errorMsg );
194 THROW_ON_ERROR( &errorMsg );
195
196 return std::make_unique<QgsSfcgalGeometry>( sfcgalGeom );
197}
198
199
200QByteArray QgsSfcgalGeometry::asWkb( QgsAbstractGeometry::WkbFlags ) const
201{
202 QString errorMsg;
203 sfcgal::errorHandler()->clearText( &errorMsg );
204
205 sfcgal::shared_geom geom = workingGeom();
206 QByteArray wkbArray = QgsSfcgalEngine::toWkb( geom.get(), &errorMsg );
207 THROW_ON_ERROR( &errorMsg );
208
209 return wkbArray;
210}
211
212QString QgsSfcgalGeometry::asWkt( int precision ) const
213{
214 QString errorMsg;
215 sfcgal::errorHandler()->clearText( &errorMsg );
216
217 sfcgal::shared_geom geom = workingGeom();
218 QString out = QgsSfcgalEngine::toWkt( geom.get(), precision, &errorMsg );
219 THROW_ON_ERROR( &errorMsg );
220
221 return out;
222}
223
224std::unique_ptr<QgsAbstractGeometry> QgsSfcgalGeometry::asQgisGeometry() const
225{
226 QString errorMsg;
227 sfcgal::errorHandler()->clearText( &errorMsg );
228
229 sfcgal::shared_geom geom = workingGeom();
230 std::unique_ptr<QgsAbstractGeometry> out = QgsSfcgalEngine::toAbstractGeometry( geom.get(), &errorMsg );
231 THROW_ON_ERROR( &errorMsg );
232 return out;
233}
234
235std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::boundary() const
236{
237 QString errorMsg;
238 sfcgal::errorHandler()->clearText( &errorMsg );
239
240 sfcgal::shared_geom geom = workingGeom();
241 sfcgal::shared_geom boundary = QgsSfcgalEngine::boundary( geom.get(), &errorMsg );
242 THROW_ON_ERROR( &errorMsg );
243
244 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( boundary, &errorMsg );
245 THROW_ON_ERROR( &errorMsg );
246 return resultGeom;
247}
248
249bool QgsSfcgalGeometry::operator==( const QgsSfcgalGeometry &other ) const
250{
251#if SFCGAL_VERSION_NUM < SFCGAL_MAKE_VERSION( 2, 1, 0 )
252 ( void ) other;
253 throw QgsNotSupportedException( QObject::tr( "This operation requires a QGIS build based on SFCGAL 2.1 or later" ) );
254#else
255 QString errorMsg;
256 sfcgal::errorHandler()->clearText( &errorMsg );
257 bool out;
258
259#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
260 if ( mIsPrimitive != other.mIsPrimitive )
261 return false;
262
263 if ( mIsPrimitive )
264 {
265 out = QgsSfcgalEngine::primitiveIsEqual( mSfcgalPrim.get(), other.mSfcgalPrim.get(), -1.0, &errorMsg );
266 }
267 else
268#endif
269 {
270 out = QgsSfcgalEngine::isEqual( mSfcgalGeom.get(), other.mSfcgalGeom.get(), -1.0, &errorMsg );
271 }
272 THROW_ON_ERROR( &errorMsg );
273 return out;
274#endif
275}
276
277bool QgsSfcgalGeometry::operator!=( const QgsSfcgalGeometry &other ) const
278{
279 return !( *this == other );
280}
281
282bool QgsSfcgalGeometry::fuzzyEqual( const QgsSfcgalGeometry &other, double epsilon ) const
283{
284 QString errorMsg;
285 sfcgal::errorHandler()->clearText( &errorMsg );
286
287 bool out;
288
289#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
290 if ( mIsPrimitive != other.mIsPrimitive )
291 return false;
292
293 if ( mIsPrimitive )
294 {
295 out = QgsSfcgalEngine::primitiveIsEqual( mSfcgalPrim.get(), other.mSfcgalPrim.get(), epsilon, &errorMsg );
296 }
297 else
298#endif
299 {
300 out = QgsSfcgalEngine::isEqual( mSfcgalGeom.get(), other.mSfcgalGeom.get(), epsilon, &errorMsg );
301 }
302
303 THROW_ON_ERROR( &errorMsg );
304 return out;
305}
306
307int QgsSfcgalGeometry::dimension() const
308{
309 QString errorMsg;
310 sfcgal::errorHandler()->clearText( &errorMsg );
311
312 if ( mIsPrimitive )
313 return 3;
314
315 int result = QgsSfcgalEngine::dimension( mSfcgalGeom.get(), &errorMsg );
316 THROW_ON_ERROR( &errorMsg );
317
318 return result;
319}
320
321std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::fromWkt( const QString &wkt )
322{
323 QString errorMsg;
324
325 sfcgal::shared_geom sfcgalGeom = QgsSfcgalEngine::fromWkt( wkt, &errorMsg );
326 THROW_ON_ERROR( &errorMsg );
327
328 return std::make_unique<QgsSfcgalGeometry>( sfcgalGeom );
329}
330
331int QgsSfcgalGeometry::partCount() const
332{
333 QString errorMsg;
334 sfcgal::errorHandler()->clearText( &errorMsg );
335
336 if ( mIsPrimitive )
337 return 1;
338
339 int out = QgsSfcgalEngine::partCount( mSfcgalGeom.get(), &errorMsg );
340 THROW_ON_ERROR( &errorMsg );
341
342 return out;
343}
344
345bool QgsSfcgalGeometry::addZValue( double zValue )
346{
347 QString errorMsg;
348 sfcgal::errorHandler()->clearText( &errorMsg );
349
350 if ( mIsPrimitive )
351 throw QgsNotSupportedException( QObject::tr( "Operation '%1' does not apply to primitive." ).arg( "addZValue" ) );
352
353 const bool added = QgsSfcgalEngine::addZValue( mSfcgalGeom.get(), zValue, &errorMsg );
354 THROW_ON_ERROR( &errorMsg );
355
356 clearCache();
357
358 return added;
359}
360
361bool QgsSfcgalGeometry::addMValue( double mValue )
362{
363 QString errorMsg;
364 sfcgal::errorHandler()->clearText( &errorMsg );
365
366 if ( mIsPrimitive )
367 throw QgsNotSupportedException( QObject::tr( "Operation '%1' does not apply to primitive." ).arg( "addMValue" ) );
368
369 const bool added = QgsSfcgalEngine::addMValue( mSfcgalGeom.get(), mValue, &errorMsg );
370 THROW_ON_ERROR( &errorMsg );
371
372 clearCache();
373
374 return added;
375}
376
377bool QgsSfcgalGeometry::dropZValue()
378{
379 QString errorMsg;
380 sfcgal::errorHandler()->clearText( &errorMsg );
381
382 if ( mIsPrimitive )
383 throw QgsNotSupportedException( QObject::tr( "Operation '%1' does not apply to primitive." ).arg( "dropZValue" ) );
384
385 const bool dropped = QgsSfcgalEngine::dropZValue( mSfcgalGeom.get(), &errorMsg );
386 THROW_ON_ERROR( &errorMsg );
387
388 clearCache();
389
390 return dropped;
391}
392
393bool QgsSfcgalGeometry::dropMValue()
394{
395 QString errorMsg;
396 sfcgal::errorHandler()->clearText( &errorMsg );
397
398 if ( mIsPrimitive )
399 throw QgsNotSupportedException( QObject::tr( "Operation '%1' does not apply to primitive." ).arg( "dropMValue" ) );
400
401 const bool dropped = QgsSfcgalEngine::dropMValue( mSfcgalGeom.get(), &errorMsg );
402 THROW_ON_ERROR( &errorMsg );
403
404 clearCache();
405
406 return dropped;
407}
408
409void QgsSfcgalGeometry::swapXy()
410{
411 QString errorMsg;
412 sfcgal::errorHandler()->clearText( &errorMsg );
413
414 if ( mIsPrimitive )
415 throw QgsNotSupportedException( QObject::tr( "Operation '%1' does not apply to primitive." ).arg( "swapXy" ) );
416
417 QgsSfcgalEngine::swapXy( mSfcgalGeom.get(), &errorMsg );
418 THROW_ON_ERROR( &errorMsg );
419
420 clearCache();
421}
422
423bool QgsSfcgalGeometry::isValid() const
424{
425 QString errorMsg;
426 sfcgal::errorHandler()->clearText( &errorMsg );
427
428 if ( mIsPrimitive )
429 return true;
430
431 const bool valid = QgsSfcgalEngine::isValid( mSfcgalGeom.get(), &errorMsg, nullptr );
432 THROW_ON_ERROR( &errorMsg );
433 return valid;
434}
435
436void QgsSfcgalGeometry::clearCache() const
437{}
438
439bool QgsSfcgalGeometry::isSimple() const
440{
441 QString errorMsg;
442 sfcgal::errorHandler()->clearText( &errorMsg );
443
444 if ( mIsPrimitive )
445 return true;
446
447 bool result = QgsSfcgalEngine::isSimple( mSfcgalGeom.get(), &errorMsg );
448 THROW_ON_ERROR( &errorMsg );
449 return result;
450}
451
452std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::geometryN( unsigned int index ) const
453{
454 QString errorMsg;
455 sfcgal::errorHandler()->clearText( &errorMsg );
456
457 sfcgal::shared_geom geom = workingGeom();
458 sfcgal::shared_geom result = QgsSfcgalEngine::geometryN( geom.get(), index );
459 THROW_ON_ERROR( &errorMsg );
460
461 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
462 THROW_ON_ERROR( &errorMsg );
463 return resultGeom;
464}
465
466QgsPoint QgsSfcgalGeometry::centroid() const
467{
468 QString errorMsg;
469 sfcgal::errorHandler()->clearText( &errorMsg );
470
471 sfcgal::shared_geom geom = workingGeom();
472 return QgsSfcgalEngine::centroid( geom.get(), &errorMsg );
473}
474
475bool QgsSfcgalGeometry::isEmpty() const
476{
477 QString errorMsg;
478 sfcgal::errorHandler()->clearText( &errorMsg );
479
480 if ( mIsPrimitive )
481 return false;
482
483 bool result = QgsSfcgalEngine::isEmpty( mSfcgalGeom.get(), &errorMsg );
484 THROW_ON_ERROR( &errorMsg );
485
486 return result;
487}
488
489std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::translate( const QgsVector3D &translation ) const
490{
491 QString errorMsg;
492 sfcgal::errorHandler()->clearText( &errorMsg );
493
494 std::unique_ptr<QgsSfcgalGeometry> resultGeom;
495#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
496 if ( mIsPrimitive )
497 {
498 sfcgal::shared_prim result = QgsSfcgalEngine::primitiveTranslate( mSfcgalPrim.get(), translation, &errorMsg );
499 THROW_ON_ERROR( &errorMsg );
500 resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, mPrimType, &errorMsg );
501 }
502 else
503#endif
504 {
505 sfcgal::shared_geom result = QgsSfcgalEngine::translate( mSfcgalGeom.get(), translation, &errorMsg );
506 THROW_ON_ERROR( &errorMsg );
507 resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
508 }
509
510 THROW_ON_ERROR( &errorMsg );
511 return resultGeom;
512}
513
514std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::scale( const QgsVector3D &scaleFactor, const QgsPoint &center ) const
515{
516 QString errorMsg;
517 sfcgal::errorHandler()->clearText( &errorMsg );
518
519 std::unique_ptr<QgsSfcgalGeometry> resultGeom;
520#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
521 if ( mIsPrimitive )
522 {
523 sfcgal::shared_prim result = QgsSfcgalEngine::primitiveScale( mSfcgalPrim.get(), scaleFactor, center, &errorMsg );
524 THROW_ON_ERROR( &errorMsg );
525 resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, mPrimType, &errorMsg );
526 }
527 else
528#endif
529 {
530 sfcgal::shared_geom result = QgsSfcgalEngine::scale( mSfcgalGeom.get(), scaleFactor, center, &errorMsg );
531 THROW_ON_ERROR( &errorMsg );
532 resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
533 }
534
535 THROW_ON_ERROR( &errorMsg );
536 return resultGeom;
537}
538
539std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::rotate2D( double angle, const QgsPoint &center ) const
540{
541 QString errorMsg;
542 sfcgal::errorHandler()->clearText( &errorMsg );
543
544 std::unique_ptr<QgsSfcgalGeometry> resultGeom;
545#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
546 if ( mIsPrimitive )
547 {
548 sfcgal::shared_prim result = QgsSfcgalEngine::primitiveRotate( mSfcgalPrim.get(), angle, { 0.0, 0.0, 1.0 }, center, &errorMsg );
549 THROW_ON_ERROR( &errorMsg );
550 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, mPrimType, &errorMsg );
551 THROW_ON_ERROR( &errorMsg );
552 return resultGeom;
553 }
554 else
555#endif
556 {
557 sfcgal::shared_geom result = QgsSfcgalEngine::rotate2D( mSfcgalGeom.get(), angle, center, &errorMsg );
558 THROW_ON_ERROR( &errorMsg );
559
560 resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
561 }
562
563 THROW_ON_ERROR( &errorMsg );
564 return resultGeom;
565}
566
567std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::transform( const QgsMatrix4x4 &mat ) const
568{
569 QString errorMsg;
570 sfcgal::errorHandler()->clearText( &errorMsg );
571
572#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
573 sfcgal::shared_geom geom = workingGeom();
574
575 sfcgal::shared_geom result = QgsSfcgalEngine::transform( geom.get(), mat );
576 THROW_ON_ERROR( &errorMsg );
577
578 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
579 THROW_ON_ERROR( &errorMsg );
580 return resultGeom;
581#else
582 ( void ) mat;
583 throw QgsNotSupportedException( QObject::tr( "This operation requires a QGIS build based on SFCGAL 2.3 or later" ) );
584#endif
585}
586
587std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::rotate3D( double angle, const QgsVector3D &axisVector, const QgsPoint &center ) const
588{
589 QString errorMsg;
590 sfcgal::errorHandler()->clearText( &errorMsg );
591
592 std::unique_ptr<QgsSfcgalGeometry> resultGeom;
593#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
594 if ( mIsPrimitive )
595 {
596 sfcgal::shared_prim result = QgsSfcgalEngine::primitiveRotate( mSfcgalPrim.get(), angle, axisVector, center, &errorMsg );
597 THROW_ON_ERROR( &errorMsg );
598 resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, mPrimType, &errorMsg );
599 }
600 else
601#endif
602 {
603 sfcgal::shared_geom result = QgsSfcgalEngine::rotate3D( mSfcgalGeom.get(), angle, axisVector, center, &errorMsg );
604 THROW_ON_ERROR( &errorMsg );
605
606 resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
607 }
608
609 THROW_ON_ERROR( &errorMsg );
610 return resultGeom;
611}
612
613double QgsSfcgalGeometry::area( bool withDiscretization ) const
614{
615 QString errorMsg;
616 sfcgal::errorHandler()->clearText( &errorMsg );
617
618 double result;
619#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
620 if ( mIsPrimitive )
621 {
622 result = QgsSfcgalEngine::primitiveArea( mSfcgalPrim.get(), withDiscretization, &errorMsg );
623 }
624 else
625#endif
626 {
627 ( void ) withDiscretization;
628 result = QgsSfcgalEngine::area( mSfcgalGeom.get(), &errorMsg );
629 }
630
631 THROW_ON_ERROR( &errorMsg );
632 return result;
633}
634
635double QgsSfcgalGeometry::length() const
636{
637 QString errorMsg;
638 sfcgal::errorHandler()->clearText( &errorMsg );
639
640 if ( mIsPrimitive )
641 throw QgsNotSupportedException( QObject::tr( "Operation '%1' does not apply to primitive." ).arg( "length" ) );
642
643 double result = QgsSfcgalEngine::length( mSfcgalGeom.get(), &errorMsg );
644 THROW_ON_ERROR( &errorMsg );
645
646 return result;
647}
648
649double QgsSfcgalGeometry::volume( bool withDiscretization ) const
650{
651 QString errorMsg;
652 sfcgal::errorHandler()->clearText( &errorMsg );
653
654 if ( !mIsPrimitive )
655 throw QgsNotSupportedException( QObject::tr( "Operation '%1' does not apply to geometry." ).arg( "volume" ) );
656
657 double result;
658#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
659 result = QgsSfcgalEngine::primitiveVolume( mSfcgalPrim.get(), withDiscretization, &errorMsg );
660#else
661 ( void ) withDiscretization;
662 throw QgsNotSupportedException( QObject::tr( "This operation requires a QGIS build based on SFCGAL 2.3 or later" ) );
663#endif
664
665 THROW_ON_ERROR( &errorMsg );
666 return result;
667}
668
669bool QgsSfcgalGeometry::intersects( const QgsAbstractGeometry *otherGeom ) const
670{
671 QString errorMsg;
672 sfcgal::errorHandler()->clearText( &errorMsg );
673 sfcgal::shared_geom otherShared = QgsSfcgalEngine::fromAbstractGeometry( otherGeom, &errorMsg );
674 THROW_ON_ERROR( &errorMsg );
675
676 sfcgal::shared_geom geom = workingGeom();
677 bool out = QgsSfcgalEngine::intersects( geom.get(), otherShared.get(), &errorMsg );
678 THROW_ON_ERROR( &errorMsg );
679 return out;
680}
681
682bool QgsSfcgalGeometry::intersects( const QgsSfcgalGeometry &otherGeom ) const
683{
684 QString errorMsg;
685 sfcgal::errorHandler()->clearText( &errorMsg );
686
687 sfcgal::shared_geom geom = workingGeom();
688 bool out = QgsSfcgalEngine::intersects( geom.get(), otherGeom.workingGeom().get(), &errorMsg );
689 THROW_ON_ERROR( &errorMsg );
690 return out;
691}
692
693std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::intersection( const QgsAbstractGeometry *otherGeom ) const
694{
695 QString errorMsg;
696 sfcgal::errorHandler()->clearText( &errorMsg );
697 sfcgal::shared_geom otherShared = QgsSfcgalEngine::fromAbstractGeometry( otherGeom, &errorMsg );
698 THROW_ON_ERROR( &errorMsg );
699
700 sfcgal::shared_geom geom = workingGeom();
701 sfcgal::shared_geom result = QgsSfcgalEngine::intersection( geom.get(), otherShared.get(), &errorMsg );
702 THROW_ON_ERROR( &errorMsg );
703
704 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
705 THROW_ON_ERROR( &errorMsg );
706 return resultGeom;
707}
708
709std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::intersection( const QgsSfcgalGeometry &otherGeom ) const
710{
711 QString errorMsg;
712 sfcgal::errorHandler()->clearText( &errorMsg );
713
714 sfcgal::shared_geom geom = workingGeom();
715 sfcgal::shared_geom result = QgsSfcgalEngine::intersection( geom.get(), otherGeom.workingGeom().get(), &errorMsg );
716 THROW_ON_ERROR( &errorMsg );
717
718 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
719 THROW_ON_ERROR( &errorMsg );
720 return resultGeom;
721}
722
723std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::combine( const QVector<QgsAbstractGeometry *> &geomList ) const
724{
725 QString errorMsg;
726 sfcgal::errorHandler()->clearText( &errorMsg );
727 QVector<sfcgal::shared_geom> sfcgalGeomList;
728
729 sfcgal::shared_geom geom = workingGeom();
730 sfcgalGeomList.append( geom );
731 for ( QVector<QgsAbstractGeometry *>::const_iterator ite = geomList.constBegin(); ite != geomList.constEnd(); ++ite )
732 {
733 sfcgal::shared_geom otherShared = QgsSfcgalEngine::fromAbstractGeometry( *ite, &errorMsg );
734 THROW_ON_ERROR( &errorMsg );
735 sfcgalGeomList.append( otherShared );
736 }
737
738 sfcgal::shared_geom result = QgsSfcgalEngine::combine( sfcgalGeomList, &errorMsg );
739 THROW_ON_ERROR( &errorMsg );
740
741 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
742 THROW_ON_ERROR( &errorMsg );
743 return resultGeom;
744}
745
746std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::difference( const QgsAbstractGeometry *otherGeom ) const
747{
748 QString errorMsg;
749 sfcgal::errorHandler()->clearText( &errorMsg );
750 sfcgal::shared_geom otherSharedr = QgsSfcgalEngine::fromAbstractGeometry( otherGeom, &errorMsg );
751 THROW_ON_ERROR( &errorMsg );
752
753 sfcgal::shared_geom geom = workingGeom();
754 sfcgal::shared_geom result = QgsSfcgalEngine::difference( geom.get(), otherSharedr.get(), &errorMsg );
755 THROW_ON_ERROR( &errorMsg );
756
757 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
758 THROW_ON_ERROR( &errorMsg );
759 return resultGeom;
760}
761
762std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::difference( const QgsSfcgalGeometry &otherGeom ) const
763{
764 QString errorMsg;
765 sfcgal::errorHandler()->clearText( &errorMsg );
766
767 sfcgal::shared_geom geom = workingGeom();
768 sfcgal::shared_geom result = QgsSfcgalEngine::difference( geom.get(), otherGeom.workingGeom().get(), &errorMsg );
769 THROW_ON_ERROR( &errorMsg );
770
771 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
772 THROW_ON_ERROR( &errorMsg );
773 return resultGeom;
774}
775
776std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::triangulate() const
777{
778 QString errorMsg;
779 sfcgal::errorHandler()->clearText( &errorMsg );
780
781 sfcgal::shared_geom geom = workingGeom();
782 sfcgal::shared_geom result = QgsSfcgalEngine::triangulate( geom.get(), &errorMsg );
783 THROW_ON_ERROR( &errorMsg );
784
785 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
786 THROW_ON_ERROR( &errorMsg );
787 return resultGeom;
788}
789
790std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::convexHull() const
791{
792 QString errorMsg;
793 sfcgal::errorHandler()->clearText( &errorMsg );
794
795 sfcgal::shared_geom geom = workingGeom();
796 sfcgal::shared_geom result = QgsSfcgalEngine::convexHull( geom.get(), &errorMsg );
797 THROW_ON_ERROR( &errorMsg );
798
799 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
800 THROW_ON_ERROR( &errorMsg );
801 return resultGeom;
802}
803
804std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::envelope() const
805{
806 QString errorMsg;
807 sfcgal::errorHandler()->clearText( &errorMsg );
808
809 sfcgal::shared_geom geom = workingGeom();
810 sfcgal::shared_geom result = QgsSfcgalEngine::envelope( geom.get(), &errorMsg );
811 THROW_ON_ERROR( &errorMsg );
812
813 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
814 THROW_ON_ERROR( &errorMsg );
815 return resultGeom;
816}
817
818bool QgsSfcgalGeometry::covers( const QgsSfcgalGeometry &otherGeom ) const
819{
820 QString errorMsg;
821 sfcgal::errorHandler()->clearText( &errorMsg );
822
823 sfcgal::shared_geom geom = workingGeom();
824 bool out = QgsSfcgalEngine::covers( geom.get(), otherGeom.workingGeom().get(), &errorMsg );
825 THROW_ON_ERROR( &errorMsg );
826 return out;
827}
828
829std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::buffer3D( double radius, int segments, Qgis::JoinStyle3D joinStyle3D ) const
830{
831 QString errorMsg;
832 sfcgal::errorHandler()->clearText( &errorMsg );
833
834 sfcgal::shared_geom geom = workingGeom();
835 sfcgal::shared_geom result = QgsSfcgalEngine::buffer3D( geom.get(), radius, segments, joinStyle3D, &errorMsg );
836 THROW_ON_ERROR( &errorMsg );
837
838 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
839 THROW_ON_ERROR( &errorMsg );
840 return resultGeom;
841}
842
843std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::buffer2D( double radius, int segments, Qgis::JoinStyle joinStyle ) const
844{
845 QString errorMsg;
846 sfcgal::errorHandler()->clearText( &errorMsg );
847
848 sfcgal::shared_geom geom = workingGeom();
849 sfcgal::shared_geom result = QgsSfcgalEngine::buffer2D( geom.get(), radius, segments, joinStyle, &errorMsg );
850 THROW_ON_ERROR( &errorMsg );
851
852 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
853 THROW_ON_ERROR( &errorMsg );
854 return resultGeom;
855}
856
857std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::simplify( double tolerance, bool preserveTopology ) const
858{
859 QString errorMsg;
860 sfcgal::errorHandler()->clearText( &errorMsg );
861
862 sfcgal::shared_geom geom = workingGeom();
863 sfcgal::shared_geom result = QgsSfcgalEngine::simplify( geom.get(), tolerance, preserveTopology, &errorMsg );
864 THROW_ON_ERROR( &errorMsg );
865
866 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
867 THROW_ON_ERROR( &errorMsg );
868 return resultGeom;
869}
870
871std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::extrude( const QgsVector3D &extrusion ) const
872{
873 QString errorMsg;
874 sfcgal::errorHandler()->clearText( &errorMsg );
875
876 sfcgal::shared_geom geom = workingGeom();
877 sfcgal::shared_geom result = QgsSfcgalEngine::extrude( geom.get(), extrusion, &errorMsg );
878 THROW_ON_ERROR( &errorMsg );
879
880 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
881 THROW_ON_ERROR( &errorMsg );
882 return resultGeom;
883}
884
885std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::approximateMedialAxis( bool extendToEdges ) const
886{
887 QString errorMsg;
888 sfcgal::errorHandler()->clearText( &errorMsg );
889
890 sfcgal::shared_geom geom = workingGeom();
891 sfcgal::shared_geom result = QgsSfcgalEngine::approximateMedialAxis( geom.get(), extendToEdges, &errorMsg );
892 THROW_ON_ERROR( &errorMsg );
893
894 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
895 THROW_ON_ERROR( &errorMsg );
896 return resultGeom;
897}
898
899std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::toSolid() const
900{
901 QString errorMsg;
902 sfcgal::errorHandler()->clearText( &errorMsg );
903
904 sfcgal::shared_geom geom = workingGeom();
905 sfcgal::shared_geom solid = QgsSfcgalEngine::toSolid( geom.get(), &errorMsg );
906 THROW_ON_ERROR( &errorMsg );
907
908 std::unique_ptr<QgsSfcgalGeometry> solidGeom = QgsSfcgalEngine::toSfcgalGeometry( solid, &errorMsg );
909 THROW_ON_ERROR( &errorMsg );
910 return solidGeom;
911}
912
913std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::split3D( const QgsPoint &planePoint, const QgsVector3D &planeNormal, bool closeGeometries ) const
914{
915 QString errorMsg;
916 sfcgal::errorHandler()->clearText( &errorMsg );
917
918#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
919 sfcgal::shared_geom geom = workingGeom();
920
921 sfcgal::shared_geom result = QgsSfcgalEngine::split3D( geom.get(), planePoint, planeNormal, closeGeometries );
922 THROW_ON_ERROR( &errorMsg );
923
924 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
925 THROW_ON_ERROR( &errorMsg );
926 return resultGeom;
927#else
928 Q_UNUSED( planePoint )
929 Q_UNUSED( planeNormal )
930 Q_UNUSED( closeGeometries )
931 throw QgsNotSupportedException( QObject::tr( "This operation requires a QGIS build based on SFCGAL 2.3 or later" ) );
932#endif
933}
934
935std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::toPolyhedralSurface() const
936{
937 QString errorMsg;
938 sfcgal::errorHandler()->clearText( &errorMsg );
939
940 sfcgal::shared_geom geom = workingGeom();
941 sfcgal::shared_geom phs = QgsSfcgalEngine::toPolyhedralSurface( geom.get(), &errorMsg );
942 THROW_ON_ERROR( &errorMsg );
943
944 std::unique_ptr<QgsSfcgalGeometry> phsGeom = QgsSfcgalEngine::toSfcgalGeometry( phs, &errorMsg );
945 THROW_ON_ERROR( &errorMsg );
946 return phsGeom;
947}
948
949std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::createBox( double sizeX, double sizeY, double sizeZ )
950{
951#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
952 QString errorMsg;
953 sfcgal::errorHandler()->clearText( &errorMsg );
954 sfcgal::shared_prim result = QgsSfcgalEngine::createBox( sizeX, sizeY, sizeZ, &errorMsg );
955 THROW_ON_ERROR( &errorMsg );
956
957 auto resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, sfcgal::primitiveType::SFCGAL_TYPE_BOX, &errorMsg );
958 THROW_ON_ERROR( &errorMsg );
959 return resultGeom;
960#else
961 ( void ) sizeX;
962 ( void ) sizeY;
963 ( void ) sizeZ;
964 throw QgsNotSupportedException( QObject::tr( "This operation requires a QGIS build based on SFCGAL 2.3 or later" ) );
965#endif
966}
967
968std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::createCone( double bottomRadius, double height, double topRadius, unsigned int radial )
969{
970#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
971 QString errorMsg;
972 sfcgal::errorHandler()->clearText( &errorMsg );
973 sfcgal::shared_prim result = QgsSfcgalEngine::createCone( bottomRadius, height, topRadius, radial, &errorMsg );
974 THROW_ON_ERROR( &errorMsg );
975
976 auto resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, sfcgal::primitiveType::SFCGAL_TYPE_CONE, &errorMsg );
977 THROW_ON_ERROR( &errorMsg );
978 return resultGeom;
979#else
980 ( void ) bottomRadius;
981 ( void ) height;
982 ( void ) topRadius;
983 ( void ) radial;
984 throw QgsNotSupportedException( QObject::tr( "This operation requires a QGIS build based on SFCGAL 2.3 or later" ) );
985#endif
986}
987
988std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::createCube( double size )
989{
990#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
991 QString errorMsg;
992 sfcgal::errorHandler()->clearText( &errorMsg );
993 sfcgal::shared_prim result = QgsSfcgalEngine::createCube( size, &errorMsg );
994 THROW_ON_ERROR( &errorMsg );
995
996 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, sfcgal::primitiveType::SFCGAL_TYPE_CUBE, &errorMsg );
997 THROW_ON_ERROR( &errorMsg );
998 return resultGeom;
999#else
1000 ( void ) size;
1001 throw QgsNotSupportedException( QObject::tr( "This operation requires a QGIS build based on SFCGAL 2.3 or later" ) );
1002#endif
1003}
1004
1005std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::createCylinder( double radius, double height, unsigned int radial )
1006{
1007#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
1008 QString errorMsg;
1009 sfcgal::errorHandler()->clearText( &errorMsg );
1010 sfcgal::shared_prim result = QgsSfcgalEngine::createCylinder( radius, height, radial, &errorMsg );
1011 THROW_ON_ERROR( &errorMsg );
1012
1013 auto resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, sfcgal::primitiveType::SFCGAL_TYPE_CYLINDER, &errorMsg );
1014 THROW_ON_ERROR( &errorMsg );
1015 return resultGeom;
1016#else
1017 ( void ) radius;
1018 ( void ) height;
1019 ( void ) radial;
1020 throw QgsNotSupportedException( QObject::tr( "This operation requires a QGIS build based on SFCGAL 2.3 or later" ) );
1021#endif
1022}
1023
1024std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::createSphere( double radius, unsigned int subdivisions )
1025{
1026#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
1027 QString errorMsg;
1028 sfcgal::errorHandler()->clearText( &errorMsg );
1029 sfcgal::shared_prim result = QgsSfcgalEngine::createSphere( radius, subdivisions, &errorMsg );
1030 THROW_ON_ERROR( &errorMsg );
1031
1032 auto resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, sfcgal::primitiveType::SFCGAL_TYPE_SPHERE, &errorMsg );
1033 THROW_ON_ERROR( &errorMsg );
1034 return resultGeom;
1035#else
1036 ( void ) radius;
1037 ( void ) subdivisions;
1038 throw QgsNotSupportedException( QObject::tr( "This operation requires a QGIS build based on SFCGAL 2.3 or later" ) );
1039#endif
1040}
1041
1042std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::createTorus( double mainRadius, double tubeRadius, unsigned int mainRadial, unsigned int tubeRadial )
1043{
1044#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
1045 QString errorMsg;
1046 sfcgal::errorHandler()->clearText( &errorMsg );
1047 sfcgal::shared_prim result = QgsSfcgalEngine::createTorus( mainRadius, tubeRadius, mainRadial, tubeRadial, &errorMsg );
1048 THROW_ON_ERROR( &errorMsg );
1049
1050 auto resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, sfcgal::primitiveType::SFCGAL_TYPE_TORUS, &errorMsg );
1051 THROW_ON_ERROR( &errorMsg );
1052 return resultGeom;
1053#else
1054 ( void ) mainRadius;
1055 ( void ) tubeRadius;
1056 ( void ) mainRadial;
1057 ( void ) tubeRadial;
1058 throw QgsNotSupportedException( QObject::tr( "This operation requires a QGIS build based on SFCGAL 2.3 or later" ) );
1059#endif
1060}
1061
1062std::unique_ptr<QgsSfcgalGeometry> QgsSfcgalGeometry::primitiveAsPolyhedralSurface() const
1063{
1064#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
1065 if ( !mIsPrimitive )
1066 throw QgsSfcgalException( "Need primitive geometry to operate." );
1067
1068 QString errorMsg;
1069 sfcgal::errorHandler()->clearText( &errorMsg );
1070 sfcgal::shared_prim result = QgsSfcgalEngine::primitiveAsPolyhedral( mSfcgalPrim.get(), &errorMsg );
1071 THROW_ON_ERROR( &errorMsg );
1072
1073 std::unique_ptr<QgsSfcgalGeometry> resultGeom = QgsSfcgalEngine::toSfcgalGeometry( result, &errorMsg );
1074 THROW_ON_ERROR( &errorMsg );
1075 return resultGeom;
1076#else
1077 throw QgsNotSupportedException( QObject::tr( "This operation requires a QGIS build based on SFCGAL 2.3 or later" ) );
1078#endif
1079}
1080
1081QgsMatrix4x4 QgsSfcgalGeometry::primitiveTransform() const
1082{
1083#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
1084 if ( !mIsPrimitive )
1085 {
1086 throw QgsSfcgalException( "Need primitive geometry to operate." );
1087 }
1088
1089 QString errorMsg;
1090 sfcgal::errorHandler()->clearText( &errorMsg );
1091 double *data = sfcgal_primitive_transformation( mSfcgalPrim.get() );
1092 THROW_ON_ERROR( &errorMsg );
1093
1094 // sfcgal_primitive_transformation returns data in column-major order
1095 // QgsMatrix4x4 constructor expects data in row-major order
1096 // clang-format off
1097 QgsMatrix4x4 transformMatrix(
1098 data[0], data[4], data[8], data[12],
1099 data[1], data[5], data[9], data[13],
1100 data[2], data[6], data[10], data[14],
1101 data[3], data[7], data[11], data[15]
1102 );
1103 // clang-format on
1104 sfcgal_free_buffer( data );
1105 return transformMatrix;
1106#else
1107 throw QgsNotSupportedException( QObject::tr( "This operation requires a QGIS build based on SFCGAL 2.3 or later" ) );
1108#endif
1109}
1110
1111QList<std::pair<QString, QString>> QgsSfcgalGeometry::primitiveParameters() const
1112{
1113#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
1114 if ( !mIsPrimitive )
1115 throw QgsSfcgalException( "Need primitive geometry to operate." );
1116
1117 QString errorMsg;
1118 sfcgal::errorHandler()->clearText( &errorMsg );
1119 QVector<sfcgal::PrimitiveParameterDesc> result = QgsSfcgalEngine::primitiveParameters( mSfcgalPrim.get(), &errorMsg );
1120 THROW_ON_ERROR( &errorMsg );
1121
1122 QList<QPair<QString, QString>> out;
1123 for ( const auto &param : result )
1124 {
1125 out.append( std::pair<QString, QString>( QString::fromStdString( param.name ), QString::fromStdString( param.type ) ) );
1126 }
1127
1128 return out;
1129#else
1130 throw QgsNotSupportedException( QObject::tr( "This operation requires a QGIS build based on SFCGAL 2.3 or later" ) );
1131#endif
1132}
1133
1134QVariant QgsSfcgalGeometry::primitiveParameter( const QString &name ) const
1135{
1136#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
1137 if ( !mIsPrimitive )
1138 throw QgsSfcgalException( "Need primitive geometry to operate." );
1139
1140 QString errorMsg;
1141 sfcgal::errorHandler()->clearText( &errorMsg );
1142 QVariant result = QgsSfcgalEngine::primitiveParameter( mSfcgalPrim.get(), name, &errorMsg );
1143 THROW_ON_ERROR( &errorMsg );
1144
1145 return result;
1146#else
1147 ( void ) name;
1148 throw QgsNotSupportedException( QObject::tr( "This operation requires a QGIS build based on SFCGAL 2.3 or later" ) );
1149#endif
1150}
1151
1152void QgsSfcgalGeometry::primitiveSetParameter( const QString &name, const QVariant &value )
1153{
1154#if SFCGAL_VERSION_NUM >= SFCGAL_MAKE_VERSION( 2, 3, 0 )
1155 if ( !mIsPrimitive )
1156 throw QgsSfcgalException( "Need primitive geometry to operate." );
1157
1158 QString errorMsg;
1159 sfcgal::errorHandler()->clearText( &errorMsg );
1160 QgsSfcgalEngine::primitiveSetParameter( mSfcgalPrim.get(), name, value, &errorMsg );
1161 THROW_ON_ERROR( &errorMsg );
1162
1163#else
1164 ( void ) name;
1165 ( void ) value;
1166 throw QgsNotSupportedException( QObject::tr( "This operation requires a QGIS build based on SFCGAL 2.3 or later" ) );
1167#endif
1168}
1169
1170#endif
JoinStyle3D
Join styles for 3D buffers.
Definition qgis.h:2255
JoinStyle
Join styles for buffers.
Definition qgis.h:2242
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:294
@ PolyhedralSurfaceZ
PolyhedralSurfaceZ.
Definition qgis.h:326
Abstract base class for all geometries.
QFlags< WkbFlag > WkbFlags
A const WKB pointer.
Definition qgswkbptr.h:211
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
A simple 4x4 matrix implementation useful for transformation in 3D space.
Custom exception class which is raised when an operation is not supported.
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:53
Custom exception class for SfCGAL related operations.
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
Definition qgsvector3d.h:33