Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/chart2/source/view/diagram/VDiagram.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <ShapeFactory.hxx>
21
#include <VDiagram.hxx>
22
#include <Diagram.hxx>
23
#include <PropertyMapper.hxx>
24
#include <ViewDefines.hxx>
25
#include <Stripe.hxx>
26
#include <ObjectIdentifier.hxx>
27
#include <ChartType.hxx>
28
#include <BaseGFXHelper.hxx>
29
#include <ThreeDHelper.hxx>
30
#include <defines.hxx>
31
#include <editeng/unoprnms.hxx>
32
#include <svx/scene3d.hxx>
33
#include <svx/e3dsceneupdater.hxx>
34
#include <comphelper/diagnose_ex.hxx>
35
36
namespace chart
37
{
38
using namespace ::com::sun::star;
39
using namespace ::com::sun::star::chart2;
40
41
VDiagram::VDiagram(
42
    const rtl::Reference<Diagram> & xDiagram, const drawing::Direction3D& rPreferredAspectRatio,
43
    sal_Int32 nDimension )
44
0
    : m_nDimensionCount(nDimension)
45
0
    , m_xDiagram(xDiagram)
46
0
    , m_aPreferredAspectRatio(rPreferredAspectRatio)
47
0
    , m_fXAnglePi(0)
48
0
    , m_fYAnglePi(0)
49
0
    , m_fZAnglePi(0)
50
0
    , m_bRightAngledAxes(false)
51
0
{
52
0
    if( m_nDimensionCount != 3)
53
0
        return;
54
55
0
    xDiagram->getRotationAngle( m_fXAnglePi, m_fYAnglePi, m_fZAnglePi );
56
0
    auto xChartType = m_xDiagram->getChartTypeByIndex(0);
57
0
    if (xChartType.is() ? xChartType->isSupportingRightAngledAxes() : true)
58
0
    {
59
0
        if(xDiagram.is())
60
0
            xDiagram->getPropertyValue(u"RightAngledAxes"_ustr) >>= m_bRightAngledAxes;
61
0
        if( m_bRightAngledAxes )
62
0
        {
63
0
            ThreeDHelper::adaptRadAnglesForRightAngledAxes( m_fXAnglePi, m_fYAnglePi );
64
0
            m_fZAnglePi=0.0;
65
0
        }
66
0
    }
67
0
}
68
69
VDiagram::~VDiagram()
70
0
{
71
0
}
72
73
void VDiagram::init( const rtl::Reference<SvxShapeGroupAnyD>& xTarget )
74
0
{
75
0
    m_xTarget  = xTarget;
76
0
}
77
78
void VDiagram::createShapes( const awt::Point& rPos, const awt::Size& rSize )
79
0
{
80
0
    m_aAvailablePosIncludingAxes = rPos;
81
0
    m_aAvailableSizeIncludingAxes = rSize;
82
83
0
    if( m_nDimensionCount == 3 )
84
0
        createShapes_3d();
85
0
    else
86
0
        createShapes_2d();
87
0
}
88
89
::basegfx::B2IRectangle VDiagram::adjustPosAndSize( const awt::Point& rPos, const awt::Size& rSize )
90
0
{
91
0
    ::basegfx::B2IRectangle aAllowedRect( BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes,m_aAvailableSizeIncludingAxes) );
92
0
    ::basegfx::B2IRectangle aNewInnerRect( BaseGFXHelper::makeRectangle(rPos,rSize) );
93
0
    aNewInnerRect.intersect( aAllowedRect );
94
95
0
    if( m_nDimensionCount == 3 )
96
0
        aNewInnerRect = adjustPosAndSize_3d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) );
97
0
    else
98
0
        aNewInnerRect = adjustPosAndSize_2d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) );
99
100
0
    return aNewInnerRect;
101
0
}
102
103
::basegfx::B2IRectangle VDiagram::adjustPosAndSize_2d( const awt::Point& rPos, const awt::Size& rAvailableSize )
104
0
{
105
0
    m_aCurrentPosWithoutAxes = rPos;
106
0
    m_aCurrentSizeWithoutAxes = rAvailableSize;
107
0
    if( m_aPreferredAspectRatio.DirectionX > 0 && m_aPreferredAspectRatio.DirectionY > 0)
108
0
    {
109
        //do not change aspect ratio
110
0
        awt::Size  aAspectRatio( static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME),
111
0
                                 static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionY*FIXED_SIZE_FOR_3D_CHART_VOLUME ));
112
0
        m_aCurrentSizeWithoutAxes = ShapeFactory::calculateNewSizeRespectingAspectRatio(
113
0
                        rAvailableSize, aAspectRatio );
114
        //center diagram position
115
0
        m_aCurrentPosWithoutAxes = ShapeFactory::calculateTopLeftPositionToCenterObject(
116
0
            rPos, rAvailableSize, m_aCurrentSizeWithoutAxes );
117
118
0
    }
119
120
0
    if( m_xWall2D.is() )
121
0
    {
122
0
        m_xWall2D->setSize( m_aCurrentSizeWithoutAxes);
123
0
        m_xWall2D->setPosition(m_aCurrentPosWithoutAxes);
124
0
    }
125
126
0
    return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes);
127
0
}
128
129
void VDiagram::createShapes_2d()
130
0
{
131
0
    OSL_PRECOND(m_xTarget.is(), "is not proper initialized");
132
0
    if (!m_xTarget.is())
133
0
        return;
134
135
    //create group shape
136
0
    rtl::Reference<SvxShapeGroupAnyD> xOuterGroup_Shapes = ShapeFactory::createGroup2D(m_xTarget);
137
0
    m_xOuterGroupShape = xOuterGroup_Shapes;
138
139
0
    rtl::Reference<SvxShapeGroupAnyD> xGroupForWall( ShapeFactory::createGroup2D(xOuterGroup_Shapes,u"PlotAreaExcludingAxes"_ustr) );
140
141
    //create independent group shape as container for datapoints and such things
142
0
    m_xCoordinateRegionShape = ShapeFactory::createGroup2D(xOuterGroup_Shapes,u"testonly;CooContainer=XXX_CID"_ustr);
143
144
0
    bool bAddFloorAndWall = m_xDiagram->isSupportingFloorAndWall();
145
146
    //add back wall
147
0
    {
148
0
        m_xWall2D = ShapeFactory::createRectangle( xGroupForWall );
149
150
0
        try
151
0
        {
152
0
            OSL_ENSURE( m_xDiagram.is(), "Invalid Diagram model" );
153
0
            if( m_xDiagram.is() )
154
0
            {
155
0
                uno::Reference< beans::XPropertySet > xWallProp( m_xDiagram->getWall());
156
0
                if( xWallProp.is())
157
0
                    PropertyMapper::setMappedProperties( *m_xWall2D, xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties() );
158
0
            }
159
0
            if( !bAddFloorAndWall )
160
0
            {
161
                //we always need this object as dummy object for correct scene dimensions
162
                //but it should not be visible in this case:
163
0
                ShapeFactory::makeShapeInvisible( m_xWall2D );
164
0
            }
165
0
            else
166
0
            {
167
                //CID for selection handling
168
0
                OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, u"" ) );//@todo read CID from model
169
0
                m_xWall2D->SvxShape::setPropertyValue( UNO_NAME_MISC_OBJ_NAME, uno::Any( aWallCID ) );
170
0
            }
171
0
        }
172
0
        catch( const uno::Exception& )
173
0
        {
174
0
            TOOLS_WARN_EXCEPTION("chart2", "" );
175
0
        }
176
0
    }
177
178
    //position and size for diagram
179
0
    adjustPosAndSize_2d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes );
180
0
}
181
182
static E3dScene* lcl_getE3dScene( const rtl::Reference<SvxShapeGroupAnyD>& xShape )
183
0
{
184
0
    return DynCastE3dScene(xShape->GetSdrObject());
185
0
}
186
187
static void lcl_setLightSources(
188
    const uno::Reference< beans::XPropertySet > & xSource,
189
    const uno::Reference< beans::XPropertySet > & xDest )
190
0
{
191
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_1,
192
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_1));
193
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_2,
194
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_2));
195
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_3,
196
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_3));
197
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_4,
198
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_4));
199
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_5,
200
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_5));
201
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_6,
202
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_6));
203
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_7,
204
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_7));
205
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_8,
206
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_8));
207
208
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1,
209
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1));
210
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2,
211
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2));
212
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3,
213
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3));
214
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4,
215
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4));
216
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5,
217
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5));
218
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6,
219
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6));
220
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7,
221
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7));
222
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8,
223
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8));
224
225
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_1,
226
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_1));
227
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_2,
228
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_2));
229
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_3,
230
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_3));
231
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_4,
232
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_4));
233
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_5,
234
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_5));
235
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_6,
236
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_6));
237
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_7,
238
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_7));
239
0
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_8,
240
0
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_8));
241
0
}
242
243
namespace
244
{
245
246
void lcl_ensureScaleValue( double& rfScale )
247
0
{
248
0
    OSL_ENSURE(rfScale>0, "calculation error for automatic 3D height in chart");
249
0
    if( rfScale<0 )
250
0
        rfScale = 1.0;
251
0
    else if( rfScale<0.2 )
252
0
        rfScale = 0.2;
253
0
    else if( rfScale>5.0 )
254
0
        rfScale = 5.0;
255
0
}
256
257
}
258
259
void VDiagram::adjustAspectRatio3d( const awt::Size& rAvailableSize )
260
0
{
261
0
    OSL_PRECOND(m_xAspectRatio3D.is(), "created shape offers no XPropertySet");
262
0
    if( !m_xAspectRatio3D.is())
263
0
        return;
264
265
0
    try
266
0
    {
267
0
        double fScaleX = m_aPreferredAspectRatio.DirectionX;
268
0
        double fScaleY = m_aPreferredAspectRatio.DirectionY;
269
0
        double fScaleZ = m_aPreferredAspectRatio.DirectionZ;
270
271
        //normalize scale factors
272
0
        {
273
0
            double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ );
274
0
            fScaleX/=fMax;
275
0
            fScaleY/=fMax;
276
0
            fScaleZ/=fMax;
277
0
        }
278
279
0
        if( fScaleX<0 || fScaleY<0 || fScaleZ<0 )
280
0
        {
281
            //calculate automatic 3D aspect ratio that fits good into the given 2D area
282
0
            double fW = rAvailableSize.Width;
283
0
            double fH = rAvailableSize.Height;
284
285
0
            double sx = fabs(sin(m_fXAnglePi));
286
0
            double sy = fabs(sin(m_fYAnglePi));
287
0
            double cz = fabs(cos(m_fZAnglePi));
288
0
            double sz = fabs(sin(m_fZAnglePi));
289
290
0
            if(m_bRightAngledAxes)
291
0
            {
292
                //base equations:
293
                //fH*zoomfactor == sx*fScaleZ + fScaleY;
294
                //fW*zoomfactor == sy*fScaleZ + fScaleX;
295
296
0
                if( fScaleX>0 && fScaleZ>0 )
297
0
                {
298
                    //calculate fScaleY:
299
0
                    if( !::basegfx::fTools::equalZero(fW) )
300
0
                    {
301
0
                        fScaleY = (fH/fW)*(sy*fScaleZ+fScaleX)-(sx*fScaleZ);
302
0
                        lcl_ensureScaleValue( fScaleY );
303
0
                    }
304
0
                    else
305
0
                        fScaleY = 1.0;//looking from top or bottom the height is irrelevant
306
0
                }
307
0
                else if( fScaleY>0 && fScaleZ>0 )
308
0
                {
309
                    //calculate fScaleX:
310
0
                    if( !::basegfx::fTools::equalZero(fH) )
311
0
                    {
312
0
                        fScaleX = (fW/fH)*(sx*fScaleZ+fScaleY)-(sy*fScaleZ);
313
0
                        lcl_ensureScaleValue(fScaleX);
314
0
                    }
315
0
                    else
316
0
                        fScaleX = 1.0;//looking from top or bottom height is irrelevant
317
0
                }
318
0
                else
319
0
                {
320
                    //todo
321
0
                    OSL_FAIL("not implemented yet");
322
323
0
                    if( fScaleX<0 )
324
0
                        fScaleX = 1.0;
325
0
                    if( fScaleY<0 )
326
0
                        fScaleY = 1.0;
327
0
                    if( fScaleZ<0 )
328
0
                        fScaleZ = 1.0;
329
0
                }
330
0
            }
331
0
            else
332
0
            {
333
                //base equations:
334
                //fH*zoomfactor == cz*fScaleY + sz*fScaleX;
335
                //fW*zoomfactor == cz*fScaleX + sz*fScaleY;
336
                //==>  fScaleY*(fH*sz-fW*cz) == fScaleX*(fW*sz-fH*cz);
337
0
                if( fScaleX>0 && fScaleZ>0 )
338
0
                {
339
                    //calculate fScaleY:
340
0
                    double fDivide = fH*sz-fW*cz;
341
0
                    if( !::basegfx::fTools::equalZero(fDivide) )
342
0
                    {
343
0
                        fScaleY = fScaleX*(fW*sz-fH*cz) / fDivide;
344
0
                        lcl_ensureScaleValue(fScaleY);
345
0
                    }
346
0
                    else
347
0
                        fScaleY = 1.0;//looking from top or bottom the height is irrelevant
348
349
0
                }
350
0
                else if( fScaleY>0 && fScaleZ>0 )
351
0
                {
352
                    //calculate fScaleX:
353
0
                    double fDivide = fW*sz-fH*cz;
354
0
                    if( !::basegfx::fTools::equalZero(fDivide) )
355
0
                    {
356
0
                        fScaleX = fScaleY*(fH*sz-fW*cz) / fDivide;
357
0
                        lcl_ensureScaleValue(fScaleX);
358
0
                    }
359
0
                    else
360
0
                        fScaleX = 1.0;//looking from top or bottom height is irrelevant
361
0
                }
362
0
                else
363
0
                {
364
                    //todo
365
0
                    OSL_FAIL("not implemented yet");
366
367
0
                    if( fScaleX<0 )
368
0
                        fScaleX = 1.0;
369
0
                    if( fScaleY<0 )
370
0
                        fScaleY = 1.0;
371
0
                    if( fScaleZ<0 )
372
0
                        fScaleZ = 1.0;
373
0
                }
374
0
            }
375
0
        }
376
377
        //normalize scale factors
378
0
        {
379
0
            double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ );
380
0
            fScaleX/=fMax;
381
0
            fScaleY/=fMax;
382
0
            fScaleZ/=fMax;
383
0
        }
384
385
        // identity matrix
386
0
        ::basegfx::B3DHomMatrix aResult;
387
0
        aResult.translate( -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
388
0
                        -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
389
0
                        -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0 );
390
0
        aResult.scale( fScaleX, fScaleY, fScaleZ );
391
0
        aResult.translate( FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
392
0
                        FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
393
0
                        FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0 );
394
395
        // To get the 3D aspect ratio's effect on the 2D scene size, the scene's 2D size needs to be adapted to
396
        // 3D content changes here. The tooling class remembers the current 3D transformation stack
397
        // and in its destructor, calculates a new 2D SnapRect for the scene and it's modified 3D geometry.
398
0
        E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene(m_xOuterGroupShape));
399
400
0
        m_xAspectRatio3D->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
401
0
            , uno::Any(BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aResult )) );
402
0
    }
403
0
    catch( const uno::Exception& )
404
0
    {
405
0
        TOOLS_WARN_EXCEPTION("chart2", "" );
406
0
    }
407
0
}
408
409
::basegfx::B2IRectangle VDiagram::adjustPosAndSize_3d( const awt::Point& rPos, const awt::Size& rAvailableSize )
410
0
{
411
0
    adjustAspectRatio3d( rAvailableSize );
412
413
    //do not change aspect ratio of 3D scene with 2D bound rect
414
0
    m_aCurrentSizeWithoutAxes = ShapeFactory::calculateNewSizeRespectingAspectRatio(
415
0
                    rAvailableSize, m_xOuterGroupShape->getSize() );
416
0
    m_xOuterGroupShape->setSize( m_aCurrentSizeWithoutAxes );
417
418
    //center diagram position
419
0
    m_aCurrentPosWithoutAxes= ShapeFactory::calculateTopLeftPositionToCenterObject(
420
0
         rPos, rAvailableSize, m_aCurrentSizeWithoutAxes );
421
0
    m_xOuterGroupShape->setPosition(m_aCurrentPosWithoutAxes);
422
423
0
    return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes);
424
0
}
425
426
void VDiagram::createShapes_3d()
427
0
{
428
0
    OSL_PRECOND(m_xTarget.is(), "is not proper initialized");
429
0
    if (!m_xTarget.is())
430
0
        return;
431
432
    //create shape
433
0
    rtl::Reference<Svx3DSceneObject> xShapes = ShapeFactory::createGroup3D( m_xTarget, u"PlotAreaExcludingAxes"_ustr );
434
0
    m_xOuterGroupShape = xShapes;
435
436
0
    rtl::Reference<SvxShapeGroupAnyD> xOuterGroup_Shapes = m_xOuterGroupShape;
437
438
    //create additional group to manipulate the aspect ratio of the whole diagram:
439
0
    {
440
0
        rtl::Reference<Svx3DSceneObject> xAdditionalGroup = ShapeFactory::createGroup3D( xOuterGroup_Shapes );
441
0
        xOuterGroup_Shapes = xAdditionalGroup;
442
443
0
        m_xAspectRatio3D = std::move(xAdditionalGroup);
444
0
    }
445
446
0
    bool bAddFloorAndWall = m_xDiagram->isSupportingFloorAndWall();
447
448
0
    const bool bDoubleSided = false;
449
450
    //add walls
451
0
    {
452
0
        uno::Reference< beans::XPropertySet > xWallProp;
453
0
        if( m_xDiagram.is() )
454
0
            xWallProp.set( m_xDiagram->getWall() );
455
456
0
        OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, u"" ) );//@todo read CID from model
457
0
        if( !bAddFloorAndWall )
458
0
            aWallCID.clear();
459
0
        rtl::Reference<Svx3DSceneObject> xWallGroup_Shapes = ShapeFactory::createGroup3D( xOuterGroup_Shapes, aWallCID );
460
461
0
        CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( m_xDiagram ) );
462
0
        CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( m_xDiagram ) );
463
464
        //add left wall
465
0
        {
466
0
            short nRotatedTexture = ( eBackWallPos==CuboidPlanePosition_Front ) ? 3 : 1;
467
0
            double xPos = 0.0;
468
0
            if( eLeftWallPos==CuboidPlanePosition_Right )
469
0
                xPos = FIXED_SIZE_FOR_3D_CHART_VOLUME;
470
0
            Stripe aStripe( drawing::Position3D(xPos,FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
471
0
                , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME)
472
0
                , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
473
0
            if( eLeftWallPos==CuboidPlanePosition_Right )
474
0
            {
475
0
                nRotatedTexture = ( eBackWallPos==CuboidPlanePosition_Front ) ? 2 : 0;
476
0
                aStripe = Stripe( drawing::Position3D(xPos,FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
477
0
                    , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
478
0
                    , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME) );
479
0
            }
480
0
            aStripe.InvertNormal(true);
481
482
0
            rtl::Reference<Svx3DPolygonObject> xShape =
483
0
                ShapeFactory::createStripe( xWallGroup_Shapes, aStripe
484
0
                    , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture );
485
0
            if( !bAddFloorAndWall )
486
0
            {
487
                //we always need this object as dummy object for correct scene dimensions
488
                //but it should not be visible in this case:
489
0
                ShapeFactory::makeShapeInvisible( xShape );
490
0
            }
491
0
        }
492
        //add back wall
493
0
        {
494
0
            short nRotatedTexture = 0;
495
0
            double zPos = 0.0;
496
0
            if( eBackWallPos==CuboidPlanePosition_Front )
497
0
                    zPos = FIXED_SIZE_FOR_3D_CHART_VOLUME;
498
0
            Stripe aStripe( drawing::Position3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,zPos)
499
0
                , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
500
0
                , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) );
501
0
            if( eBackWallPos==CuboidPlanePosition_Front )
502
0
            {
503
0
                aStripe = Stripe( drawing::Position3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,zPos)
504
0
                , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0)
505
0
                , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
506
0
                nRotatedTexture = 3;
507
0
            }
508
0
            aStripe.InvertNormal(true);
509
510
0
            rtl::Reference<Svx3DPolygonObject> xShape =
511
0
                ShapeFactory::createStripe(xWallGroup_Shapes, aStripe
512
0
                    , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture );
513
0
            if( !bAddFloorAndWall )
514
0
            {
515
                //we always need this object as dummy object for correct scene dimensions
516
                //but it should not be visible in this case:
517
0
                ShapeFactory::makeShapeInvisible( xShape );
518
0
            }
519
0
        }
520
0
    }
521
522
0
    try
523
0
    {
524
        //perspective
525
0
        {
526
            //ignore distance and focal length from file format and model completely
527
            //use vrp only to indicate the distance of the camera and thus influence the perspective
528
0
            m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_DISTANCE, uno::Any(
529
0
                                        static_cast<sal_Int32>(m_xDiagram->getCameraDistance())));
530
0
            m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_PERSPECTIVE,
531
0
                                        m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_PERSPECTIVE));
532
0
        }
533
534
        //light
535
0
        {
536
0
            m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_SHADE_MODE,
537
0
                                        m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_SHADE_MODE));
538
0
            m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR,
539
0
                                        m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR));
540
0
            m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING,
541
0
                                        m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING));
542
0
            lcl_setLightSources( m_xDiagram, m_xOuterGroupShape );
543
0
        }
544
545
        //rotation
546
0
        {
547
            //set diagrams rotation is set exclusively via the transformation matrix
548
            //don't set a camera at all!
549
            //the camera's rotation is incorporated into this matrix
550
551
0
            ::basegfx::B3DHomMatrix aEffectiveTransformation;
552
0
            aEffectiveTransformation.translate(-FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0, -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0, -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0);
553
554
0
            if(!m_bRightAngledAxes)
555
0
                aEffectiveTransformation.rotate(m_fXAnglePi,m_fYAnglePi,m_fZAnglePi);
556
0
            else
557
0
                aEffectiveTransformation.shearXY(m_fYAnglePi,-m_fXAnglePi);
558
559
            //#i98497# 3D charts are rendered with wrong size
560
0
            E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene(m_xOuterGroupShape));
561
562
0
            m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX,
563
0
                    uno::Any( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aEffectiveTransformation ) ) );
564
0
        }
565
0
    }
566
0
    catch( const uno::Exception & )
567
0
    {
568
0
        DBG_UNHANDLED_EXCEPTION("chart2" );
569
0
    }
570
571
    //add floor plate
572
0
    {
573
0
        uno::Reference< beans::XPropertySet > xFloorProp;
574
0
        if( m_xDiagram.is() )
575
0
            xFloorProp.set( m_xDiagram->getFloor() );
576
577
0
        Stripe aStripe( drawing::Position3D(0,0,0)
578
0
            , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME)
579
0
            , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) );
580
0
        aStripe.InvertNormal(true);
581
582
0
        rtl::Reference<Svx3DPolygonObject> xShape =
583
0
            ShapeFactory::createStripe(xOuterGroup_Shapes, aStripe
584
0
                , xFloorProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided );
585
586
0
        CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( m_xDiagram ) );
587
0
        if( !bAddFloorAndWall || (eBottomPos!=CuboidPlanePosition_Bottom) )
588
0
        {
589
            //we always need this object as dummy object for correct scene dimensions
590
            //but it should not be visible in this case:
591
0
            ShapeFactory::makeShapeInvisible( xShape );
592
0
        }
593
0
        else
594
0
        {
595
0
            OUString aFloorCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, u"" ) );//@todo read CID from model
596
0
            ShapeFactory::setShapeName( xShape, aFloorCID );
597
0
        }
598
0
    }
599
600
    //create an additional scene for the smaller inner coordinate region:
601
0
    {
602
0
        rtl::Reference<Svx3DSceneObject> xShapes2 = ShapeFactory::createGroup3D( xOuterGroup_Shapes,u"testonly;CooContainer=XXX_CID"_ustr );
603
0
        m_xCoordinateRegionShape = xShapes2;
604
605
0
        try
606
0
        {
607
0
            double fXScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
608
0
            double fYScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
609
0
            double fZScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
610
611
0
            ::basegfx::B3DHomMatrix aM;
612
0
            aM.translate(GRID_TO_WALL_DISTANCE/fXScale, GRID_TO_WALL_DISTANCE/fYScale, GRID_TO_WALL_DISTANCE/fZScale);
613
0
            aM.scale( fXScale, fYScale, fZScale );
614
0
            E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene(m_xOuterGroupShape));
615
616
0
            xShapes2->SvxShape::setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
617
0
                , uno::Any(BaseGFXHelper::B3DHomMatrixToHomogenMatrix(aM)) );
618
0
        }
619
0
        catch( const uno::Exception& )
620
0
        {
621
0
            TOOLS_WARN_EXCEPTION("chart2", "" );
622
0
        }
623
0
    }
624
625
0
    m_aCurrentPosWithoutAxes = m_aAvailablePosIncludingAxes;
626
0
    m_aCurrentSizeWithoutAxes = m_aAvailableSizeIncludingAxes;
627
0
    adjustPosAndSize_3d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes );
628
0
}
629
630
basegfx::B2IRectangle VDiagram::getCurrentRectangle() const
631
0
{
632
0
    return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes);
633
0
}
634
635
void VDiagram::reduceToMinimumSize()
636
0
{
637
0
    if( !m_xOuterGroupShape.is() )
638
0
        return;
639
640
0
    awt::Size aMaxSize( m_aAvailableSizeIncludingAxes );
641
0
    awt::Point aMaxPos( m_aAvailablePosIncludingAxes );
642
643
0
    sal_Int32 nNewWidth = std::round(aMaxSize.Width/2.2);
644
0
    sal_Int32 nNewHeight = std::round(aMaxSize.Height/2.2);
645
0
    awt::Size aNewSize( nNewWidth, nNewHeight );
646
0
    awt::Point aNewPos( aMaxPos );
647
0
    aNewPos.X += nNewWidth;
648
0
    aNewPos.Y += nNewHeight;
649
650
0
    adjustPosAndSize( aNewPos, aNewSize );
651
0
}
652
653
::basegfx::B2IRectangle VDiagram::adjustInnerSize( const ::basegfx::B2IRectangle& rConsumedOuterRect )
654
0
{
655
0
    awt::Point aNewPos = m_aCurrentPosWithoutAxes;
656
0
    awt::Size aNewSize = m_aCurrentSizeWithoutAxes;
657
658
0
    basegfx::B2IRectangle aAvailableOuterRect =
659
0
        BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes);
660
661
0
    sal_Int32 nDeltaWidth = aAvailableOuterRect.getWidth() - rConsumedOuterRect.getWidth();
662
0
    sal_Int32 nDeltaHeight = aAvailableOuterRect.getHeight() - rConsumedOuterRect.getHeight();
663
0
    if( (aNewSize.Width + nDeltaWidth) < aAvailableOuterRect.getWidth()/3 )
664
0
        nDeltaWidth = aAvailableOuterRect.getWidth()/3 - aNewSize.Width;
665
0
    aNewSize.Width += nDeltaWidth;
666
667
0
    if( (aNewSize.Height + nDeltaHeight) < aAvailableOuterRect.getHeight()/3 )
668
0
        nDeltaHeight = aAvailableOuterRect.getHeight()/3 - aNewSize.Height;
669
0
    aNewSize.Height += nDeltaHeight;
670
671
0
    sal_Int32 nDiffLeft = rConsumedOuterRect.getMinX() - aAvailableOuterRect.getMinX();
672
0
    sal_Int32 nDiffRight = aAvailableOuterRect.getMaxX() - rConsumedOuterRect.getMaxX();
673
0
    if( nDiffLeft >= 0 )
674
0
        aNewPos.X -= nDiffLeft;
675
0
    else if( nDiffRight >= 0 )
676
0
    {
677
0
        if( nDiffRight > -nDiffLeft )
678
0
            aNewPos.X += abs(nDiffLeft);
679
0
        else if( nDiffRight > abs(nDeltaWidth) )
680
0
            aNewPos.X += nDiffRight;
681
0
        else
682
0
            aNewPos.X += abs(nDeltaWidth);
683
0
    }
684
685
0
    sal_Int32 nDiffUp = rConsumedOuterRect.getMinY() - aAvailableOuterRect.getMinY();
686
0
    sal_Int32 nDiffDown = aAvailableOuterRect.getMaxY() - rConsumedOuterRect.getMaxY();
687
0
    if( nDiffUp >= 0 )
688
0
        aNewPos.Y -= nDiffUp;
689
0
    else if( nDiffDown >= 0 )
690
0
    {
691
0
        if( nDiffDown > -nDiffUp )
692
0
            aNewPos.Y += abs(nDiffUp);
693
0
        else if( nDiffDown > abs(nDeltaHeight) )
694
0
            aNewPos.Y += nDiffDown;
695
0
        else
696
0
            aNewPos.Y += abs(nDeltaHeight);
697
0
    }
698
699
0
    return adjustPosAndSize( aNewPos, aNewSize );
700
0
}
701
702
} //namespace chart
703
704
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */