Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/chart2/source/view/diagram/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 29 kB image not shown  

Quelle  VDiagram.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <ShapeFactory.hxx>
#include <VDiagram.hxx>
#include <Diagram.hxx>
#include <PropertyMapper.hxx>
#include <ViewDefines.hxx>
#include <Stripe.hxx>
#include <ObjectIdentifier.hxx>
#include <DiagramHelper.hxx>
#include <ChartType.hxx>
#include <BaseGFXHelper.hxx>
#include <ChartTypeHelper.hxx>
#include <ThreeDHelper.hxx>
#include <defines.hxx>
#include <editeng/unoprnms.hxx>
#include <svx/scene3d.hxx>
#include <svx/e3dsceneupdater.hxx>
#include <comphelper/diagnose_ex.hxx>

namespace chart
{
using namespace ::com::sun::star;
using namespace ::com::sun::star::chart2;

VDiagram::VDiagram(
    const rtl::Reference<Diagram> & xDiagram, const drawing::Direction3D& rPreferredAspectRatio,
    sal_Int32 nDimension )
    : m_nDimensionCount(nDimension)
    , m_xDiagram(xDiagram)
    , m_aPreferredAspectRatio(rPreferredAspectRatio)
    , m_fXAnglePi(0)
    , m_fYAnglePi(0)
    , m_fZAnglePi(0)
    , m_bRightAngledAxes(false)
{
    if( m_nDimensionCount != 3)
        return;

    xDiagram->getRotationAngle( m_fXAnglePi, m_fYAnglePi, m_fZAnglePi );
    auto xChartType = m_xDiagram->getChartTypeByIndex(0);
    if (xChartType.is() ? xChartType->isSupportingRightAngledAxes() : true)
    {
        if(xDiagram.is())
            xDiagram->getPropertyValue(u"RightAngledAxes"_ustr) >>= m_bRightAngledAxes;
        if( m_bRightAngledAxes )
        {
            ThreeDHelper::adaptRadAnglesForRightAngledAxes( m_fXAnglePi, m_fYAnglePi );
            m_fZAnglePi=0.0;
        }
    }
}

VDiagram::~VDiagram()
{
}

void VDiagram::init( const rtl::Reference<SvxShapeGroupAnyD>& xTarget )
{
    m_xTarget  = xTarget;
}

void VDiagram::createShapes( const awt::Point& rPos, const awt::Size& rSize )
{
    m_aAvailablePosIncludingAxes = rPos;
    m_aAvailableSizeIncludingAxes = rSize;

    if( m_nDimensionCount == 3 )
        createShapes_3d();
    else
        createShapes_2d();
}

::basegfx::B2IRectangle VDiagram::adjustPosAndSize( const awt::Point& rPos, const awt::Size& rSize )
{
    ::basegfx::B2IRectangle aAllowedRect( BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes,m_aAvailableSizeIncludingAxes) );
    ::basegfx::B2IRectangle aNewInnerRect( BaseGFXHelper::makeRectangle(rPos,rSize) );
    aNewInnerRect.intersect( aAllowedRect );

    if( m_nDimensionCount == 3 )
        aNewInnerRect = adjustPosAndSize_3d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) );
    else
        aNewInnerRect = adjustPosAndSize_2d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) );

    return aNewInnerRect;
}

::basegfx::B2IRectangle VDiagram::adjustPosAndSize_2d( const awt::Point& rPos, const awt::Size& rAvailableSize )
{
    m_aCurrentPosWithoutAxes = rPos;
    m_aCurrentSizeWithoutAxes = rAvailableSize;
    if( m_aPreferredAspectRatio.DirectionX > 0 && m_aPreferredAspectRatio.DirectionY > 0)
    {
        //do not change aspect ratio
        awt::Size  aAspectRatio( static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME),
                                 static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionY*FIXED_SIZE_FOR_3D_CHART_VOLUME ));
        m_aCurrentSizeWithoutAxes = ShapeFactory::calculateNewSizeRespectingAspectRatio(
                        rAvailableSize, aAspectRatio );
        //center diagram position
        m_aCurrentPosWithoutAxes = ShapeFactory::calculateTopLeftPositionToCenterObject(
            rPos, rAvailableSize, m_aCurrentSizeWithoutAxes );

    }

    if( m_xWall2D.is() )
    {
        m_xWall2D->setSize( m_aCurrentSizeWithoutAxes);
        m_xWall2D->setPosition(m_aCurrentPosWithoutAxes);
    }

    return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes);
}

void VDiagram::createShapes_2d()
{
    OSL_PRECOND(m_xTarget.is(), "is not proper initialized");
    if (!m_xTarget.is())
        return;

    //create group shape
    rtl::Reference<SvxShapeGroupAnyD> xOuterGroup_Shapes = ShapeFactory::createGroup2D(m_xTarget);
    m_xOuterGroupShape = xOuterGroup_Shapes;

    rtl::Reference<SvxShapeGroupAnyD> xGroupForWall( ShapeFactory::createGroup2D(xOuterGroup_Shapes,u"PlotAreaExcludingAxes"_ustr) );

    //create independent group shape as container for datapoints and such things
    m_xCoordinateRegionShape = ShapeFactory::createGroup2D(xOuterGroup_Shapes,u"testonly;CooContainer=XXX_CID"_ustr);

    bool bAddFloorAndWall = m_xDiagram->isSupportingFloorAndWall();

    //add back wall
    {
        m_xWall2D = ShapeFactory::createRectangle( xGroupForWall );

        try
        {
            OSL_ENSURE( m_xDiagram.is(), "Invalid Diagram model" );
            if( m_xDiagram.is() )
            {
                uno::Reference< beans::XPropertySet > xWallProp( m_xDiagram->getWall());
                if( xWallProp.is())
                    PropertyMapper::setMappedProperties( *m_xWall2D, xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties() );
            }
            if( !bAddFloorAndWall )
            {
                //we always need this object as dummy object for correct scene dimensions
                //but it should not be visible in this case:
                ShapeFactory::makeShapeInvisible( m_xWall2D );
            }
            else
            {
                //CID for selection handling
                OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, u"" ) );//@todo read CID from model
                m_xWall2D->SvxShape::setPropertyValue( UNO_NAME_MISC_OBJ_NAME, uno::Any( aWallCID ) );
            }
        }
        catchconst uno::Exception& )
        {
            TOOLS_WARN_EXCEPTION("chart2""" );
        }
    }

    //position and size for diagram
    adjustPosAndSize_2d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes );
}

static E3dScene* lcl_getE3dScene( const rtl::Reference<SvxShapeGroupAnyD>& xShape )
{
    return DynCastE3dScene(xShape->GetSdrObject());
}

static void lcl_setLightSources(
    const uno::Reference< beans::XPropertySet > & xSource,
    const uno::Reference< beans::XPropertySet > & xDest )
{
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_1,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_1));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_2,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_2));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_3,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_3));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_4,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_4));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_5,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_5));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_6,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_6));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_7,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_7));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_8,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_8));

    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8));

    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_1,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_1));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_2,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_2));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_3,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_3));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_4,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_4));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_5,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_5));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_6,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_6));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_7,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_7));
    xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_8,
                             xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_8));
}

namespace
{

void lcl_ensureScaleValue( double& rfScale )
{
    OSL_ENSURE(rfScale>0, "calculation error for automatic 3D height in chart");
    if( rfScale<0 )
        rfScale = 1.0;
    else if( rfScale<0.2 )
        rfScale = 0.2;
    else if( rfScale>5.0 )
        rfScale = 5.0;
}

}

void VDiagram::adjustAspectRatio3d( const awt::Size& rAvailableSize )
{
    OSL_PRECOND(m_xAspectRatio3D.is(), "created shape offers no XPropertySet");
    if( !m_xAspectRatio3D.is())
        return;

    try
    {
        double fScaleX = m_aPreferredAspectRatio.DirectionX;
        double fScaleY = m_aPreferredAspectRatio.DirectionY;
        double fScaleZ = m_aPreferredAspectRatio.DirectionZ;

        //normalize scale factors
        {
            double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ );
            fScaleX/=fMax;
            fScaleY/=fMax;
            fScaleZ/=fMax;
        }

        if( fScaleX<0 || fScaleY<0 || fScaleZ<0 )
        {
            //calculate automatic 3D aspect ratio that fits good into the given 2D area
            double fW = rAvailableSize.Width;
            double fH = rAvailableSize.Height;

            double sx = fabs(sin(m_fXAnglePi));
            double sy = fabs(sin(m_fYAnglePi));
            double cz = fabs(cos(m_fZAnglePi));
            double sz = fabs(sin(m_fZAnglePi));

            if(m_bRightAngledAxes)
            {
                //base equations:
                //fH*zoomfactor == sx*fScaleZ + fScaleY;
                //fW*zoomfactor == sy*fScaleZ + fScaleX;

                if( fScaleX>0 && fScaleZ>0 )
                {
                    //calculate fScaleY:
                    if( !::basegfx::fTools::equalZero(fW) )
                    {
                        fScaleY = (fH/fW)*(sy*fScaleZ+fScaleX)-(sx*fScaleZ);
                        lcl_ensureScaleValue( fScaleY );
                    }
                    else
                        fScaleY = 1.0;//looking from top or bottom the height is irrelevant
                }
                else if( fScaleY>0 && fScaleZ>0 )
                {
                    //calculate fScaleX:
                    if( !::basegfx::fTools::equalZero(fH) )
                    {
                        fScaleX = (fW/fH)*(sx*fScaleZ+fScaleY)-(sy*fScaleZ);
                        lcl_ensureScaleValue(fScaleX);
                    }
                    else
                        fScaleX = 1.0;//looking from top or bottom height is irrelevant
                }
                else
                {
                    //todo
                    OSL_FAIL("not implemented yet");

                    if( fScaleX<0 )
                        fScaleX = 1.0;
                    if( fScaleY<0 )
                        fScaleY = 1.0;
                    if( fScaleZ<0 )
                        fScaleZ = 1.0;
                }
            }
            else
            {
                //base equations:
                //fH*zoomfactor == cz*fScaleY + sz*fScaleX;
                //fW*zoomfactor == cz*fScaleX + sz*fScaleY;
                //==>  fScaleY*(fH*sz-fW*cz) == fScaleX*(fW*sz-fH*cz);
                if( fScaleX>0 && fScaleZ>0 )
                {
                    //calculate fScaleY:
                    double fDivide = fH*sz-fW*cz;
                    if( !::basegfx::fTools::equalZero(fDivide) )
                    {
                        fScaleY = fScaleX*(fW*sz-fH*cz) / fDivide;
                        lcl_ensureScaleValue(fScaleY);
                    }
                    else
                        fScaleY = 1.0;//looking from top or bottom the height is irrelevant

                }
                else if( fScaleY>0 && fScaleZ>0 )
                {
                    //calculate fScaleX:
                    double fDivide = fW*sz-fH*cz;
                    if( !::basegfx::fTools::equalZero(fDivide) )
                    {
                        fScaleX = fScaleY*(fH*sz-fW*cz) / fDivide;
                        lcl_ensureScaleValue(fScaleX);
                    }
                    else
                        fScaleX = 1.0;//looking from top or bottom height is irrelevant
                }
                else
                {
                    //todo
                    OSL_FAIL("not implemented yet");

                    if( fScaleX<0 )
                        fScaleX = 1.0;
                    if( fScaleY<0 )
                        fScaleY = 1.0;
                    if( fScaleZ<0 )
                        fScaleZ = 1.0;
                }
            }
        }

        //normalize scale factors
        {
            double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ );
            fScaleX/=fMax;
            fScaleY/=fMax;
            fScaleZ/=fMax;
        }

        // identity matrix
        ::basegfx::B3DHomMatrix aResult;
        aResult.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 );
        aResult.scale( fScaleX, fScaleY, fScaleZ );
        aResult.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 );

        // To get the 3D aspect ratio's effect on the 2D scene size, the scene's 2D size needs to be adapted to
        // 3D content changes here. The tooling class remembers the current 3D transformation stack
        // and in its destructor, calculates a new 2D SnapRect for the scene and it's modified 3D geometry.
        E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene(m_xOuterGroupShape));

        m_xAspectRatio3D->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
            , uno::Any(BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aResult )) );
    }
    catchconst uno::Exception& )
    {
        TOOLS_WARN_EXCEPTION("chart2""" );
    }
}

::basegfx::B2IRectangle VDiagram::adjustPosAndSize_3d( const awt::Point& rPos, const awt::Size& rAvailableSize )
{
    adjustAspectRatio3d( rAvailableSize );

    //do not change aspect ratio of 3D scene with 2D bound rect
    m_aCurrentSizeWithoutAxes = ShapeFactory::calculateNewSizeRespectingAspectRatio(
                    rAvailableSize, m_xOuterGroupShape->getSize() );
    m_xOuterGroupShape->setSize( m_aCurrentSizeWithoutAxes );

    //center diagram position
    m_aCurrentPosWithoutAxes= ShapeFactory::calculateTopLeftPositionToCenterObject(
         rPos, rAvailableSize, m_aCurrentSizeWithoutAxes );
    m_xOuterGroupShape->setPosition(m_aCurrentPosWithoutAxes);

    return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes);
}

void VDiagram::createShapes_3d()
{
    OSL_PRECOND(m_xTarget.is(), "is not proper initialized");
    if (!m_xTarget.is())
        return;

    //create shape
    rtl::Reference<Svx3DSceneObject> xShapes = ShapeFactory::createGroup3D( m_xTarget, u"PlotAreaExcludingAxes"_ustr );
    m_xOuterGroupShape = xShapes;

    rtl::Reference<SvxShapeGroupAnyD> xOuterGroup_Shapes = m_xOuterGroupShape;

    //create additional group to manipulate the aspect ratio of the whole diagram:
    {
        rtl::Reference<Svx3DSceneObject> xAdditionalGroup = ShapeFactory::createGroup3D( xOuterGroup_Shapes );
        xOuterGroup_Shapes = xAdditionalGroup;

        m_xAspectRatio3D = std::move(xAdditionalGroup);
    }

    bool bAddFloorAndWall = m_xDiagram->isSupportingFloorAndWall();

    const bool bDoubleSided = false;

    //add walls
    {
        uno::Reference< beans::XPropertySet > xWallProp;
        if( m_xDiagram.is() )
            xWallProp.set( m_xDiagram->getWall() );

        OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, u"" ) );//@todo read CID from model
        if( !bAddFloorAndWall )
            aWallCID.clear();
        rtl::Reference<Svx3DSceneObject> xWallGroup_Shapes = ShapeFactory::createGroup3D( xOuterGroup_Shapes, aWallCID );

        CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( m_xDiagram ) );
        CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( m_xDiagram ) );

        //add left wall
        {
            short nRotatedTexture = ( eBackWallPos==CuboidPlanePosition_Front ) ? 3 : 1;
            double xPos = 0.0;
            if( eLeftWallPos==CuboidPlanePosition_Right )
                xPos = FIXED_SIZE_FOR_3D_CHART_VOLUME;
            Stripe aStripe( drawing::Position3D(xPos,FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
                , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME)
                , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
            if( eLeftWallPos==CuboidPlanePosition_Right )
            {
                nRotatedTexture = ( eBackWallPos==CuboidPlanePosition_Front ) ? 2 : 0;
                aStripe = Stripe( drawing::Position3D(xPos,FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
                    , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
                    , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME) );
            }
            aStripe.InvertNormal(true);

            rtl::Reference<Svx3DPolygonObject> xShape =
                ShapeFactory::createStripe( xWallGroup_Shapes, aStripe
                    , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture );
            if( !bAddFloorAndWall )
            {
                //we always need this object as dummy object for correct scene dimensions
                //but it should not be visible in this case:
                ShapeFactory::makeShapeInvisible( xShape );
            }
        }
        //add back wall
        {
            short nRotatedTexture = 0;
            double zPos = 0.0;
            if( eBackWallPos==CuboidPlanePosition_Front )
                    zPos = FIXED_SIZE_FOR_3D_CHART_VOLUME;
            Stripe aStripe( drawing::Position3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,zPos)
                , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
                , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) );
            if( eBackWallPos==CuboidPlanePosition_Front )
            {
                aStripe = Stripe( drawing::Position3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,zPos)
                , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0)
                , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
                nRotatedTexture = 3;
            }
            aStripe.InvertNormal(true);

            rtl::Reference<Svx3DPolygonObject> xShape =
                ShapeFactory::createStripe(xWallGroup_Shapes, aStripe
                    , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture );
            if( !bAddFloorAndWall )
            {
                //we always need this object as dummy object for correct scene dimensions
                //but it should not be visible in this case:
                ShapeFactory::makeShapeInvisible( xShape );
            }
        }
    }

    try
    {
        //perspective
        {
            //ignore distance and focal length from file format and model completely
            //use vrp only to indicate the distance of the camera and thus influence the perspective
            m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_DISTANCE, uno::Any(
                                        static_cast<sal_Int32>(m_xDiagram->getCameraDistance())));
            m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_PERSPECTIVE,
                                        m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_PERSPECTIVE));
        }

        //light
        {
            m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_SHADE_MODE,
                                        m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_SHADE_MODE));
            m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR,
                                        m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR));
            m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING,
                                        m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING));
            lcl_setLightSources( m_xDiagram, m_xOuterGroupShape );
        }

        //rotation
        {
            //set diagrams rotation is set exclusively via the transformation matrix
            //don't set a camera at all!
            //the camera's rotation is incorporated into this matrix

            ::basegfx::B3DHomMatrix aEffectiveTransformation;
            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);

            if(!m_bRightAngledAxes)
                aEffectiveTransformation.rotate(m_fXAnglePi,m_fYAnglePi,m_fZAnglePi);
            else
                aEffectiveTransformation.shearXY(m_fYAnglePi,-m_fXAnglePi);

            //#i98497# 3D charts are rendered with wrong size
            E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene(m_xOuterGroupShape));

            m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX,
                    uno::Any( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aEffectiveTransformation ) ) );
        }
    }
    catchconst uno::Exception & )
    {
        DBG_UNHANDLED_EXCEPTION("chart2" );
    }

    //add floor plate
    {
        uno::Reference< beans::XPropertySet > xFloorProp;
        if( m_xDiagram.is() )
            xFloorProp.set( m_xDiagram->getFloor() );

        Stripe aStripe( drawing::Position3D(0,0,0)
            , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME)
            , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) );
        aStripe.InvertNormal(true);

        rtl::Reference<Svx3DPolygonObject> xShape =
            ShapeFactory::createStripe(xOuterGroup_Shapes, aStripe
                , xFloorProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided );

        CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( m_xDiagram ) );
        if( !bAddFloorAndWall || (eBottomPos!=CuboidPlanePosition_Bottom) )
        {
            //we always need this object as dummy object for correct scene dimensions
            //but it should not be visible in this case:
            ShapeFactory::makeShapeInvisible( xShape );
        }
        else
        {
            OUString aFloorCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, u"" ) );//@todo read CID from model
            ShapeFactory::setShapeName( xShape, aFloorCID );
        }
    }

    //create an additional scene for the smaller inner coordinate region:
    {
        rtl::Reference<Svx3DSceneObject> xShapes2 = ShapeFactory::createGroup3D( xOuterGroup_Shapes,u"testonly;CooContainer=XXX_CID"_ustr );
        m_xCoordinateRegionShape = xShapes2;

        try
        {
            double fXScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
            double fYScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
            double fZScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;

            ::basegfx::B3DHomMatrix aM;
            aM.translate(GRID_TO_WALL_DISTANCE/fXScale, GRID_TO_WALL_DISTANCE/fYScale, GRID_TO_WALL_DISTANCE/fZScale);
            aM.scale( fXScale, fYScale, fZScale );
            E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene(m_xOuterGroupShape));

            xShapes2->SvxShape::setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
                , uno::Any(BaseGFXHelper::B3DHomMatrixToHomogenMatrix(aM)) );
        }
        catchconst uno::Exception& )
        {
            TOOLS_WARN_EXCEPTION("chart2""" );
        }
    }

    m_aCurrentPosWithoutAxes = m_aAvailablePosIncludingAxes;
    m_aCurrentSizeWithoutAxes = m_aAvailableSizeIncludingAxes;
    adjustPosAndSize_3d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes );
}

basegfx::B2IRectangle VDiagram::getCurrentRectangle() const
{
    return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes);
}

void VDiagram::reduceToMinimumSize()
{
    if( !m_xOuterGroupShape.is() )
        return;

    awt::Size aMaxSize( m_aAvailableSizeIncludingAxes );
    awt::Point aMaxPos( m_aAvailablePosIncludingAxes );

    sal_Int32 nNewWidth = std::round(aMaxSize.Width/2.2);
    sal_Int32 nNewHeight = std::round(aMaxSize.Height/2.2);
    awt::Size aNewSize( nNewWidth, nNewHeight );
    awt::Point aNewPos( aMaxPos );
    aNewPos.X += nNewWidth;
    aNewPos.Y += nNewHeight;

    adjustPosAndSize( aNewPos, aNewSize );
}

::basegfx::B2IRectangle VDiagram::adjustInnerSize( const ::basegfx::B2IRectangle&&nbsp;rConsumedOuterRect )
{
    awt::Point aNewPos = m_aCurrentPosWithoutAxes;
    awt::Size aNewSize = m_aCurrentSizeWithoutAxes;

    basegfx::B2IRectangle aAvailableOuterRect =
        BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes);

    sal_Int32 nDeltaWidth = aAvailableOuterRect.getWidth() - rConsumedOuterRect.getWidth();
    sal_Int32 nDeltaHeight = aAvailableOuterRect.getHeight() - rConsumedOuterRect.getHeight();
    if( (aNewSize.Width + nDeltaWidth) < aAvailableOuterRect.getWidth()/3 )
        nDeltaWidth = aAvailableOuterRect.getWidth()/3 - aNewSize.Width;
    aNewSize.Width += nDeltaWidth;

    if( (aNewSize.Height + nDeltaHeight) < aAvailableOuterRect.getHeight()/3 )
        nDeltaHeight = aAvailableOuterRect.getHeight()/3 - aNewSize.Height;
    aNewSize.Height += nDeltaHeight;

    sal_Int32 nDiffLeft = rConsumedOuterRect.getMinX() - aAvailableOuterRect.getMinX();
    sal_Int32 nDiffRight = aAvailableOuterRect.getMaxX() - rConsumedOuterRect.getMaxX();
    if( nDiffLeft >= 0 )
        aNewPos.X -= nDiffLeft;
    else if( nDiffRight >= 0 )
    {
        if( nDiffRight > -nDiffLeft )
            aNewPos.X += abs(nDiffLeft);
        else if( nDiffRight > abs(nDeltaWidth) )
            aNewPos.X += nDiffRight;
        else
            aNewPos.X += abs(nDeltaWidth);
    }

    sal_Int32 nDiffUp = rConsumedOuterRect.getMinY() - aAvailableOuterRect.getMinY();
    sal_Int32 nDiffDown = aAvailableOuterRect.getMaxY() - rConsumedOuterRect.getMaxY();
    if( nDiffUp >= 0 )
        aNewPos.Y -= nDiffUp;
    else if( nDiffDown >= 0 )
    {
        if( nDiffDown > -nDiffUp )
            aNewPos.Y += abs(nDiffUp);
        else if( nDiffDown > abs(nDeltaHeight) )
            aNewPos.Y += nDiffDown;
        else
            aNewPos.Y += abs(nDeltaHeight);
    }

    return adjustPosAndSize( aNewPos, aNewSize );
}

//namespace chart

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=94 H=99 G=96

¤ Dauer der Verarbeitung: 0.2 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.