polygontubeprimitive3d.cxx (464702f4) | polygontubeprimitive3d.cxx (5aaf853b) |
---|---|
1/************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance --- 142 unchanged lines hidden (view full) --- 151 152 aLast = aNext; 153 } 154 } 155 156 return aLineCapList; 157 } 158 | 1/************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance --- 142 unchanged lines hidden (view full) --- 151 152 aLast = aNext; 153 } 154 } 155 156 return aLineCapList; 157 } 158 |
159 Primitive3DSequence getLineCapRoundSegments( 160 sal_uInt32 nSegments, 161 const attribute::MaterialAttribute3D& rMaterial) 162 { 163 // static data for buffered tube primitives 164 static Primitive3DSequence aLineCapRoundList; 165 static sal_uInt32 nLineCapRoundSegments(0); 166 static attribute::MaterialAttribute3D aLineMaterial; 167 168 // may exclusively change static data, use mutex 169 ::osl::Mutex m_mutex; 170 171 if(nSegments != nLineCapRoundSegments || !(rMaterial == aLineMaterial)) 172 { 173 nLineCapRoundSegments = nSegments; 174 aLineMaterial = rMaterial; 175 aLineCapRoundList = Primitive3DSequence(); 176 } 177 178 if(!aLineCapRoundList.hasElements() && nLineCapRoundSegments) 179 { 180 // calculate new horizontal segments 181 sal_uInt32 nVerSeg(nSegments / 2); 182 183 if(nVerSeg < 1) 184 { 185 nVerSeg = 1; 186 } 187 188 // create half-sphere; upper half of unit sphere 189 basegfx::B3DPolyPolygon aSphere( 190 basegfx::tools::createUnitSphereFillPolyPolygon( 191 nSegments, 192 nVerSeg, 193 true, 194 F_PI2, 0.0, 195 0.0, F_2PI)); 196 const sal_uInt32 nCount(aSphere.count()); 197 198 if(nCount) 199 { 200 // rotate to have sphere cap orientned to negative X-Axis; do not 201 // forget to transform normals, too 202 basegfx::B3DHomMatrix aSphereTrans; 203 204 aSphereTrans.rotate(0.0, 0.0, F_PI2); 205 aSphere.transform(aSphereTrans); 206 aSphere.transformNormals(aSphereTrans); 207 208 // realloc for primitives and create based on polygon snippets 209 aLineCapRoundList.realloc(nCount); 210 211 for(sal_uInt32 a(0); a < nCount; a++) 212 { 213 const basegfx::B3DPolygon aPartPolygon(aSphere.getB3DPolygon(a)); 214 const basegfx::B3DPolyPolygon aPartPolyPolygon(aPartPolygon); 215 216 // need to create one primitive per Polygon since the primitive 217 // is for planar PolyPolygons which is definitely not the case here 218 aLineCapRoundList[a] = new PolyPolygonMaterialPrimitive3D( 219 aPartPolyPolygon, 220 rMaterial, 221 false); 222 } 223 } 224 } 225 226 return aLineCapRoundList; 227 } 228 |
|
159 Primitive3DSequence getLineJoinSegments( 160 sal_uInt32 nSegments, 161 const attribute::MaterialAttribute3D& rMaterial, 162 double fAngle, 163 double /*fDegreeStepWidth*/, 164 double fMiterMinimumAngle, 165 basegfx::B2DLineJoin aLineJoin) 166 { 167 // nSegments is for whole circle, adapt to half circle 168 const sal_uInt32 nVerSeg(nSegments >> 1L); 169 std::vector< BasePrimitive3D* > aResultVector; 170 171 if(nVerSeg) 172 { 173 if(basegfx::B2DLINEJOIN_ROUND == aLineJoin) 174 { 175 // calculate new horizontal segments | 229 Primitive3DSequence getLineJoinSegments( 230 sal_uInt32 nSegments, 231 const attribute::MaterialAttribute3D& rMaterial, 232 double fAngle, 233 double /*fDegreeStepWidth*/, 234 double fMiterMinimumAngle, 235 basegfx::B2DLineJoin aLineJoin) 236 { 237 // nSegments is for whole circle, adapt to half circle 238 const sal_uInt32 nVerSeg(nSegments >> 1L); 239 std::vector< BasePrimitive3D* > aResultVector; 240 241 if(nVerSeg) 242 { 243 if(basegfx::B2DLINEJOIN_ROUND == aLineJoin) 244 { 245 // calculate new horizontal segments |
176 const sal_uInt32 nHorSeg((sal_uInt32)((fAngle / F_2PI) * (double)nSegments)); | 246 const sal_uInt32 nHorSeg(basegfx::fround((fAngle / F_2PI) * (double)nSegments)); |
177 178 if(nHorSeg) 179 { 180 // create half-sphere 181 const basegfx::B3DPolyPolygon aSphere(basegfx::tools::createUnitSphereFillPolyPolygon(nHorSeg, nVerSeg, true, F_PI2, -F_PI2, 0.0, fAngle)); 182 183 for(sal_uInt32 a(0L); a < aSphere.count(); a++) 184 { --- 213 unchanged lines hidden (view full) --- 398////////////////////////////////////////////////////////////////////////////// 399 400using namespace com::sun::star; 401 402////////////////////////////////////////////////////////////////////////////// 403 404namespace drawinglayer 405{ | 247 248 if(nHorSeg) 249 { 250 // create half-sphere 251 const basegfx::B3DPolyPolygon aSphere(basegfx::tools::createUnitSphereFillPolyPolygon(nHorSeg, nVerSeg, true, F_PI2, -F_PI2, 0.0, fAngle)); 252 253 for(sal_uInt32 a(0L); a < aSphere.count(); a++) 254 { --- 213 unchanged lines hidden (view full) --- 468////////////////////////////////////////////////////////////////////////////// 469 470using namespace com::sun::star; 471 472////////////////////////////////////////////////////////////////////////////// 473 474namespace drawinglayer 475{ |
406 namespace primitive3d 407 { 408 Primitive3DSequence PolygonTubePrimitive3D::impCreate3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const 409 { 410 const sal_uInt32 nPointCount(getB3DPolygon().count()); 411 std::vector< BasePrimitive3D* > aResultVector; | 476 namespace primitive3d 477 { 478 Primitive3DSequence PolygonTubePrimitive3D::impCreate3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const 479 { 480 const sal_uInt32 nPointCount(getB3DPolygon().count()); 481 std::vector< BasePrimitive3D* > aResultVector; 482 483 if(nPointCount) 484 { 485 if(basegfx::fTools::more(getRadius(), 0.0)) 486 { 487 const attribute::MaterialAttribute3D aMaterial(getBColor()); 488 static sal_uInt32 nSegments(8); // default for 3d line segments, for more quality just raise this value (in even steps) 489 const bool bClosed(getB3DPolygon().isClosed()); 490 const bool bNoLineJoin(basegfx::B2DLINEJOIN_NONE == getLineJoin()); 491 const sal_uInt32 nLoopCount(bClosed ? nPointCount : nPointCount - 1); 492 basegfx::B3DPoint aLast(getB3DPolygon().getB3DPoint(nPointCount - 1)); 493 basegfx::B3DPoint aCurr(getB3DPolygon().getB3DPoint(0)); 494 495 for(sal_uInt32 a(0); a < nLoopCount; a++) 496 { 497 // get next data 498 const basegfx::B3DPoint aNext(getB3DPolygon().getB3DPoint((a + 1) % nPointCount)); 499 const basegfx::B3DVector aForw(aNext - aCurr); 500 const double fForwLen(aForw.getLength()); 501 502 if(basegfx::fTools::more(fForwLen, 0.0)) 503 { 504 // find out if linecap is active 505 const bool bFirst(!a); 506 const bool bLast(a + 1 == nLoopCount); 507 const bool bLineCapPossible(!bClosed && (bFirst || bLast)); 508 const bool bLineCapRound(bLineCapPossible && com::sun::star::drawing::LineCap_ROUND == getLineCap()); 509 const bool bLineCapSquare(bLineCapPossible && com::sun::star::drawing::LineCap_SQUARE == getLineCap()); |
412 | 510 |
413 if(0L != nPointCount) 414 { 415 if(basegfx::fTools::more(getRadius(), 0.0)) 416 { 417 const attribute::MaterialAttribute3D aMaterial(getBColor()); 418 static sal_uInt32 nSegments(8L); // default for 3d line segments, for more quality just raise this value (in even steps) 419 const bool bClosed(getB3DPolygon().isClosed()); 420 const bool bNoLineJoin(basegfx::B2DLINEJOIN_NONE == getLineJoin()); 421 const sal_uInt32 nLoopCount(bClosed ? nPointCount : nPointCount - 1L); 422 basegfx::B3DPoint aLast(getB3DPolygon().getB3DPoint(nPointCount - 1L)); 423 basegfx::B3DPoint aCurr(getB3DPolygon().getB3DPoint(0L)); | 511 // get rotation from vector, this describes rotation from (1, 0, 0) to aForw 512 basegfx::B3DHomMatrix aRotVector(getRotationFromVector(aForw)); |
424 | 513 |
425 for(sal_uInt32 a(0L); a < nLoopCount; a++) 426 { 427 // get next data 428 const basegfx::B3DPoint aNext(getB3DPolygon().getB3DPoint((a + 1L) % nPointCount)); 429 const basegfx::B3DVector aForw(aNext - aCurr); 430 const double fForwLen(aForw.getLength()); | 514 // prepare transformations for tube and cap 515 basegfx::B3DHomMatrix aTubeTrans; 516 basegfx::B3DHomMatrix aCapTrans; |
431 | 517 |
432 if(basegfx::fTools::more(fForwLen, 0.0)) 433 { 434 // get rotation from vector, this describes rotation from (1, 0, 0) to aForw 435 basegfx::B3DHomMatrix aRotVector(getRotationFromVector(aForw)); | 518 // cap gets radius size 519 aCapTrans.scale(getRadius(), getRadius(), getRadius()); |
436 | 520 |
437 // create default transformation with scale and rotate 438 basegfx::B3DHomMatrix aVectorTrans; 439 aVectorTrans.scale(fForwLen, getRadius(), getRadius()); 440 aVectorTrans *= aRotVector; 441 aVectorTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ()); | 521 if(bLineCapSquare) 522 { 523 // when square line cap just prolong line segment in X, maybe 2 x radius when 524 // first and last (simple line segment) 525 const double fExtraLength(bFirst && bLast ? getRadius() * 2.0 : getRadius()); 526 527 aTubeTrans.scale(fForwLen + fExtraLength, getRadius(), getRadius()); |
442 | 528 |
443 if(bNoLineJoin || (!bClosed && !a)) 444 { 445 // line start edge, build transformed primitiveVector3D 446 TransformPrimitive3D* pNewTransformedA = new TransformPrimitive3D(aVectorTrans, getLineCapSegments(nSegments, aMaterial)); 447 aResultVector.push_back(pNewTransformedA); 448 } 449 else 450 { 451 const basegfx::B3DVector aBack(aCurr - aLast); 452 const double fCross(basegfx::cross(aBack, aForw).getLength()); | 529 if(bFirst) 530 { 531 // correct start positions for tube and cap when first and square prolonged 532 aTubeTrans.translate(-getRadius(), 0.0, 0.0); 533 aCapTrans.translate(-getRadius(), 0.0, 0.0); 534 } 535 } 536 else 537 { 538 // normal tube size 539 aTubeTrans.scale(fForwLen, getRadius(), getRadius()); 540 } |
453 | 541 |
454 if(!basegfx::fTools::equalZero(fCross)) 455 { 456 // line connect non-parallel, aBack, aForw, use getLineJoin() 457 const double fAngle(acos(aBack.scalar(aForw) / (fForwLen * aBack.getLength()))); // 0.0 .. F_PI2 458 Primitive3DSequence aNewList(getLineJoinSegments(nSegments, aMaterial, fAngle, getDegreeStepWidth(), getMiterMinimumAngle(), getLineJoin())); | 542 // rotate and translate tube and cap 543 aTubeTrans *= aRotVector; 544 aTubeTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ()); 545 aCapTrans *= aRotVector; 546 aCapTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ()); |
459 | 547 |
460 // calculate transformation. First, get angle in YZ between nForw projected on (1, 0, 0) and nBack 461 basegfx::B3DHomMatrix aInvRotVector(aRotVector); 462 aInvRotVector.invert(); 463 basegfx::B3DVector aTransBack(aInvRotVector * aBack); 464 const double fRotInYZ(atan2(aTransBack.getY(), aTransBack.getZ())); | 548 if(bNoLineJoin || (!bClosed && bFirst)) 549 { 550 // line start edge, build transformed primitiveVector3D 551 Primitive3DSequence aSequence; |
465 | 552 |
466 // create trans by rotating unit sphere with angle 90 degrees around Y, then 180-fRot in X. 467 // Also apply usual scaling and translation 468 basegfx::B3DHomMatrix aSphereTrans; 469 aSphereTrans.rotate(0.0, F_PI2, 0.0); 470 aSphereTrans.rotate(F_PI - fRotInYZ, 0.0, 0.0); 471 aSphereTrans *= aRotVector; 472 aSphereTrans.scale(getRadius(), getRadius(), getRadius()); 473 aSphereTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ()); | 553 if(bLineCapRound && bFirst) 554 { 555 // LineCapRound used 556 aSequence = getLineCapRoundSegments(nSegments, aMaterial); 557 } 558 else 559 { 560 // simple closing cap 561 aSequence = getLineCapSegments(nSegments, aMaterial); 562 } |
474 | 563 |
475 // line start edge, build transformed primitiveVector3D 476 TransformPrimitive3D* pNewTransformedB = new TransformPrimitive3D(aSphereTrans, aNewList); 477 aResultVector.push_back(pNewTransformedB); 478 } 479 } | 564 TransformPrimitive3D* pNewTransformedA = new TransformPrimitive3D(aCapTrans, aSequence); 565 aResultVector.push_back(pNewTransformedA); 566 } 567 else 568 { 569 const basegfx::B3DVector aBack(aCurr - aLast); 570 const double fCross(basegfx::cross(aBack, aForw).getLength()); |
480 | 571 |
481 // create line segments, build transformed primitiveVector3D 482 TransformPrimitive3D* pNewTransformedC = new TransformPrimitive3D(aVectorTrans, getLineTubeSegments(nSegments, aMaterial)); 483 aResultVector.push_back(pNewTransformedC); | 572 if(!basegfx::fTools::equalZero(fCross)) 573 { 574 // line connect non-parallel, aBack, aForw, use getLineJoin() 575 const double fAngle(acos(aBack.scalar(aForw) / (fForwLen * aBack.getLength()))); // 0.0 .. F_PI2 576 Primitive3DSequence aNewList( 577 getLineJoinSegments( 578 nSegments, 579 aMaterial, 580 fAngle, 581 getDegreeStepWidth(), 582 getMiterMinimumAngle(), 583 getLineJoin())); |
484 | 584 |
485 if(bNoLineJoin || (!bClosed && ((a + 1L) == nLoopCount))) 486 { 487 // line end edge, first rotate (mirror) and translate, then use use aRotVector 488 basegfx::B3DHomMatrix aBackTrans; 489 aBackTrans.rotate(0.0, F_PI, 0.0); 490 aBackTrans.translate(1.0, 0.0, 0.0); 491 aBackTrans.scale(fForwLen, getRadius(), getRadius()); 492 aBackTrans *= aRotVector; 493 aBackTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ()); 494 495 // line end edge, build transformed primitiveVector3D 496 TransformPrimitive3D* pNewTransformedD = new TransformPrimitive3D(aBackTrans, getLineCapSegments(nSegments, aMaterial)); 497 aResultVector.push_back(pNewTransformedD); 498 } 499 } | 585 // calculate transformation. First, get angle in YZ between nForw projected on (1, 0, 0) and nBack 586 basegfx::B3DHomMatrix aInvRotVector(aRotVector); 587 aInvRotVector.invert(); 588 basegfx::B3DVector aTransBack(aInvRotVector * aBack); 589 const double fRotInYZ(atan2(aTransBack.getY(), aTransBack.getZ())); 590 591 // create trans by rotating unit sphere with angle 90 degrees around Y, then 180-fRot in X. 592 // Also apply usual scaling and translation 593 basegfx::B3DHomMatrix aSphereTrans; 594 aSphereTrans.rotate(0.0, F_PI2, 0.0); 595 aSphereTrans.rotate(F_PI - fRotInYZ, 0.0, 0.0); 596 aSphereTrans *= aRotVector; 597 aSphereTrans.scale(getRadius(), getRadius(), getRadius()); 598 aSphereTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ()); 599 600 // line start edge, build transformed primitiveVector3D 601 aResultVector.push_back( 602 new TransformPrimitive3D( 603 aSphereTrans, 604 aNewList)); 605 } 606 } |
500 | 607 |
608 // create line segments, build transformed primitiveVector3D 609 aResultVector.push_back( 610 new TransformPrimitive3D( 611 aTubeTrans, 612 getLineTubeSegments(nSegments, aMaterial))); 613 614 if(bNoLineJoin || (!bClosed && bLast)) 615 { 616 // line end edge 617 basegfx::B3DHomMatrix aBackCapTrans; 618 619 // Mirror (line end) and radius scale 620 aBackCapTrans.rotate(0.0, F_PI, 0.0); 621 aBackCapTrans.scale(getRadius(), getRadius(), getRadius()); 622 623 if(bLineCapSquare && bLast) 624 { 625 // correct position when square and prolonged 626 aBackCapTrans.translate(fForwLen + getRadius(), 0.0, 0.0); 627 } 628 else 629 { 630 // standard position 631 aBackCapTrans.translate(fForwLen, 0.0, 0.0); 632 } 633 634 // rotate and translate to destination 635 aBackCapTrans *= aRotVector; 636 aBackCapTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ()); 637 638 // get primitiveVector3D 639 Primitive3DSequence aSequence; 640 641 if(bLineCapRound && bLast) 642 { 643 // LineCapRound used 644 aSequence = getLineCapRoundSegments(nSegments, aMaterial); 645 } 646 else 647 { 648 // simple closing cap 649 aSequence = getLineCapSegments(nSegments, aMaterial); 650 } 651 652 aResultVector.push_back( 653 new TransformPrimitive3D( 654 aBackCapTrans, 655 aSequence)); 656 } 657 } 658 |
|
501 // prepare next loop step 502 aLast = aCurr; 503 aCurr = aNext; 504 } 505 } 506 else 507 { 508 // create hairline --- 12 unchanged lines hidden (view full) --- 521 522 return aRetval; 523 } 524 525 PolygonTubePrimitive3D::PolygonTubePrimitive3D( 526 const basegfx::B3DPolygon& rPolygon, 527 const basegfx::BColor& rBColor, 528 double fRadius, basegfx::B2DLineJoin aLineJoin, | 659 // prepare next loop step 660 aLast = aCurr; 661 aCurr = aNext; 662 } 663 } 664 else 665 { 666 // create hairline --- 12 unchanged lines hidden (view full) --- 679 680 return aRetval; 681 } 682 683 PolygonTubePrimitive3D::PolygonTubePrimitive3D( 684 const basegfx::B3DPolygon& rPolygon, 685 const basegfx::BColor& rBColor, 686 double fRadius, basegfx::B2DLineJoin aLineJoin, |
687 com::sun::star::drawing::LineCap aLineCap, |
|
529 double fDegreeStepWidth, 530 double fMiterMinimumAngle) 531 : PolygonHairlinePrimitive3D(rPolygon, rBColor), 532 maLast3DDecomposition(), 533 mfRadius(fRadius), 534 mfDegreeStepWidth(fDegreeStepWidth), 535 mfMiterMinimumAngle(fMiterMinimumAngle), | 688 double fDegreeStepWidth, 689 double fMiterMinimumAngle) 690 : PolygonHairlinePrimitive3D(rPolygon, rBColor), 691 maLast3DDecomposition(), 692 mfRadius(fRadius), 693 mfDegreeStepWidth(fDegreeStepWidth), 694 mfMiterMinimumAngle(fMiterMinimumAngle), |
536 maLineJoin(aLineJoin) | 695 maLineJoin(aLineJoin), 696 maLineCap(aLineCap) |
537 { 538 } 539 540 bool PolygonTubePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const 541 { 542 if(PolygonHairlinePrimitive3D::operator==(rPrimitive)) 543 { 544 const PolygonTubePrimitive3D& rCompare = (PolygonTubePrimitive3D&)rPrimitive; 545 546 return (getRadius() == rCompare.getRadius() 547 && getDegreeStepWidth() == rCompare.getDegreeStepWidth() 548 && getMiterMinimumAngle() == rCompare.getMiterMinimumAngle() | 697 { 698 } 699 700 bool PolygonTubePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const 701 { 702 if(PolygonHairlinePrimitive3D::operator==(rPrimitive)) 703 { 704 const PolygonTubePrimitive3D& rCompare = (PolygonTubePrimitive3D&)rPrimitive; 705 706 return (getRadius() == rCompare.getRadius() 707 && getDegreeStepWidth() == rCompare.getDegreeStepWidth() 708 && getMiterMinimumAngle() == rCompare.getMiterMinimumAngle() |
549 && getLineJoin() == rCompare.getLineJoin()); | 709 && getLineJoin() == rCompare.getLineJoin() 710 && getLineCap() == rCompare.getLineCap()); |
550 } 551 552 return false; 553 } 554 555 Primitive3DSequence PolygonTubePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const 556 { 557 ::osl::MutexGuard aGuard( m_aMutex ); --- 18 unchanged lines hidden --- | 711 } 712 713 return false; 714 } 715 716 Primitive3DSequence PolygonTubePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const 717 { 718 ::osl::MutexGuard aGuard( m_aMutex ); --- 18 unchanged lines hidden --- |