1464702f4SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3464702f4SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4464702f4SAndrew Rist * or more contributor license agreements. See the NOTICE file 5464702f4SAndrew Rist * distributed with this work for additional information 6464702f4SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7464702f4SAndrew Rist * to you under the Apache License, Version 2.0 (the 8464702f4SAndrew Rist * "License"); you may not use this file except in compliance 9464702f4SAndrew Rist * with the License. You may obtain a copy of the License at 10464702f4SAndrew Rist * 11464702f4SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12464702f4SAndrew Rist * 13464702f4SAndrew Rist * Unless required by applicable law or agreed to in writing, 14464702f4SAndrew Rist * software distributed under the License is distributed on an 15464702f4SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16464702f4SAndrew Rist * KIND, either express or implied. See the License for the 17464702f4SAndrew Rist * specific language governing permissions and limitations 18464702f4SAndrew Rist * under the License. 19464702f4SAndrew Rist * 20464702f4SAndrew Rist *************************************************************/ 21464702f4SAndrew Rist 22464702f4SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <drawinglayer/primitive3d/polygontubeprimitive3d.hxx> 28cdf0e10cSrcweir #include <drawinglayer/attribute/materialattribute3d.hxx> 29cdf0e10cSrcweir #include <basegfx/matrix/b3dhommatrix.hxx> 30cdf0e10cSrcweir #include <basegfx/polygon/b3dpolypolygon.hxx> 31cdf0e10cSrcweir #include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx> 32cdf0e10cSrcweir #include <basegfx/polygon/b3dpolypolygontools.hxx> 33cdf0e10cSrcweir #include <drawinglayer/primitive3d/transformprimitive3d.hxx> 34cdf0e10cSrcweir #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx> 35cdf0e10cSrcweir 36cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 37cdf0e10cSrcweir 38cdf0e10cSrcweir namespace drawinglayer 39cdf0e10cSrcweir { 40cdf0e10cSrcweir namespace primitive3d 41cdf0e10cSrcweir { 42cdf0e10cSrcweir namespace // anonymous namespace 43cdf0e10cSrcweir { getLineTubeSegments(sal_uInt32 nSegments,const attribute::MaterialAttribute3D & rMaterial)44cdf0e10cSrcweir Primitive3DSequence getLineTubeSegments( 45cdf0e10cSrcweir sal_uInt32 nSegments, 46cdf0e10cSrcweir const attribute::MaterialAttribute3D& rMaterial) 47cdf0e10cSrcweir { 48cdf0e10cSrcweir // static data for buffered tube primitives 49cdf0e10cSrcweir static Primitive3DSequence aLineTubeList; 50cdf0e10cSrcweir static sal_uInt32 nLineTubeSegments(0L); 51cdf0e10cSrcweir static attribute::MaterialAttribute3D aLineMaterial; 52cdf0e10cSrcweir 53cdf0e10cSrcweir // may exclusively change static data, use mutex 54cdf0e10cSrcweir ::osl::Mutex m_mutex; 55cdf0e10cSrcweir 56cdf0e10cSrcweir if(nSegments != nLineTubeSegments || !(rMaterial == aLineMaterial)) 57cdf0e10cSrcweir { 58cdf0e10cSrcweir nLineTubeSegments = nSegments; 59cdf0e10cSrcweir aLineMaterial = rMaterial; 60cdf0e10cSrcweir aLineTubeList = Primitive3DSequence(); 61cdf0e10cSrcweir } 62cdf0e10cSrcweir 63cdf0e10cSrcweir if(!aLineTubeList.hasElements() && 0L != nLineTubeSegments) 64cdf0e10cSrcweir { 65cdf0e10cSrcweir const basegfx::B3DPoint aLeft(0.0, 0.0, 0.0); 66cdf0e10cSrcweir const basegfx::B3DPoint aRight(1.0, 0.0, 0.0); 67cdf0e10cSrcweir basegfx::B3DPoint aLastLeft(0.0, 1.0, 0.0); 68cdf0e10cSrcweir basegfx::B3DPoint aLastRight(1.0, 1.0, 0.0); 69cdf0e10cSrcweir basegfx::B3DHomMatrix aRot; 70cdf0e10cSrcweir aRot.rotate(F_2PI / (double)nLineTubeSegments, 0.0, 0.0); 71cdf0e10cSrcweir aLineTubeList.realloc(nLineTubeSegments); 72cdf0e10cSrcweir 73cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nLineTubeSegments; a++) 74cdf0e10cSrcweir { 75cdf0e10cSrcweir const basegfx::B3DPoint aNextLeft(aRot * aLastLeft); 76cdf0e10cSrcweir const basegfx::B3DPoint aNextRight(aRot * aLastRight); 77cdf0e10cSrcweir basegfx::B3DPolygon aNewPolygon; 78cdf0e10cSrcweir 79cdf0e10cSrcweir aNewPolygon.append(aNextLeft); 80cdf0e10cSrcweir aNewPolygon.setNormal(0L, basegfx::B3DVector(aNextLeft - aLeft)); 81cdf0e10cSrcweir 82cdf0e10cSrcweir aNewPolygon.append(aLastLeft); 83cdf0e10cSrcweir aNewPolygon.setNormal(1L, basegfx::B3DVector(aLastLeft - aLeft)); 84cdf0e10cSrcweir 85cdf0e10cSrcweir aNewPolygon.append(aLastRight); 86cdf0e10cSrcweir aNewPolygon.setNormal(2L, basegfx::B3DVector(aLastRight - aRight)); 87cdf0e10cSrcweir 88cdf0e10cSrcweir aNewPolygon.append(aNextRight); 89cdf0e10cSrcweir aNewPolygon.setNormal(3L, basegfx::B3DVector(aNextRight - aRight)); 90cdf0e10cSrcweir 91cdf0e10cSrcweir aNewPolygon.setClosed(true); 92cdf0e10cSrcweir 93cdf0e10cSrcweir const basegfx::B3DPolyPolygon aNewPolyPolygon(aNewPolygon); 94cdf0e10cSrcweir const Primitive3DReference xRef(new PolyPolygonMaterialPrimitive3D(aNewPolyPolygon, aLineMaterial, false)); 95cdf0e10cSrcweir aLineTubeList[a] = xRef; 96cdf0e10cSrcweir 97cdf0e10cSrcweir aLastLeft = aNextLeft; 98cdf0e10cSrcweir aLastRight = aNextRight; 99cdf0e10cSrcweir } 100cdf0e10cSrcweir } 101cdf0e10cSrcweir 102cdf0e10cSrcweir return aLineTubeList; 103cdf0e10cSrcweir } 104cdf0e10cSrcweir getLineCapSegments(sal_uInt32 nSegments,const attribute::MaterialAttribute3D & rMaterial)105cdf0e10cSrcweir Primitive3DSequence getLineCapSegments( 106cdf0e10cSrcweir sal_uInt32 nSegments, 107cdf0e10cSrcweir const attribute::MaterialAttribute3D& rMaterial) 108cdf0e10cSrcweir { 109cdf0e10cSrcweir // static data for buffered tube primitives 110cdf0e10cSrcweir static Primitive3DSequence aLineCapList; 111cdf0e10cSrcweir static sal_uInt32 nLineCapSegments(0L); 112cdf0e10cSrcweir static attribute::MaterialAttribute3D aLineMaterial; 113cdf0e10cSrcweir 114cdf0e10cSrcweir // may exclusively change static data, use mutex 115cdf0e10cSrcweir ::osl::Mutex m_mutex; 116cdf0e10cSrcweir 117cdf0e10cSrcweir if(nSegments != nLineCapSegments || !(rMaterial == aLineMaterial)) 118cdf0e10cSrcweir { 119cdf0e10cSrcweir nLineCapSegments = nSegments; 120cdf0e10cSrcweir aLineMaterial = rMaterial; 121cdf0e10cSrcweir aLineCapList = Primitive3DSequence(); 122cdf0e10cSrcweir } 123cdf0e10cSrcweir 124cdf0e10cSrcweir if(!aLineCapList.hasElements() && 0L != nLineCapSegments) 125cdf0e10cSrcweir { 126cdf0e10cSrcweir const basegfx::B3DPoint aNull(0.0, 0.0, 0.0); 127cdf0e10cSrcweir basegfx::B3DPoint aLast(0.0, 1.0, 0.0); 128cdf0e10cSrcweir basegfx::B3DHomMatrix aRot; 129cdf0e10cSrcweir aRot.rotate(F_2PI / (double)nLineCapSegments, 0.0, 0.0); 130cdf0e10cSrcweir aLineCapList.realloc(nLineCapSegments); 131cdf0e10cSrcweir 132cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nLineCapSegments; a++) 133cdf0e10cSrcweir { 134cdf0e10cSrcweir const basegfx::B3DPoint aNext(aRot * aLast); 135cdf0e10cSrcweir basegfx::B3DPolygon aNewPolygon; 136cdf0e10cSrcweir 137cdf0e10cSrcweir aNewPolygon.append(aLast); 138cdf0e10cSrcweir aNewPolygon.setNormal(0L, basegfx::B3DVector(aLast - aNull)); 139cdf0e10cSrcweir 140cdf0e10cSrcweir aNewPolygon.append(aNext); 141cdf0e10cSrcweir aNewPolygon.setNormal(1L, basegfx::B3DVector(aNext - aNull)); 142cdf0e10cSrcweir 143cdf0e10cSrcweir aNewPolygon.append(aNull); 144cdf0e10cSrcweir aNewPolygon.setNormal(2L, basegfx::B3DVector(-1.0, 0.0, 0.0)); 145cdf0e10cSrcweir 146cdf0e10cSrcweir aNewPolygon.setClosed(true); 147cdf0e10cSrcweir 148cdf0e10cSrcweir const basegfx::B3DPolyPolygon aNewPolyPolygon(aNewPolygon); 149cdf0e10cSrcweir const Primitive3DReference xRef(new PolyPolygonMaterialPrimitive3D(aNewPolyPolygon, aLineMaterial, false)); 150cdf0e10cSrcweir aLineCapList[a] = xRef; 151cdf0e10cSrcweir 152cdf0e10cSrcweir aLast = aNext; 153cdf0e10cSrcweir } 154cdf0e10cSrcweir } 155cdf0e10cSrcweir 156cdf0e10cSrcweir return aLineCapList; 157cdf0e10cSrcweir } 158cdf0e10cSrcweir getLineCapRoundSegments(sal_uInt32 nSegments,const attribute::MaterialAttribute3D & rMaterial)159*5aaf853bSArmin Le Grand Primitive3DSequence getLineCapRoundSegments( 160*5aaf853bSArmin Le Grand sal_uInt32 nSegments, 161*5aaf853bSArmin Le Grand const attribute::MaterialAttribute3D& rMaterial) 162*5aaf853bSArmin Le Grand { 163*5aaf853bSArmin Le Grand // static data for buffered tube primitives 164*5aaf853bSArmin Le Grand static Primitive3DSequence aLineCapRoundList; 165*5aaf853bSArmin Le Grand static sal_uInt32 nLineCapRoundSegments(0); 166*5aaf853bSArmin Le Grand static attribute::MaterialAttribute3D aLineMaterial; 167*5aaf853bSArmin Le Grand 168*5aaf853bSArmin Le Grand // may exclusively change static data, use mutex 169*5aaf853bSArmin Le Grand ::osl::Mutex m_mutex; 170*5aaf853bSArmin Le Grand 171*5aaf853bSArmin Le Grand if(nSegments != nLineCapRoundSegments || !(rMaterial == aLineMaterial)) 172*5aaf853bSArmin Le Grand { 173*5aaf853bSArmin Le Grand nLineCapRoundSegments = nSegments; 174*5aaf853bSArmin Le Grand aLineMaterial = rMaterial; 175*5aaf853bSArmin Le Grand aLineCapRoundList = Primitive3DSequence(); 176*5aaf853bSArmin Le Grand } 177*5aaf853bSArmin Le Grand 178*5aaf853bSArmin Le Grand if(!aLineCapRoundList.hasElements() && nLineCapRoundSegments) 179*5aaf853bSArmin Le Grand { 180*5aaf853bSArmin Le Grand // calculate new horizontal segments 181*5aaf853bSArmin Le Grand sal_uInt32 nVerSeg(nSegments / 2); 182*5aaf853bSArmin Le Grand 183*5aaf853bSArmin Le Grand if(nVerSeg < 1) 184*5aaf853bSArmin Le Grand { 185*5aaf853bSArmin Le Grand nVerSeg = 1; 186*5aaf853bSArmin Le Grand } 187*5aaf853bSArmin Le Grand 188*5aaf853bSArmin Le Grand // create half-sphere; upper half of unit sphere 189*5aaf853bSArmin Le Grand basegfx::B3DPolyPolygon aSphere( 190*5aaf853bSArmin Le Grand basegfx::tools::createUnitSphereFillPolyPolygon( 191*5aaf853bSArmin Le Grand nSegments, 192*5aaf853bSArmin Le Grand nVerSeg, 193*5aaf853bSArmin Le Grand true, 194*5aaf853bSArmin Le Grand F_PI2, 0.0, 195*5aaf853bSArmin Le Grand 0.0, F_2PI)); 196*5aaf853bSArmin Le Grand const sal_uInt32 nCount(aSphere.count()); 197*5aaf853bSArmin Le Grand 198*5aaf853bSArmin Le Grand if(nCount) 199*5aaf853bSArmin Le Grand { 200*5aaf853bSArmin Le Grand // rotate to have sphere cap orientned to negative X-Axis; do not 201*5aaf853bSArmin Le Grand // forget to transform normals, too 202*5aaf853bSArmin Le Grand basegfx::B3DHomMatrix aSphereTrans; 203*5aaf853bSArmin Le Grand 204*5aaf853bSArmin Le Grand aSphereTrans.rotate(0.0, 0.0, F_PI2); 205*5aaf853bSArmin Le Grand aSphere.transform(aSphereTrans); 206*5aaf853bSArmin Le Grand aSphere.transformNormals(aSphereTrans); 207*5aaf853bSArmin Le Grand 208*5aaf853bSArmin Le Grand // realloc for primitives and create based on polygon snippets 209*5aaf853bSArmin Le Grand aLineCapRoundList.realloc(nCount); 210*5aaf853bSArmin Le Grand 211*5aaf853bSArmin Le Grand for(sal_uInt32 a(0); a < nCount; a++) 212*5aaf853bSArmin Le Grand { 213*5aaf853bSArmin Le Grand const basegfx::B3DPolygon aPartPolygon(aSphere.getB3DPolygon(a)); 214*5aaf853bSArmin Le Grand const basegfx::B3DPolyPolygon aPartPolyPolygon(aPartPolygon); 215*5aaf853bSArmin Le Grand 216*5aaf853bSArmin Le Grand // need to create one primitive per Polygon since the primitive 217*5aaf853bSArmin Le Grand // is for planar PolyPolygons which is definitely not the case here 218*5aaf853bSArmin Le Grand aLineCapRoundList[a] = new PolyPolygonMaterialPrimitive3D( 219*5aaf853bSArmin Le Grand aPartPolyPolygon, 220*5aaf853bSArmin Le Grand rMaterial, 221*5aaf853bSArmin Le Grand false); 222*5aaf853bSArmin Le Grand } 223*5aaf853bSArmin Le Grand } 224*5aaf853bSArmin Le Grand } 225*5aaf853bSArmin Le Grand 226*5aaf853bSArmin Le Grand return aLineCapRoundList; 227*5aaf853bSArmin Le Grand } 228*5aaf853bSArmin Le Grand getLineJoinSegments(sal_uInt32 nSegments,const attribute::MaterialAttribute3D & rMaterial,double fAngle,double,double fMiterMinimumAngle,basegfx::B2DLineJoin aLineJoin)229cdf0e10cSrcweir Primitive3DSequence getLineJoinSegments( 230cdf0e10cSrcweir sal_uInt32 nSegments, 231cdf0e10cSrcweir const attribute::MaterialAttribute3D& rMaterial, 232cdf0e10cSrcweir double fAngle, 233cdf0e10cSrcweir double /*fDegreeStepWidth*/, 234cdf0e10cSrcweir double fMiterMinimumAngle, 235cdf0e10cSrcweir basegfx::B2DLineJoin aLineJoin) 236cdf0e10cSrcweir { 237cdf0e10cSrcweir // nSegments is for whole circle, adapt to half circle 238cdf0e10cSrcweir const sal_uInt32 nVerSeg(nSegments >> 1L); 239cdf0e10cSrcweir std::vector< BasePrimitive3D* > aResultVector; 240cdf0e10cSrcweir 241cdf0e10cSrcweir if(nVerSeg) 242cdf0e10cSrcweir { 243cdf0e10cSrcweir if(basegfx::B2DLINEJOIN_ROUND == aLineJoin) 244cdf0e10cSrcweir { 245cdf0e10cSrcweir // calculate new horizontal segments 246*5aaf853bSArmin Le Grand const sal_uInt32 nHorSeg(basegfx::fround((fAngle / F_2PI) * (double)nSegments)); 247cdf0e10cSrcweir 248cdf0e10cSrcweir if(nHorSeg) 249cdf0e10cSrcweir { 250cdf0e10cSrcweir // create half-sphere 251cdf0e10cSrcweir const basegfx::B3DPolyPolygon aSphere(basegfx::tools::createUnitSphereFillPolyPolygon(nHorSeg, nVerSeg, true, F_PI2, -F_PI2, 0.0, fAngle)); 252cdf0e10cSrcweir 253cdf0e10cSrcweir for(sal_uInt32 a(0L); a < aSphere.count(); a++) 254cdf0e10cSrcweir { 255cdf0e10cSrcweir const basegfx::B3DPolygon aPartPolygon(aSphere.getB3DPolygon(a)); 256cdf0e10cSrcweir const basegfx::B3DPolyPolygon aPartPolyPolygon(aPartPolygon); 257cdf0e10cSrcweir BasePrimitive3D* pNew = new PolyPolygonMaterialPrimitive3D(aPartPolyPolygon, rMaterial, false); 258cdf0e10cSrcweir aResultVector.push_back(pNew); 259cdf0e10cSrcweir } 260cdf0e10cSrcweir } 261cdf0e10cSrcweir else 262cdf0e10cSrcweir { 263cdf0e10cSrcweir // fallback to bevel when there is not at least one segment hor and ver 264cdf0e10cSrcweir aLineJoin = basegfx::B2DLINEJOIN_BEVEL; 265cdf0e10cSrcweir } 266cdf0e10cSrcweir } 267cdf0e10cSrcweir 268cdf0e10cSrcweir if(basegfx::B2DLINEJOIN_MIDDLE == aLineJoin 269cdf0e10cSrcweir || basegfx::B2DLINEJOIN_BEVEL == aLineJoin 270cdf0e10cSrcweir || basegfx::B2DLINEJOIN_MITER == aLineJoin) 271cdf0e10cSrcweir { 272cdf0e10cSrcweir if(basegfx::B2DLINEJOIN_MITER == aLineJoin) 273cdf0e10cSrcweir { 274cdf0e10cSrcweir const double fMiterAngle(fAngle/2.0); 275cdf0e10cSrcweir 276cdf0e10cSrcweir if(fMiterAngle < fMiterMinimumAngle) 277cdf0e10cSrcweir { 278cdf0e10cSrcweir // fallback to bevel when miter's angle is too small 279cdf0e10cSrcweir aLineJoin = basegfx::B2DLINEJOIN_BEVEL; 280cdf0e10cSrcweir } 281cdf0e10cSrcweir } 282cdf0e10cSrcweir 283cdf0e10cSrcweir const double fInc(F_PI / (double)nVerSeg); 284cdf0e10cSrcweir const double fSin(sin(-fAngle)); 285cdf0e10cSrcweir const double fCos(cos(-fAngle)); 286cdf0e10cSrcweir const bool bMiter(basegfx::B2DLINEJOIN_MITER == aLineJoin); 287cdf0e10cSrcweir const double fMiterSin(bMiter ? sin(-(fAngle/2.0)) : 0.0); 288cdf0e10cSrcweir const double fMiterCos(bMiter ? cos(-(fAngle/2.0)) : 0.0); 289cdf0e10cSrcweir double fPos(-F_PI2); 290cdf0e10cSrcweir basegfx::B3DPoint aPointOnXY, aPointRotY, aNextPointOnXY, aNextPointRotY; 291cdf0e10cSrcweir basegfx::B3DPoint aCurrMiter, aNextMiter; 292cdf0e10cSrcweir basegfx::B3DPolygon aNewPolygon, aMiterPolygon; 293cdf0e10cSrcweir 294cdf0e10cSrcweir // close polygon 295cdf0e10cSrcweir aNewPolygon.setClosed(true); 296cdf0e10cSrcweir aMiterPolygon.setClosed(true); 297cdf0e10cSrcweir 298cdf0e10cSrcweir for(sal_uInt32 a(0L); a < nVerSeg; a++) 299cdf0e10cSrcweir { 300cdf0e10cSrcweir const bool bFirst(0L == a); 301cdf0e10cSrcweir const bool bLast(a + 1L == nVerSeg); 302cdf0e10cSrcweir 303cdf0e10cSrcweir if(bFirst || !bLast) 304cdf0e10cSrcweir { 305cdf0e10cSrcweir fPos += fInc; 306cdf0e10cSrcweir 307cdf0e10cSrcweir aNextPointOnXY = basegfx::B3DPoint( 308cdf0e10cSrcweir cos(fPos), 309cdf0e10cSrcweir sin(fPos), 310cdf0e10cSrcweir 0.0); 311cdf0e10cSrcweir 312cdf0e10cSrcweir aNextPointRotY = basegfx::B3DPoint( 313cdf0e10cSrcweir aNextPointOnXY.getX() * fCos, 314cdf0e10cSrcweir aNextPointOnXY.getY(), 315cdf0e10cSrcweir aNextPointOnXY.getX() * fSin); 316cdf0e10cSrcweir 317cdf0e10cSrcweir if(bMiter) 318cdf0e10cSrcweir { 319cdf0e10cSrcweir aNextMiter = basegfx::B3DPoint( 320cdf0e10cSrcweir aNextPointOnXY.getX(), 321cdf0e10cSrcweir aNextPointOnXY.getY(), 322cdf0e10cSrcweir fMiterSin * (aNextPointOnXY.getX() / fMiterCos)); 323cdf0e10cSrcweir } 324cdf0e10cSrcweir } 325cdf0e10cSrcweir 326cdf0e10cSrcweir if(bFirst) 327cdf0e10cSrcweir { 328cdf0e10cSrcweir aNewPolygon.clear(); 329cdf0e10cSrcweir 330cdf0e10cSrcweir if(bMiter) 331cdf0e10cSrcweir { 332cdf0e10cSrcweir aNewPolygon.append(basegfx::B3DPoint(0.0, -1.0, 0.0)); 333cdf0e10cSrcweir aNewPolygon.append(aNextPointOnXY); 334cdf0e10cSrcweir aNewPolygon.append(aNextMiter); 335cdf0e10cSrcweir 336cdf0e10cSrcweir aMiterPolygon.clear(); 337cdf0e10cSrcweir aMiterPolygon.append(basegfx::B3DPoint(0.0, -1.0, 0.0)); 338cdf0e10cSrcweir aMiterPolygon.append(aNextMiter); 339cdf0e10cSrcweir aMiterPolygon.append(aNextPointRotY); 340cdf0e10cSrcweir } 341cdf0e10cSrcweir else 342cdf0e10cSrcweir { 343cdf0e10cSrcweir aNewPolygon.append(basegfx::B3DPoint(0.0, -1.0, 0.0)); 344cdf0e10cSrcweir aNewPolygon.append(aNextPointOnXY); 345cdf0e10cSrcweir aNewPolygon.append(aNextPointRotY); 346cdf0e10cSrcweir } 347cdf0e10cSrcweir } 348cdf0e10cSrcweir else if(bLast) 349cdf0e10cSrcweir { 350cdf0e10cSrcweir aNewPolygon.clear(); 351cdf0e10cSrcweir 352cdf0e10cSrcweir if(bMiter) 353cdf0e10cSrcweir { 354cdf0e10cSrcweir aNewPolygon.append(basegfx::B3DPoint(0.0, 1.0, 0.0)); 355cdf0e10cSrcweir aNewPolygon.append(aCurrMiter); 356cdf0e10cSrcweir aNewPolygon.append(aPointOnXY); 357cdf0e10cSrcweir 358cdf0e10cSrcweir aMiterPolygon.clear(); 359cdf0e10cSrcweir aMiterPolygon.append(basegfx::B3DPoint(0.0, 1.0, 0.0)); 360cdf0e10cSrcweir aMiterPolygon.append(aPointRotY); 361cdf0e10cSrcweir aMiterPolygon.append(aCurrMiter); 362cdf0e10cSrcweir } 363cdf0e10cSrcweir else 364cdf0e10cSrcweir { 365cdf0e10cSrcweir aNewPolygon.append(basegfx::B3DPoint(0.0, 1.0, 0.0)); 366cdf0e10cSrcweir aNewPolygon.append(aPointRotY); 367cdf0e10cSrcweir aNewPolygon.append(aPointOnXY); 368cdf0e10cSrcweir } 369cdf0e10cSrcweir } 370cdf0e10cSrcweir else 371cdf0e10cSrcweir { 372cdf0e10cSrcweir aNewPolygon.clear(); 373cdf0e10cSrcweir 374cdf0e10cSrcweir if(bMiter) 375cdf0e10cSrcweir { 376cdf0e10cSrcweir aNewPolygon.append(aPointOnXY); 377cdf0e10cSrcweir aNewPolygon.append(aNextPointOnXY); 378cdf0e10cSrcweir aNewPolygon.append(aNextMiter); 379cdf0e10cSrcweir aNewPolygon.append(aCurrMiter); 380cdf0e10cSrcweir 381cdf0e10cSrcweir aMiterPolygon.clear(); 382cdf0e10cSrcweir aMiterPolygon.append(aCurrMiter); 383cdf0e10cSrcweir aMiterPolygon.append(aNextMiter); 384cdf0e10cSrcweir aMiterPolygon.append(aNextPointRotY); 385cdf0e10cSrcweir aMiterPolygon.append(aPointRotY); 386cdf0e10cSrcweir } 387cdf0e10cSrcweir else 388cdf0e10cSrcweir { 389cdf0e10cSrcweir aNewPolygon.append(aPointRotY); 390cdf0e10cSrcweir aNewPolygon.append(aPointOnXY); 391cdf0e10cSrcweir aNewPolygon.append(aNextPointOnXY); 392cdf0e10cSrcweir aNewPolygon.append(aNextPointRotY); 393cdf0e10cSrcweir } 394cdf0e10cSrcweir } 395cdf0e10cSrcweir 396cdf0e10cSrcweir // set normals 397cdf0e10cSrcweir for(sal_uInt32 b(0L); b < aNewPolygon.count(); b++) 398cdf0e10cSrcweir { 399cdf0e10cSrcweir aNewPolygon.setNormal(b, basegfx::B3DVector(aNewPolygon.getB3DPoint(b))); 400cdf0e10cSrcweir } 401cdf0e10cSrcweir 402cdf0e10cSrcweir // create primitive 403cdf0e10cSrcweir if(aNewPolygon.count()) 404cdf0e10cSrcweir { 405cdf0e10cSrcweir const basegfx::B3DPolyPolygon aNewPolyPolygon(aNewPolygon); 406cdf0e10cSrcweir BasePrimitive3D* pNew = new PolyPolygonMaterialPrimitive3D(aNewPolyPolygon, rMaterial, false); 407cdf0e10cSrcweir aResultVector.push_back(pNew); 408cdf0e10cSrcweir } 409cdf0e10cSrcweir 410cdf0e10cSrcweir if(bMiter && aMiterPolygon.count()) 411cdf0e10cSrcweir { 412cdf0e10cSrcweir // set normals 413cdf0e10cSrcweir for(sal_uInt32 c(0L); c < aMiterPolygon.count(); c++) 414cdf0e10cSrcweir { 415cdf0e10cSrcweir aMiterPolygon.setNormal(c, basegfx::B3DVector(aMiterPolygon.getB3DPoint(c))); 416cdf0e10cSrcweir } 417cdf0e10cSrcweir 418cdf0e10cSrcweir // create primitive 419cdf0e10cSrcweir const basegfx::B3DPolyPolygon aMiterPolyPolygon(aMiterPolygon); 420cdf0e10cSrcweir BasePrimitive3D* pNew = new PolyPolygonMaterialPrimitive3D(aMiterPolyPolygon, rMaterial, false); 421cdf0e10cSrcweir aResultVector.push_back(pNew); 422cdf0e10cSrcweir } 423cdf0e10cSrcweir 424cdf0e10cSrcweir // prepare next step 425cdf0e10cSrcweir if(bFirst || !bLast) 426cdf0e10cSrcweir { 427cdf0e10cSrcweir aPointOnXY = aNextPointOnXY; 428cdf0e10cSrcweir aPointRotY = aNextPointRotY; 429cdf0e10cSrcweir 430cdf0e10cSrcweir if(bMiter) 431cdf0e10cSrcweir { 432cdf0e10cSrcweir aCurrMiter = aNextMiter; 433cdf0e10cSrcweir } 434cdf0e10cSrcweir } 435cdf0e10cSrcweir } 436cdf0e10cSrcweir } 437cdf0e10cSrcweir } 438cdf0e10cSrcweir 439cdf0e10cSrcweir Primitive3DSequence aRetval(aResultVector.size()); 440cdf0e10cSrcweir 441cdf0e10cSrcweir for(sal_uInt32 a(0L); a < aResultVector.size(); a++) 442cdf0e10cSrcweir { 443cdf0e10cSrcweir aRetval[a] = Primitive3DReference(aResultVector[a]); 444cdf0e10cSrcweir } 445cdf0e10cSrcweir 446cdf0e10cSrcweir return aRetval; 447cdf0e10cSrcweir } 448cdf0e10cSrcweir getRotationFromVector(const basegfx::B3DVector & rVector)449cdf0e10cSrcweir basegfx::B3DHomMatrix getRotationFromVector(const basegfx::B3DVector& rVector) 450cdf0e10cSrcweir { 451cdf0e10cSrcweir // build transformation from unit vector to vector 452cdf0e10cSrcweir basegfx::B3DHomMatrix aRetval; 453cdf0e10cSrcweir 454cdf0e10cSrcweir // get applied rotations from angles in XY and in XZ (cartesian) 455cdf0e10cSrcweir const double fRotInXY(atan2(rVector.getY(), rVector.getXZLength())); 456cdf0e10cSrcweir const double fRotInXZ(atan2(-rVector.getZ(), rVector.getX())); 457cdf0e10cSrcweir 458cdf0e10cSrcweir // apply rotations. Rot around Z needs to be done first, so apply in two steps 459cdf0e10cSrcweir aRetval.rotate(0.0, 0.0, fRotInXY); 460cdf0e10cSrcweir aRetval.rotate(0.0, fRotInXZ, 0.0); 461cdf0e10cSrcweir 462cdf0e10cSrcweir return aRetval; 463cdf0e10cSrcweir } 464cdf0e10cSrcweir } // end of anonymous namespace 465cdf0e10cSrcweir } // end of namespace primitive3d 466cdf0e10cSrcweir } // end of namespace drawinglayer 467cdf0e10cSrcweir 468cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 469cdf0e10cSrcweir 470cdf0e10cSrcweir using namespace com::sun::star; 471cdf0e10cSrcweir 472cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 473cdf0e10cSrcweir 474cdf0e10cSrcweir namespace drawinglayer 475cdf0e10cSrcweir { 476*5aaf853bSArmin Le Grand namespace primitive3d 477*5aaf853bSArmin Le Grand { impCreate3DDecomposition(const geometry::ViewInformation3D &) const478*5aaf853bSArmin Le Grand Primitive3DSequence PolygonTubePrimitive3D::impCreate3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const 479*5aaf853bSArmin Le Grand { 480*5aaf853bSArmin Le Grand const sal_uInt32 nPointCount(getB3DPolygon().count()); 481*5aaf853bSArmin Le Grand std::vector< BasePrimitive3D* > aResultVector; 482*5aaf853bSArmin Le Grand 483*5aaf853bSArmin Le Grand if(nPointCount) 484*5aaf853bSArmin Le Grand { 485*5aaf853bSArmin Le Grand if(basegfx::fTools::more(getRadius(), 0.0)) 486*5aaf853bSArmin Le Grand { 487*5aaf853bSArmin Le Grand const attribute::MaterialAttribute3D aMaterial(getBColor()); 488*5aaf853bSArmin Le Grand static sal_uInt32 nSegments(8); // default for 3d line segments, for more quality just raise this value (in even steps) 489*5aaf853bSArmin Le Grand const bool bClosed(getB3DPolygon().isClosed()); 490*5aaf853bSArmin Le Grand const bool bNoLineJoin(basegfx::B2DLINEJOIN_NONE == getLineJoin()); 491*5aaf853bSArmin Le Grand const sal_uInt32 nLoopCount(bClosed ? nPointCount : nPointCount - 1); 492*5aaf853bSArmin Le Grand basegfx::B3DPoint aLast(getB3DPolygon().getB3DPoint(nPointCount - 1)); 493*5aaf853bSArmin Le Grand basegfx::B3DPoint aCurr(getB3DPolygon().getB3DPoint(0)); 494*5aaf853bSArmin Le Grand 495*5aaf853bSArmin Le Grand for(sal_uInt32 a(0); a < nLoopCount; a++) 496*5aaf853bSArmin Le Grand { 497*5aaf853bSArmin Le Grand // get next data 498*5aaf853bSArmin Le Grand const basegfx::B3DPoint aNext(getB3DPolygon().getB3DPoint((a + 1) % nPointCount)); 499*5aaf853bSArmin Le Grand const basegfx::B3DVector aForw(aNext - aCurr); 500*5aaf853bSArmin Le Grand const double fForwLen(aForw.getLength()); 501*5aaf853bSArmin Le Grand 502*5aaf853bSArmin Le Grand if(basegfx::fTools::more(fForwLen, 0.0)) 503*5aaf853bSArmin Le Grand { 504*5aaf853bSArmin Le Grand // find out if linecap is active 505*5aaf853bSArmin Le Grand const bool bFirst(!a); 506*5aaf853bSArmin Le Grand const bool bLast(a + 1 == nLoopCount); 507*5aaf853bSArmin Le Grand const bool bLineCapPossible(!bClosed && (bFirst || bLast)); 508*5aaf853bSArmin Le Grand const bool bLineCapRound(bLineCapPossible && com::sun::star::drawing::LineCap_ROUND == getLineCap()); 509*5aaf853bSArmin Le Grand const bool bLineCapSquare(bLineCapPossible && com::sun::star::drawing::LineCap_SQUARE == getLineCap()); 510*5aaf853bSArmin Le Grand 511*5aaf853bSArmin Le Grand // get rotation from vector, this describes rotation from (1, 0, 0) to aForw 512*5aaf853bSArmin Le Grand basegfx::B3DHomMatrix aRotVector(getRotationFromVector(aForw)); 513*5aaf853bSArmin Le Grand 514*5aaf853bSArmin Le Grand // prepare transformations for tube and cap 515*5aaf853bSArmin Le Grand basegfx::B3DHomMatrix aTubeTrans; 516*5aaf853bSArmin Le Grand basegfx::B3DHomMatrix aCapTrans; 517*5aaf853bSArmin Le Grand 518*5aaf853bSArmin Le Grand // cap gets radius size 519*5aaf853bSArmin Le Grand aCapTrans.scale(getRadius(), getRadius(), getRadius()); 520*5aaf853bSArmin Le Grand 521*5aaf853bSArmin Le Grand if(bLineCapSquare) 522*5aaf853bSArmin Le Grand { 523*5aaf853bSArmin Le Grand // when square line cap just prolong line segment in X, maybe 2 x radius when 524*5aaf853bSArmin Le Grand // first and last (simple line segment) 525*5aaf853bSArmin Le Grand const double fExtraLength(bFirst && bLast ? getRadius() * 2.0 : getRadius()); 526*5aaf853bSArmin Le Grand 527*5aaf853bSArmin Le Grand aTubeTrans.scale(fForwLen + fExtraLength, getRadius(), getRadius()); 528*5aaf853bSArmin Le Grand 529*5aaf853bSArmin Le Grand if(bFirst) 530*5aaf853bSArmin Le Grand { 531*5aaf853bSArmin Le Grand // correct start positions for tube and cap when first and square prolonged 532*5aaf853bSArmin Le Grand aTubeTrans.translate(-getRadius(), 0.0, 0.0); 533*5aaf853bSArmin Le Grand aCapTrans.translate(-getRadius(), 0.0, 0.0); 534*5aaf853bSArmin Le Grand } 535*5aaf853bSArmin Le Grand } 536*5aaf853bSArmin Le Grand else 537*5aaf853bSArmin Le Grand { 538*5aaf853bSArmin Le Grand // normal tube size 539*5aaf853bSArmin Le Grand aTubeTrans.scale(fForwLen, getRadius(), getRadius()); 540*5aaf853bSArmin Le Grand } 541*5aaf853bSArmin Le Grand 542*5aaf853bSArmin Le Grand // rotate and translate tube and cap 543*5aaf853bSArmin Le Grand aTubeTrans *= aRotVector; 544*5aaf853bSArmin Le Grand aTubeTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ()); 545*5aaf853bSArmin Le Grand aCapTrans *= aRotVector; 546*5aaf853bSArmin Le Grand aCapTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ()); 547*5aaf853bSArmin Le Grand 548*5aaf853bSArmin Le Grand if(bNoLineJoin || (!bClosed && bFirst)) 549*5aaf853bSArmin Le Grand { 550*5aaf853bSArmin Le Grand // line start edge, build transformed primitiveVector3D 551*5aaf853bSArmin Le Grand Primitive3DSequence aSequence; 552*5aaf853bSArmin Le Grand 553*5aaf853bSArmin Le Grand if(bLineCapRound && bFirst) 554*5aaf853bSArmin Le Grand { 555*5aaf853bSArmin Le Grand // LineCapRound used 556*5aaf853bSArmin Le Grand aSequence = getLineCapRoundSegments(nSegments, aMaterial); 557*5aaf853bSArmin Le Grand } 558*5aaf853bSArmin Le Grand else 559*5aaf853bSArmin Le Grand { 560*5aaf853bSArmin Le Grand // simple closing cap 561*5aaf853bSArmin Le Grand aSequence = getLineCapSegments(nSegments, aMaterial); 562*5aaf853bSArmin Le Grand } 563*5aaf853bSArmin Le Grand 564*5aaf853bSArmin Le Grand TransformPrimitive3D* pNewTransformedA = new TransformPrimitive3D(aCapTrans, aSequence); 565*5aaf853bSArmin Le Grand aResultVector.push_back(pNewTransformedA); 566*5aaf853bSArmin Le Grand } 567*5aaf853bSArmin Le Grand else 568*5aaf853bSArmin Le Grand { 569*5aaf853bSArmin Le Grand const basegfx::B3DVector aBack(aCurr - aLast); 570*5aaf853bSArmin Le Grand const double fCross(basegfx::cross(aBack, aForw).getLength()); 571*5aaf853bSArmin Le Grand 572*5aaf853bSArmin Le Grand if(!basegfx::fTools::equalZero(fCross)) 573*5aaf853bSArmin Le Grand { 574*5aaf853bSArmin Le Grand // line connect non-parallel, aBack, aForw, use getLineJoin() 575*5aaf853bSArmin Le Grand const double fAngle(acos(aBack.scalar(aForw) / (fForwLen * aBack.getLength()))); // 0.0 .. F_PI2 576*5aaf853bSArmin Le Grand Primitive3DSequence aNewList( 577*5aaf853bSArmin Le Grand getLineJoinSegments( 578*5aaf853bSArmin Le Grand nSegments, 579*5aaf853bSArmin Le Grand aMaterial, 580*5aaf853bSArmin Le Grand fAngle, 581*5aaf853bSArmin Le Grand getDegreeStepWidth(), 582*5aaf853bSArmin Le Grand getMiterMinimumAngle(), 583*5aaf853bSArmin Le Grand getLineJoin())); 584*5aaf853bSArmin Le Grand 585*5aaf853bSArmin Le Grand // calculate transformation. First, get angle in YZ between nForw projected on (1, 0, 0) and nBack 586*5aaf853bSArmin Le Grand basegfx::B3DHomMatrix aInvRotVector(aRotVector); 587*5aaf853bSArmin Le Grand aInvRotVector.invert(); 588*5aaf853bSArmin Le Grand basegfx::B3DVector aTransBack(aInvRotVector * aBack); 589*5aaf853bSArmin Le Grand const double fRotInYZ(atan2(aTransBack.getY(), aTransBack.getZ())); 590*5aaf853bSArmin Le Grand 591*5aaf853bSArmin Le Grand // create trans by rotating unit sphere with angle 90 degrees around Y, then 180-fRot in X. 592*5aaf853bSArmin Le Grand // Also apply usual scaling and translation 593*5aaf853bSArmin Le Grand basegfx::B3DHomMatrix aSphereTrans; 594*5aaf853bSArmin Le Grand aSphereTrans.rotate(0.0, F_PI2, 0.0); 595*5aaf853bSArmin Le Grand aSphereTrans.rotate(F_PI - fRotInYZ, 0.0, 0.0); 596*5aaf853bSArmin Le Grand aSphereTrans *= aRotVector; 597*5aaf853bSArmin Le Grand aSphereTrans.scale(getRadius(), getRadius(), getRadius()); 598*5aaf853bSArmin Le Grand aSphereTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ()); 599*5aaf853bSArmin Le Grand 600*5aaf853bSArmin Le Grand // line start edge, build transformed primitiveVector3D 601*5aaf853bSArmin Le Grand aResultVector.push_back( 602*5aaf853bSArmin Le Grand new TransformPrimitive3D( 603*5aaf853bSArmin Le Grand aSphereTrans, 604*5aaf853bSArmin Le Grand aNewList)); 605*5aaf853bSArmin Le Grand } 606*5aaf853bSArmin Le Grand } 607*5aaf853bSArmin Le Grand 608*5aaf853bSArmin Le Grand // create line segments, build transformed primitiveVector3D 609*5aaf853bSArmin Le Grand aResultVector.push_back( 610*5aaf853bSArmin Le Grand new TransformPrimitive3D( 611*5aaf853bSArmin Le Grand aTubeTrans, 612*5aaf853bSArmin Le Grand getLineTubeSegments(nSegments, aMaterial))); 613*5aaf853bSArmin Le Grand 614*5aaf853bSArmin Le Grand if(bNoLineJoin || (!bClosed && bLast)) 615*5aaf853bSArmin Le Grand { 616*5aaf853bSArmin Le Grand // line end edge 617*5aaf853bSArmin Le Grand basegfx::B3DHomMatrix aBackCapTrans; 618*5aaf853bSArmin Le Grand 619*5aaf853bSArmin Le Grand // Mirror (line end) and radius scale 620*5aaf853bSArmin Le Grand aBackCapTrans.rotate(0.0, F_PI, 0.0); 621*5aaf853bSArmin Le Grand aBackCapTrans.scale(getRadius(), getRadius(), getRadius()); 622*5aaf853bSArmin Le Grand 623*5aaf853bSArmin Le Grand if(bLineCapSquare && bLast) 624*5aaf853bSArmin Le Grand { 625*5aaf853bSArmin Le Grand // correct position when square and prolonged 626*5aaf853bSArmin Le Grand aBackCapTrans.translate(fForwLen + getRadius(), 0.0, 0.0); 627*5aaf853bSArmin Le Grand } 628*5aaf853bSArmin Le Grand else 629*5aaf853bSArmin Le Grand { 630*5aaf853bSArmin Le Grand // standard position 631*5aaf853bSArmin Le Grand aBackCapTrans.translate(fForwLen, 0.0, 0.0); 632*5aaf853bSArmin Le Grand } 633*5aaf853bSArmin Le Grand 634*5aaf853bSArmin Le Grand // rotate and translate to destination 635*5aaf853bSArmin Le Grand aBackCapTrans *= aRotVector; 636*5aaf853bSArmin Le Grand aBackCapTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ()); 637*5aaf853bSArmin Le Grand 638*5aaf853bSArmin Le Grand // get primitiveVector3D 639*5aaf853bSArmin Le Grand Primitive3DSequence aSequence; 640*5aaf853bSArmin Le Grand 641*5aaf853bSArmin Le Grand if(bLineCapRound && bLast) 642*5aaf853bSArmin Le Grand { 643*5aaf853bSArmin Le Grand // LineCapRound used 644*5aaf853bSArmin Le Grand aSequence = getLineCapRoundSegments(nSegments, aMaterial); 645*5aaf853bSArmin Le Grand } 646*5aaf853bSArmin Le Grand else 647*5aaf853bSArmin Le Grand { 648*5aaf853bSArmin Le Grand // simple closing cap 649*5aaf853bSArmin Le Grand aSequence = getLineCapSegments(nSegments, aMaterial); 650*5aaf853bSArmin Le Grand } 651*5aaf853bSArmin Le Grand 652*5aaf853bSArmin Le Grand aResultVector.push_back( 653*5aaf853bSArmin Le Grand new TransformPrimitive3D( 654*5aaf853bSArmin Le Grand aBackCapTrans, 655*5aaf853bSArmin Le Grand aSequence)); 656*5aaf853bSArmin Le Grand } 657*5aaf853bSArmin Le Grand } 658cdf0e10cSrcweir 659cdf0e10cSrcweir // prepare next loop step 660cdf0e10cSrcweir aLast = aCurr; 661cdf0e10cSrcweir aCurr = aNext; 662cdf0e10cSrcweir } 663cdf0e10cSrcweir } 664cdf0e10cSrcweir else 665cdf0e10cSrcweir { 666cdf0e10cSrcweir // create hairline 667cdf0e10cSrcweir PolygonHairlinePrimitive3D* pNew = new PolygonHairlinePrimitive3D(getB3DPolygon(), getBColor()); 668cdf0e10cSrcweir aResultVector.push_back(pNew); 669cdf0e10cSrcweir } 670cdf0e10cSrcweir } 671cdf0e10cSrcweir 672cdf0e10cSrcweir // prepare return value 673cdf0e10cSrcweir Primitive3DSequence aRetval(aResultVector.size()); 674cdf0e10cSrcweir 675cdf0e10cSrcweir for(sal_uInt32 a(0L); a < aResultVector.size(); a++) 676cdf0e10cSrcweir { 677cdf0e10cSrcweir aRetval[a] = Primitive3DReference(aResultVector[a]); 678cdf0e10cSrcweir } 679cdf0e10cSrcweir 680cdf0e10cSrcweir return aRetval; 681cdf0e10cSrcweir } 682cdf0e10cSrcweir PolygonTubePrimitive3D(const basegfx::B3DPolygon & rPolygon,const basegfx::BColor & rBColor,double fRadius,basegfx::B2DLineJoin aLineJoin,com::sun::star::drawing::LineCap aLineCap,double fDegreeStepWidth,double fMiterMinimumAngle)683cdf0e10cSrcweir PolygonTubePrimitive3D::PolygonTubePrimitive3D( 684cdf0e10cSrcweir const basegfx::B3DPolygon& rPolygon, 685cdf0e10cSrcweir const basegfx::BColor& rBColor, 686cdf0e10cSrcweir double fRadius, basegfx::B2DLineJoin aLineJoin, 687*5aaf853bSArmin Le Grand com::sun::star::drawing::LineCap aLineCap, 688cdf0e10cSrcweir double fDegreeStepWidth, 689cdf0e10cSrcweir double fMiterMinimumAngle) 690cdf0e10cSrcweir : PolygonHairlinePrimitive3D(rPolygon, rBColor), 691cdf0e10cSrcweir maLast3DDecomposition(), 692cdf0e10cSrcweir mfRadius(fRadius), 693cdf0e10cSrcweir mfDegreeStepWidth(fDegreeStepWidth), 694cdf0e10cSrcweir mfMiterMinimumAngle(fMiterMinimumAngle), 695*5aaf853bSArmin Le Grand maLineJoin(aLineJoin), 696*5aaf853bSArmin Le Grand maLineCap(aLineCap) 697cdf0e10cSrcweir { 698cdf0e10cSrcweir } 699cdf0e10cSrcweir operator ==(const BasePrimitive3D & rPrimitive) const700cdf0e10cSrcweir bool PolygonTubePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const 701cdf0e10cSrcweir { 702cdf0e10cSrcweir if(PolygonHairlinePrimitive3D::operator==(rPrimitive)) 703cdf0e10cSrcweir { 704cdf0e10cSrcweir const PolygonTubePrimitive3D& rCompare = (PolygonTubePrimitive3D&)rPrimitive; 705cdf0e10cSrcweir 706cdf0e10cSrcweir return (getRadius() == rCompare.getRadius() 707cdf0e10cSrcweir && getDegreeStepWidth() == rCompare.getDegreeStepWidth() 708cdf0e10cSrcweir && getMiterMinimumAngle() == rCompare.getMiterMinimumAngle() 709*5aaf853bSArmin Le Grand && getLineJoin() == rCompare.getLineJoin() 710*5aaf853bSArmin Le Grand && getLineCap() == rCompare.getLineCap()); 711cdf0e10cSrcweir } 712cdf0e10cSrcweir 713cdf0e10cSrcweir return false; 714cdf0e10cSrcweir } 715cdf0e10cSrcweir get3DDecomposition(const geometry::ViewInformation3D & rViewInformation) const716cdf0e10cSrcweir Primitive3DSequence PolygonTubePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const 717cdf0e10cSrcweir { 718cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex ); 719cdf0e10cSrcweir 720cdf0e10cSrcweir if(!getLast3DDecomposition().hasElements()) 721cdf0e10cSrcweir { 722cdf0e10cSrcweir const Primitive3DSequence aNewSequence(impCreate3DDecomposition(rViewInformation)); 723cdf0e10cSrcweir const_cast< PolygonTubePrimitive3D* >(this)->setLast3DDecomposition(aNewSequence); 724cdf0e10cSrcweir } 725cdf0e10cSrcweir 726cdf0e10cSrcweir return getLast3DDecomposition(); 727cdf0e10cSrcweir } 728cdf0e10cSrcweir 729cdf0e10cSrcweir // provide unique ID 730cdf0e10cSrcweir ImplPrimitrive3DIDBlock(PolygonTubePrimitive3D, PRIMITIVE3D_ID_POLYGONTUBEPRIMITIVE3D) 731cdf0e10cSrcweir 732cdf0e10cSrcweir } // end of namespace primitive3d 733cdf0e10cSrcweir } // end of namespace drawinglayer 734cdf0e10cSrcweir 735cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 736cdf0e10cSrcweir // eof 737