1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include <drawinglayer/primitive3d/sdrextrudeprimitive3d.hxx> 32*cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx> 33*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx> 34*cdf0e10cSrcweir #include <basegfx/polygon/b3dpolypolygontools.hxx> 35*cdf0e10cSrcweir #include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx> 36*cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx> 37*cdf0e10cSrcweir #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx> 38*cdf0e10cSrcweir #include <drawinglayer/geometry/viewinformation3d.hxx> 39*cdf0e10cSrcweir #include <drawinglayer/attribute/sdrfillattribute.hxx> 40*cdf0e10cSrcweir #include <drawinglayer/attribute/sdrlineattribute.hxx> 41*cdf0e10cSrcweir #include <drawinglayer/attribute/sdrshadowattribute.hxx> 42*cdf0e10cSrcweir 43*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 44*cdf0e10cSrcweir 45*cdf0e10cSrcweir using namespace com::sun::star; 46*cdf0e10cSrcweir 47*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 48*cdf0e10cSrcweir 49*cdf0e10cSrcweir namespace drawinglayer 50*cdf0e10cSrcweir { 51*cdf0e10cSrcweir namespace primitive3d 52*cdf0e10cSrcweir { 53*cdf0e10cSrcweir Primitive3DSequence SdrExtrudePrimitive3D::create3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const 54*cdf0e10cSrcweir { 55*cdf0e10cSrcweir Primitive3DSequence aRetval; 56*cdf0e10cSrcweir 57*cdf0e10cSrcweir // get slices 58*cdf0e10cSrcweir const Slice3DVector& rSliceVector = getSlices(); 59*cdf0e10cSrcweir 60*cdf0e10cSrcweir if(rSliceVector.size()) 61*cdf0e10cSrcweir { 62*cdf0e10cSrcweir sal_uInt32 a; 63*cdf0e10cSrcweir 64*cdf0e10cSrcweir // decide what to create 65*cdf0e10cSrcweir const ::com::sun::star::drawing::NormalsKind eNormalsKind(getSdr3DObjectAttribute().getNormalsKind()); 66*cdf0e10cSrcweir const bool bCreateNormals(::com::sun::star::drawing::NormalsKind_SPECIFIC == eNormalsKind); 67*cdf0e10cSrcweir const bool bCreateTextureCoordiantesX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX()); 68*cdf0e10cSrcweir const bool bCreateTextureCoordiantesY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY()); 69*cdf0e10cSrcweir double fRelativeTextureWidth(1.0); 70*cdf0e10cSrcweir basegfx::B2DHomMatrix aTexTransform; 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir if(!getSdrLFSAttribute().getFill().isDefault() && (bCreateTextureCoordiantesX || bCreateTextureCoordiantesY)) 73*cdf0e10cSrcweir { 74*cdf0e10cSrcweir const basegfx::B2DPolygon aFirstPolygon(maCorrectedPolyPolygon.getB2DPolygon(0L)); 75*cdf0e10cSrcweir const double fFrontLength(basegfx::tools::getLength(aFirstPolygon)); 76*cdf0e10cSrcweir const double fFrontArea(basegfx::tools::getArea(aFirstPolygon)); 77*cdf0e10cSrcweir const double fSqrtFrontArea(sqrt(fFrontArea)); 78*cdf0e10cSrcweir fRelativeTextureWidth = basegfx::fTools::equalZero(fSqrtFrontArea) ? 1.0 : fFrontLength / fSqrtFrontArea; 79*cdf0e10cSrcweir fRelativeTextureWidth = (double)((sal_uInt32)(fRelativeTextureWidth - 0.5)); 80*cdf0e10cSrcweir 81*cdf0e10cSrcweir if(fRelativeTextureWidth < 1.0) 82*cdf0e10cSrcweir { 83*cdf0e10cSrcweir fRelativeTextureWidth = 1.0; 84*cdf0e10cSrcweir } 85*cdf0e10cSrcweir 86*cdf0e10cSrcweir aTexTransform.translate(-0.5, -0.5); 87*cdf0e10cSrcweir aTexTransform.scale(-1.0, -1.0); 88*cdf0e10cSrcweir aTexTransform.translate(0.5, 0.5); 89*cdf0e10cSrcweir aTexTransform.scale(fRelativeTextureWidth, 1.0); 90*cdf0e10cSrcweir } 91*cdf0e10cSrcweir 92*cdf0e10cSrcweir // create geometry 93*cdf0e10cSrcweir ::std::vector< basegfx::B3DPolyPolygon > aFill; 94*cdf0e10cSrcweir extractPlanesFromSlice(aFill, rSliceVector, 95*cdf0e10cSrcweir bCreateNormals, getSmoothHorizontalNormals(), getSmoothNormals(), getSmoothLids(), false, 96*cdf0e10cSrcweir 0.5, 0.6, bCreateTextureCoordiantesX || bCreateTextureCoordiantesY, aTexTransform); 97*cdf0e10cSrcweir 98*cdf0e10cSrcweir // get full range 99*cdf0e10cSrcweir const basegfx::B3DRange aRange(getRangeFrom3DGeometry(aFill)); 100*cdf0e10cSrcweir 101*cdf0e10cSrcweir // normal creation 102*cdf0e10cSrcweir if(!getSdrLFSAttribute().getFill().isDefault()) 103*cdf0e10cSrcweir { 104*cdf0e10cSrcweir if(::com::sun::star::drawing::NormalsKind_SPHERE == eNormalsKind) 105*cdf0e10cSrcweir { 106*cdf0e10cSrcweir applyNormalsKindSphereTo3DGeometry(aFill, aRange); 107*cdf0e10cSrcweir } 108*cdf0e10cSrcweir else if(::com::sun::star::drawing::NormalsKind_FLAT == eNormalsKind) 109*cdf0e10cSrcweir { 110*cdf0e10cSrcweir applyNormalsKindFlatTo3DGeometry(aFill); 111*cdf0e10cSrcweir } 112*cdf0e10cSrcweir 113*cdf0e10cSrcweir if(getSdr3DObjectAttribute().getNormalsInvert()) 114*cdf0e10cSrcweir { 115*cdf0e10cSrcweir applyNormalsInvertTo3DGeometry(aFill); 116*cdf0e10cSrcweir } 117*cdf0e10cSrcweir } 118*cdf0e10cSrcweir 119*cdf0e10cSrcweir // texture coordinates 120*cdf0e10cSrcweir if(!getSdrLFSAttribute().getFill().isDefault()) 121*cdf0e10cSrcweir { 122*cdf0e10cSrcweir applyTextureTo3DGeometry( 123*cdf0e10cSrcweir getSdr3DObjectAttribute().getTextureProjectionX(), 124*cdf0e10cSrcweir getSdr3DObjectAttribute().getTextureProjectionY(), 125*cdf0e10cSrcweir aFill, 126*cdf0e10cSrcweir aRange, 127*cdf0e10cSrcweir getTextureSize()); 128*cdf0e10cSrcweir } 129*cdf0e10cSrcweir 130*cdf0e10cSrcweir if(!getSdrLFSAttribute().getFill().isDefault()) 131*cdf0e10cSrcweir { 132*cdf0e10cSrcweir // add fill 133*cdf0e10cSrcweir aRetval = create3DPolyPolygonFillPrimitives( 134*cdf0e10cSrcweir aFill, 135*cdf0e10cSrcweir getTransform(), 136*cdf0e10cSrcweir getTextureSize(), 137*cdf0e10cSrcweir getSdr3DObjectAttribute(), 138*cdf0e10cSrcweir getSdrLFSAttribute().getFill(), 139*cdf0e10cSrcweir getSdrLFSAttribute().getFillFloatTransGradient()); 140*cdf0e10cSrcweir } 141*cdf0e10cSrcweir else 142*cdf0e10cSrcweir { 143*cdf0e10cSrcweir // create simplified 3d hit test geometry 144*cdf0e10cSrcweir aRetval = createHiddenGeometryPrimitives3D( 145*cdf0e10cSrcweir aFill, 146*cdf0e10cSrcweir getTransform(), 147*cdf0e10cSrcweir getTextureSize(), 148*cdf0e10cSrcweir getSdr3DObjectAttribute()); 149*cdf0e10cSrcweir } 150*cdf0e10cSrcweir 151*cdf0e10cSrcweir // add line 152*cdf0e10cSrcweir if(!getSdrLFSAttribute().getLine().isDefault()) 153*cdf0e10cSrcweir { 154*cdf0e10cSrcweir if(getSdr3DObjectAttribute().getReducedLineGeometry()) 155*cdf0e10cSrcweir { 156*cdf0e10cSrcweir // create geometric outlines with reduced line geometry for chart. 157*cdf0e10cSrcweir const basegfx::B3DPolyPolygon aVerLine(extractVerticalLinesFromSlice(rSliceVector)); 158*cdf0e10cSrcweir const sal_uInt32 nCount(aVerLine.count()); 159*cdf0e10cSrcweir basegfx::B3DPolyPolygon aReducedLoops; 160*cdf0e10cSrcweir basegfx::B3DPolyPolygon aNewLineGeometry; 161*cdf0e10cSrcweir 162*cdf0e10cSrcweir // sort out doubles (front and back planes when no edge rounding is done). Since 163*cdf0e10cSrcweir // this is a line geometry merged from PolyPolygons, loop over all Polygons 164*cdf0e10cSrcweir for(a = 0; a < nCount; a++) 165*cdf0e10cSrcweir { 166*cdf0e10cSrcweir const sal_uInt32 nReducedCount(aReducedLoops.count()); 167*cdf0e10cSrcweir const basegfx::B3DPolygon aCandidate(aVerLine.getB3DPolygon(a)); 168*cdf0e10cSrcweir bool bAdd(true); 169*cdf0e10cSrcweir 170*cdf0e10cSrcweir if(nReducedCount) 171*cdf0e10cSrcweir { 172*cdf0e10cSrcweir for(sal_uInt32 b(0); bAdd && b < nReducedCount; b++) 173*cdf0e10cSrcweir { 174*cdf0e10cSrcweir if(aCandidate == aReducedLoops.getB3DPolygon(b)) 175*cdf0e10cSrcweir { 176*cdf0e10cSrcweir bAdd = false; 177*cdf0e10cSrcweir } 178*cdf0e10cSrcweir } 179*cdf0e10cSrcweir } 180*cdf0e10cSrcweir 181*cdf0e10cSrcweir if(bAdd) 182*cdf0e10cSrcweir { 183*cdf0e10cSrcweir aReducedLoops.append(aCandidate); 184*cdf0e10cSrcweir } 185*cdf0e10cSrcweir } 186*cdf0e10cSrcweir 187*cdf0e10cSrcweir // from here work with reduced loops and reduced count without changing them 188*cdf0e10cSrcweir const sal_uInt32 nReducedCount(aReducedLoops.count()); 189*cdf0e10cSrcweir 190*cdf0e10cSrcweir if(nReducedCount > 1) 191*cdf0e10cSrcweir { 192*cdf0e10cSrcweir for(sal_uInt32 b(1); b < nReducedCount; b++) 193*cdf0e10cSrcweir { 194*cdf0e10cSrcweir // get loop pair 195*cdf0e10cSrcweir const basegfx::B3DPolygon aCandA(aReducedLoops.getB3DPolygon(b - 1)); 196*cdf0e10cSrcweir const basegfx::B3DPolygon aCandB(aReducedLoops.getB3DPolygon(b)); 197*cdf0e10cSrcweir 198*cdf0e10cSrcweir // for each loop pair create the connection edges 199*cdf0e10cSrcweir createReducedOutlines( 200*cdf0e10cSrcweir rViewInformation, 201*cdf0e10cSrcweir getTransform(), 202*cdf0e10cSrcweir aCandA, 203*cdf0e10cSrcweir aCandB, 204*cdf0e10cSrcweir aNewLineGeometry); 205*cdf0e10cSrcweir } 206*cdf0e10cSrcweir } 207*cdf0e10cSrcweir 208*cdf0e10cSrcweir // add reduced loops themselves 209*cdf0e10cSrcweir aNewLineGeometry.append(aReducedLoops); 210*cdf0e10cSrcweir 211*cdf0e10cSrcweir // to create vertical edges at non-C1/C2 steady loops, use maCorrectedPolyPolygon 212*cdf0e10cSrcweir // directly since the 3D Polygons do not suport this. 213*cdf0e10cSrcweir // 214*cdf0e10cSrcweir // Unfortunately there is no bezier polygon provided by the chart module; one reason is 215*cdf0e10cSrcweir // that the API for extrude wants a 3D polygon geometry (for historical reasons, i guess) 216*cdf0e10cSrcweir // and those have no beziers. Another reason is that he chart module uses self-created 217*cdf0e10cSrcweir // stuff to create the 2D geometry (in ShapeFactory::createPieSegment), but this geometry 218*cdf0e10cSrcweir // does not contain bezier infos, either. The only way which is possible for now is to 'detect' 219*cdf0e10cSrcweir // candidates for vertical edges of pie segments by looking for the angles in the polygon. 220*cdf0e10cSrcweir // 221*cdf0e10cSrcweir // This is all not very well designed ATM. Ideally, the ReducedLineGeometry is responsible 222*cdf0e10cSrcweir // for creating the outer geometry edges (createReducedOutlines), but for special edges 223*cdf0e10cSrcweir // like the vertical ones for pie center and both start/end, the incarnation with the 224*cdf0e10cSrcweir // knowledge about that it needs to create those and IS a pie segment -> in this case, 225*cdf0e10cSrcweir // the chart itself. 226*cdf0e10cSrcweir const sal_uInt32 nPolyCount(maCorrectedPolyPolygon.count()); 227*cdf0e10cSrcweir 228*cdf0e10cSrcweir for(sal_uInt32 c(0); c < nPolyCount; c++) 229*cdf0e10cSrcweir { 230*cdf0e10cSrcweir const basegfx::B2DPolygon aCandidate(maCorrectedPolyPolygon.getB2DPolygon(c)); 231*cdf0e10cSrcweir const sal_uInt32 nPointCount(aCandidate.count()); 232*cdf0e10cSrcweir 233*cdf0e10cSrcweir if(nPointCount > 2) 234*cdf0e10cSrcweir { 235*cdf0e10cSrcweir sal_uInt32 nIndexA(nPointCount); 236*cdf0e10cSrcweir sal_uInt32 nIndexB(nPointCount); 237*cdf0e10cSrcweir sal_uInt32 nIndexC(nPointCount); 238*cdf0e10cSrcweir 239*cdf0e10cSrcweir for(sal_uInt32 d(0); d < nPointCount; d++) 240*cdf0e10cSrcweir { 241*cdf0e10cSrcweir const sal_uInt32 nPrevInd((d + nPointCount - 1) % nPointCount); 242*cdf0e10cSrcweir const sal_uInt32 nNextInd((d + 1) % nPointCount); 243*cdf0e10cSrcweir const basegfx::B2DPoint aPoint(aCandidate.getB2DPoint(d)); 244*cdf0e10cSrcweir const basegfx::B2DVector aPrev(aCandidate.getB2DPoint(nPrevInd) - aPoint); 245*cdf0e10cSrcweir const basegfx::B2DVector aNext(aCandidate.getB2DPoint(nNextInd) - aPoint); 246*cdf0e10cSrcweir const double fAngle(aPrev.angle(aNext)); 247*cdf0e10cSrcweir 248*cdf0e10cSrcweir // take each angle which deviates more than 10% from going straight as 249*cdf0e10cSrcweir // special edge. This will detect the two outer edges of pie segments, 250*cdf0e10cSrcweir // but not always the center one (think about a near 180 degree pie) 251*cdf0e10cSrcweir if(F_PI - fabs(fAngle) > F_PI * 0.1) 252*cdf0e10cSrcweir { 253*cdf0e10cSrcweir if(nPointCount == nIndexA) 254*cdf0e10cSrcweir { 255*cdf0e10cSrcweir nIndexA = d; 256*cdf0e10cSrcweir } 257*cdf0e10cSrcweir else if(nPointCount == nIndexB) 258*cdf0e10cSrcweir { 259*cdf0e10cSrcweir nIndexB = d; 260*cdf0e10cSrcweir } 261*cdf0e10cSrcweir else if(nPointCount == nIndexC) 262*cdf0e10cSrcweir { 263*cdf0e10cSrcweir nIndexC = d; 264*cdf0e10cSrcweir d = nPointCount; 265*cdf0e10cSrcweir } 266*cdf0e10cSrcweir } 267*cdf0e10cSrcweir } 268*cdf0e10cSrcweir 269*cdf0e10cSrcweir const bool bIndexAUsed(nIndexA != nPointCount); 270*cdf0e10cSrcweir const bool bIndexBUsed(nIndexB != nPointCount); 271*cdf0e10cSrcweir bool bIndexCUsed(nIndexC != nPointCount); 272*cdf0e10cSrcweir 273*cdf0e10cSrcweir if(bIndexCUsed) 274*cdf0e10cSrcweir { 275*cdf0e10cSrcweir // already three special edges found, so the center one was already detected 276*cdf0e10cSrcweir // and does not need to be searched 277*cdf0e10cSrcweir } 278*cdf0e10cSrcweir else if(bIndexAUsed && bIndexBUsed) 279*cdf0e10cSrcweir { 280*cdf0e10cSrcweir // outer edges detected (they are approx. 90 degrees), but center one not. 281*cdf0e10cSrcweir // Look with the knowledge that it's in-between the two found ones 282*cdf0e10cSrcweir if(((nIndexA + 2) % nPointCount) == nIndexB) 283*cdf0e10cSrcweir { 284*cdf0e10cSrcweir nIndexC = (nIndexA + 1) % nPointCount; 285*cdf0e10cSrcweir } 286*cdf0e10cSrcweir else if(((nIndexA + nPointCount - 2) % nPointCount) == nIndexB) 287*cdf0e10cSrcweir { 288*cdf0e10cSrcweir nIndexC = (nIndexA + nPointCount - 1) % nPointCount; 289*cdf0e10cSrcweir } 290*cdf0e10cSrcweir 291*cdf0e10cSrcweir bIndexCUsed = (nIndexC != nPointCount); 292*cdf0e10cSrcweir } 293*cdf0e10cSrcweir 294*cdf0e10cSrcweir if(bIndexAUsed) 295*cdf0e10cSrcweir { 296*cdf0e10cSrcweir const basegfx::B2DPoint aPoint(aCandidate.getB2DPoint(nIndexA)); 297*cdf0e10cSrcweir const basegfx::B3DPoint aStart(aPoint.getX(), aPoint.getY(), 0.0); 298*cdf0e10cSrcweir const basegfx::B3DPoint aEnd(aPoint.getX(), aPoint.getY(), getDepth()); 299*cdf0e10cSrcweir basegfx::B3DPolygon aToBeAdded; 300*cdf0e10cSrcweir 301*cdf0e10cSrcweir aToBeAdded.append(aStart); 302*cdf0e10cSrcweir aToBeAdded.append(aEnd); 303*cdf0e10cSrcweir aNewLineGeometry.append(aToBeAdded); 304*cdf0e10cSrcweir } 305*cdf0e10cSrcweir 306*cdf0e10cSrcweir if(bIndexBUsed) 307*cdf0e10cSrcweir { 308*cdf0e10cSrcweir const basegfx::B2DPoint aPoint(aCandidate.getB2DPoint(nIndexB)); 309*cdf0e10cSrcweir const basegfx::B3DPoint aStart(aPoint.getX(), aPoint.getY(), 0.0); 310*cdf0e10cSrcweir const basegfx::B3DPoint aEnd(aPoint.getX(), aPoint.getY(), getDepth()); 311*cdf0e10cSrcweir basegfx::B3DPolygon aToBeAdded; 312*cdf0e10cSrcweir 313*cdf0e10cSrcweir aToBeAdded.append(aStart); 314*cdf0e10cSrcweir aToBeAdded.append(aEnd); 315*cdf0e10cSrcweir aNewLineGeometry.append(aToBeAdded); 316*cdf0e10cSrcweir } 317*cdf0e10cSrcweir 318*cdf0e10cSrcweir if(bIndexCUsed) 319*cdf0e10cSrcweir { 320*cdf0e10cSrcweir const basegfx::B2DPoint aPoint(aCandidate.getB2DPoint(nIndexC)); 321*cdf0e10cSrcweir const basegfx::B3DPoint aStart(aPoint.getX(), aPoint.getY(), 0.0); 322*cdf0e10cSrcweir const basegfx::B3DPoint aEnd(aPoint.getX(), aPoint.getY(), getDepth()); 323*cdf0e10cSrcweir basegfx::B3DPolygon aToBeAdded; 324*cdf0e10cSrcweir 325*cdf0e10cSrcweir aToBeAdded.append(aStart); 326*cdf0e10cSrcweir aToBeAdded.append(aEnd); 327*cdf0e10cSrcweir aNewLineGeometry.append(aToBeAdded); 328*cdf0e10cSrcweir } 329*cdf0e10cSrcweir } 330*cdf0e10cSrcweir } 331*cdf0e10cSrcweir 332*cdf0e10cSrcweir // append loops themselves 333*cdf0e10cSrcweir aNewLineGeometry.append(aReducedLoops); 334*cdf0e10cSrcweir 335*cdf0e10cSrcweir if(aNewLineGeometry.count()) 336*cdf0e10cSrcweir { 337*cdf0e10cSrcweir const Primitive3DSequence aLines(create3DPolyPolygonLinePrimitives( 338*cdf0e10cSrcweir aNewLineGeometry, getTransform(), getSdrLFSAttribute().getLine())); 339*cdf0e10cSrcweir appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aLines); 340*cdf0e10cSrcweir } 341*cdf0e10cSrcweir } 342*cdf0e10cSrcweir else 343*cdf0e10cSrcweir { 344*cdf0e10cSrcweir // extract line geometry from slices 345*cdf0e10cSrcweir const basegfx::B3DPolyPolygon aHorLine(extractHorizontalLinesFromSlice(rSliceVector, false)); 346*cdf0e10cSrcweir const basegfx::B3DPolyPolygon aVerLine(extractVerticalLinesFromSlice(rSliceVector)); 347*cdf0e10cSrcweir 348*cdf0e10cSrcweir // add horizontal lines 349*cdf0e10cSrcweir const Primitive3DSequence aHorLines(create3DPolyPolygonLinePrimitives( 350*cdf0e10cSrcweir aHorLine, getTransform(), getSdrLFSAttribute().getLine())); 351*cdf0e10cSrcweir appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aHorLines); 352*cdf0e10cSrcweir 353*cdf0e10cSrcweir // add vertical lines 354*cdf0e10cSrcweir const Primitive3DSequence aVerLines(create3DPolyPolygonLinePrimitives( 355*cdf0e10cSrcweir aVerLine, getTransform(), getSdrLFSAttribute().getLine())); 356*cdf0e10cSrcweir appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aVerLines); 357*cdf0e10cSrcweir } 358*cdf0e10cSrcweir } 359*cdf0e10cSrcweir 360*cdf0e10cSrcweir // add shadow 361*cdf0e10cSrcweir if(!getSdrLFSAttribute().getShadow().isDefault() && aRetval.hasElements()) 362*cdf0e10cSrcweir { 363*cdf0e10cSrcweir const Primitive3DSequence aShadow(createShadowPrimitive3D( 364*cdf0e10cSrcweir aRetval, getSdrLFSAttribute().getShadow(), getSdr3DObjectAttribute().getShadow3D())); 365*cdf0e10cSrcweir appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aShadow); 366*cdf0e10cSrcweir } 367*cdf0e10cSrcweir } 368*cdf0e10cSrcweir 369*cdf0e10cSrcweir return aRetval; 370*cdf0e10cSrcweir } 371*cdf0e10cSrcweir 372*cdf0e10cSrcweir void SdrExtrudePrimitive3D::impCreateSlices() 373*cdf0e10cSrcweir { 374*cdf0e10cSrcweir // prepare the polygon. No double points, correct orientations and a correct 375*cdf0e10cSrcweir // outmost polygon are needed 376*cdf0e10cSrcweir maCorrectedPolyPolygon = getPolyPolygon(); 377*cdf0e10cSrcweir maCorrectedPolyPolygon.removeDoublePoints(); 378*cdf0e10cSrcweir maCorrectedPolyPolygon = basegfx::tools::correctOrientations(maCorrectedPolyPolygon); 379*cdf0e10cSrcweir maCorrectedPolyPolygon = basegfx::tools::correctOutmostPolygon(maCorrectedPolyPolygon); 380*cdf0e10cSrcweir 381*cdf0e10cSrcweir // prepare slices as geometry 382*cdf0e10cSrcweir createExtrudeSlices(maSlices, maCorrectedPolyPolygon, getBackScale(), getDiagonal(), getDepth(), getCharacterMode(), getCloseFront(), getCloseBack()); 383*cdf0e10cSrcweir } 384*cdf0e10cSrcweir 385*cdf0e10cSrcweir const Slice3DVector& SdrExtrudePrimitive3D::getSlices() const 386*cdf0e10cSrcweir { 387*cdf0e10cSrcweir // This can be made dependent of getSdrLFSAttribute().getFill() and getSdrLFSAttribute().getLine() 388*cdf0e10cSrcweir // again when no longer geometry is needed for non-visible 3D objects as it is now for chart 389*cdf0e10cSrcweir if(getPolyPolygon().count() && !maSlices.size()) 390*cdf0e10cSrcweir { 391*cdf0e10cSrcweir ::osl::Mutex m_mutex; 392*cdf0e10cSrcweir const_cast< SdrExtrudePrimitive3D& >(*this).impCreateSlices(); 393*cdf0e10cSrcweir } 394*cdf0e10cSrcweir 395*cdf0e10cSrcweir return maSlices; 396*cdf0e10cSrcweir } 397*cdf0e10cSrcweir 398*cdf0e10cSrcweir SdrExtrudePrimitive3D::SdrExtrudePrimitive3D( 399*cdf0e10cSrcweir const basegfx::B3DHomMatrix& rTransform, 400*cdf0e10cSrcweir const basegfx::B2DVector& rTextureSize, 401*cdf0e10cSrcweir const attribute::SdrLineFillShadowAttribute3D& rSdrLFSAttribute, 402*cdf0e10cSrcweir const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute, 403*cdf0e10cSrcweir const basegfx::B2DPolyPolygon& rPolyPolygon, 404*cdf0e10cSrcweir double fDepth, 405*cdf0e10cSrcweir double fDiagonal, 406*cdf0e10cSrcweir double fBackScale, 407*cdf0e10cSrcweir bool bSmoothNormals, 408*cdf0e10cSrcweir bool bSmoothHorizontalNormals, 409*cdf0e10cSrcweir bool bSmoothLids, 410*cdf0e10cSrcweir bool bCharacterMode, 411*cdf0e10cSrcweir bool bCloseFront, 412*cdf0e10cSrcweir bool bCloseBack) 413*cdf0e10cSrcweir : SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute), 414*cdf0e10cSrcweir maCorrectedPolyPolygon(), 415*cdf0e10cSrcweir maSlices(), 416*cdf0e10cSrcweir maPolyPolygon(rPolyPolygon), 417*cdf0e10cSrcweir mfDepth(fDepth), 418*cdf0e10cSrcweir mfDiagonal(fDiagonal), 419*cdf0e10cSrcweir mfBackScale(fBackScale), 420*cdf0e10cSrcweir mpLastRLGViewInformation(0), 421*cdf0e10cSrcweir mbSmoothNormals(bSmoothNormals), 422*cdf0e10cSrcweir mbSmoothHorizontalNormals(bSmoothHorizontalNormals), 423*cdf0e10cSrcweir mbSmoothLids(bSmoothLids), 424*cdf0e10cSrcweir mbCharacterMode(bCharacterMode), 425*cdf0e10cSrcweir mbCloseFront(bCloseFront), 426*cdf0e10cSrcweir mbCloseBack(bCloseBack) 427*cdf0e10cSrcweir { 428*cdf0e10cSrcweir // make sure depth is positive 429*cdf0e10cSrcweir if(basegfx::fTools::lessOrEqual(getDepth(), 0.0)) 430*cdf0e10cSrcweir { 431*cdf0e10cSrcweir mfDepth = 0.0; 432*cdf0e10cSrcweir } 433*cdf0e10cSrcweir 434*cdf0e10cSrcweir // make sure the percentage value getDiagonal() is between 0.0 and 1.0 435*cdf0e10cSrcweir if(basegfx::fTools::lessOrEqual(getDiagonal(), 0.0)) 436*cdf0e10cSrcweir { 437*cdf0e10cSrcweir mfDiagonal = 0.0; 438*cdf0e10cSrcweir } 439*cdf0e10cSrcweir else if(basegfx::fTools::moreOrEqual(getDiagonal(), 1.0)) 440*cdf0e10cSrcweir { 441*cdf0e10cSrcweir mfDiagonal = 1.0; 442*cdf0e10cSrcweir } 443*cdf0e10cSrcweir 444*cdf0e10cSrcweir // no close front/back when polygon is not closed 445*cdf0e10cSrcweir if(getPolyPolygon().count() && !getPolyPolygon().getB2DPolygon(0L).isClosed()) 446*cdf0e10cSrcweir { 447*cdf0e10cSrcweir mbCloseFront = mbCloseBack = false; 448*cdf0e10cSrcweir } 449*cdf0e10cSrcweir 450*cdf0e10cSrcweir // no edge rounding when not closing 451*cdf0e10cSrcweir if(!getCloseFront() && !getCloseBack()) 452*cdf0e10cSrcweir { 453*cdf0e10cSrcweir mfDiagonal = 0.0; 454*cdf0e10cSrcweir } 455*cdf0e10cSrcweir } 456*cdf0e10cSrcweir 457*cdf0e10cSrcweir SdrExtrudePrimitive3D::~SdrExtrudePrimitive3D() 458*cdf0e10cSrcweir { 459*cdf0e10cSrcweir if(mpLastRLGViewInformation) 460*cdf0e10cSrcweir { 461*cdf0e10cSrcweir delete mpLastRLGViewInformation; 462*cdf0e10cSrcweir } 463*cdf0e10cSrcweir } 464*cdf0e10cSrcweir 465*cdf0e10cSrcweir bool SdrExtrudePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const 466*cdf0e10cSrcweir { 467*cdf0e10cSrcweir if(SdrPrimitive3D::operator==(rPrimitive)) 468*cdf0e10cSrcweir { 469*cdf0e10cSrcweir const SdrExtrudePrimitive3D& rCompare = static_cast< const SdrExtrudePrimitive3D& >(rPrimitive); 470*cdf0e10cSrcweir 471*cdf0e10cSrcweir return (getPolyPolygon() == rCompare.getPolyPolygon() 472*cdf0e10cSrcweir && getDepth() == rCompare.getDepth() 473*cdf0e10cSrcweir && getDiagonal() == rCompare.getDiagonal() 474*cdf0e10cSrcweir && getBackScale() == rCompare.getBackScale() 475*cdf0e10cSrcweir && getSmoothNormals() == rCompare.getSmoothNormals() 476*cdf0e10cSrcweir && getSmoothHorizontalNormals() == rCompare.getSmoothHorizontalNormals() 477*cdf0e10cSrcweir && getSmoothLids() == rCompare.getSmoothLids() 478*cdf0e10cSrcweir && getCharacterMode() == rCompare.getCharacterMode() 479*cdf0e10cSrcweir && getCloseFront() == rCompare.getCloseFront() 480*cdf0e10cSrcweir && getCloseBack() == rCompare.getCloseBack()); 481*cdf0e10cSrcweir } 482*cdf0e10cSrcweir 483*cdf0e10cSrcweir return false; 484*cdf0e10cSrcweir } 485*cdf0e10cSrcweir 486*cdf0e10cSrcweir basegfx::B3DRange SdrExtrudePrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const 487*cdf0e10cSrcweir { 488*cdf0e10cSrcweir // use defaut from sdrPrimitive3D which uses transformation expanded by line width/2 489*cdf0e10cSrcweir // The parent implementation which uses the ranges of the decomposition would be more 490*cdf0e10cSrcweir // corrcet, but for historical reasons it is necessary to do the old method: To get 491*cdf0e10cSrcweir // the range of the non-transformed geometry and transform it then. This leads to different 492*cdf0e10cSrcweir // ranges where the new method is more correct, but the need to keep the old behaviour 493*cdf0e10cSrcweir // has priority here. 494*cdf0e10cSrcweir return get3DRangeFromSlices(getSlices()); 495*cdf0e10cSrcweir } 496*cdf0e10cSrcweir 497*cdf0e10cSrcweir Primitive3DSequence SdrExtrudePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const 498*cdf0e10cSrcweir { 499*cdf0e10cSrcweir if(getSdr3DObjectAttribute().getReducedLineGeometry()) 500*cdf0e10cSrcweir { 501*cdf0e10cSrcweir if(!mpLastRLGViewInformation || 502*cdf0e10cSrcweir (getBuffered3DDecomposition().hasElements() 503*cdf0e10cSrcweir && *mpLastRLGViewInformation != rViewInformation)) 504*cdf0e10cSrcweir { 505*cdf0e10cSrcweir // conditions of last local decomposition with reduced lines have changed. Remember 506*cdf0e10cSrcweir // new one and clear current decompositiopn 507*cdf0e10cSrcweir ::osl::Mutex m_mutex; 508*cdf0e10cSrcweir SdrExtrudePrimitive3D* pThat = const_cast< SdrExtrudePrimitive3D* >(this); 509*cdf0e10cSrcweir pThat->setBuffered3DDecomposition(Primitive3DSequence()); 510*cdf0e10cSrcweir delete pThat->mpLastRLGViewInformation; 511*cdf0e10cSrcweir pThat->mpLastRLGViewInformation = new geometry::ViewInformation3D(rViewInformation); 512*cdf0e10cSrcweir } 513*cdf0e10cSrcweir } 514*cdf0e10cSrcweir 515*cdf0e10cSrcweir // no test for buffering needed, call parent 516*cdf0e10cSrcweir return SdrPrimitive3D::get3DDecomposition(rViewInformation); 517*cdf0e10cSrcweir } 518*cdf0e10cSrcweir 519*cdf0e10cSrcweir // provide unique ID 520*cdf0e10cSrcweir ImplPrimitrive3DIDBlock(SdrExtrudePrimitive3D, PRIMITIVE3D_ID_SDREXTRUDEPRIMITIVE3D) 521*cdf0e10cSrcweir 522*cdf0e10cSrcweir } // end of namespace primitive3d 523*cdf0e10cSrcweir } // end of namespace drawinglayer 524*cdf0e10cSrcweir 525*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 526*cdf0e10cSrcweir // eof 527