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

Quelle  VCoordinateSystem.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 <BaseGFXHelper.hxx>
#include <ChartView.hxx>
#include <DateHelper.hxx>
#include <VCoordinateSystem.hxx>
#include "VCartesianCoordinateSystem.hxx"
#include "VPolarCoordinateSystem.hxx"
#include <BaseCoordinateSystem.hxx>
#include <ExplicitCategoriesProvider.hxx>
#include <GridProperties.hxx>
#include <ChartModel.hxx>
#include <ScaleAutomatism.hxx>
#include <ShapeFactory.hxx>
#include <servicenames_coosystems.hxx>
#include <ObjectIdentifier.hxx>
#include <ExplicitCategoriesProvider.hxx>
#include <Axis.hxx>
#include "VAxisBase.hxx"
#include <defines.hxx>
#include <com/sun/star/chart/TimeUnit.hpp>
#include <com/sun/star/chart2/AxisType.hpp>
#include <rtl/math.hxx>
#include <comphelper/diagnose_ex.hxx>

#include <algorithm>
#include <limits>
#include <utility>

namespace chart
{
using namespace ::com::sun::star;
using namespace ::com::sun::star::chart2;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;

std::unique_ptr<VCoordinateSystem> VCoordinateSystem::createCoordinateSystem(
            const rtl::Reference< BaseCoordinateSystem >& xCooSysModel )
{
    if( !xCooSysModel.is() )
        return nullptr;

    OUString aViewServiceName = xCooSysModel->getViewServiceName();

    //@todo: in future the coordinatesystems should be instantiated via service factory
    std::unique_ptr<VCoordinateSystem> pRet;
    if( aViewServiceName == CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME )
        pRet.reset( new VCartesianCoordinateSystem(xCooSysModel) );
    else if( aViewServiceName == CHART2_COOSYSTEM_POLAR_VIEW_SERVICE_NAME )
        pRet.reset( new VPolarCoordinateSystem(xCooSysModel) );
    if(!pRet)
        pRet.reset( new VCoordinateSystem(xCooSysModel) );
    return pRet;
}

VCoordinateSystem::VCoordinateSystem( rtl::Reference< BaseCoordinateSystem > xCooSys )
    : m_xCooSysModel(std::move(xCooSys))
    , m_eLeftWallPos(CuboidPlanePosition_Left)
    , m_eBackWallPos(CuboidPlanePosition_Back)
    , m_eBottomPos(CuboidPlanePosition_Bottom)
    , m_aExplicitScales(3)
    , m_aExplicitIncrements(3)
{
    if( !m_xCooSysModel.is() || m_xCooSysModel->getDimension()<3 )
    {
        m_aExplicitScales[2].Minimum = 1.0;
        m_aExplicitScales[2].Maximum = 2.0;
        m_aExplicitScales[2].Orientation = AxisOrientation_MATHEMATICAL;
    }
}
VCoordinateSystem::~VCoordinateSystem()
{
}

void VCoordinateSystem::initPlottingTargets(  const rtl::Reference< SvxShapeGroupAnyD >&&nbsp;xLogicTarget
       , const rtl::Reference< SvxShapeGroupAnyD >& xFinalTarget
       , rtl::Reference<SvxShapeGroupAnyD>& xLogicTargetForSeriesBehindAxis )
{
    OSL_PRECOND(xLogicTarget.is()&&xFinalTarget.is(),"no proper initialization parameters");
    //is only allowed to be called once

    sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
    //create group shape for grids first thus axes are always painted above grids
    if(nDimensionCount==2)
    {
        //create and add to target
        m_xLogicTargetForGrids = ShapeFactory::createGroup2D( xLogicTarget );
        xLogicTargetForSeriesBehindAxis = ShapeFactory::createGroup2D( xLogicTarget );
        m_xLogicTargetForAxes = ShapeFactory::createGroup2D( xLogicTarget );
    }
    else
    {
        //create and added to target
        m_xLogicTargetForGrids = ShapeFactory::createGroup3D( xLogicTarget );
        xLogicTargetForSeriesBehindAxis = ShapeFactory::createGroup3D( xLogicTarget );
        m_xLogicTargetForAxes = ShapeFactory::createGroup3D( xLogicTarget );
    }
    m_xFinalTarget  = xFinalTarget;
}

void VCoordinateSystem::setParticle( const OUString& rCooSysParticle )
{
    m_aCooSysParticle = rCooSysParticle;
}

void VCoordinateSystem::setTransformationSceneToScreen(
    const drawing::HomogenMatrix& rMatrix )
{
    m_aMatrixSceneToScreen = rMatrix;

    //correct transformation for axis
    for (auto const& elem : m_aAxisMap)
    {
        VAxisBase* pVAxis = elem.second.get();
        if( pVAxis )
        {
            if(pVAxis->getDimensionCount()==2)
                pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
        }
    }
}

//better performance for big data
uno::Sequence< sal_Int32 > VCoordinateSystem::getCoordinateSystemResolution(
            const awt::Size& rPageSize, const awt::Size& rPageResolution )
{
    uno::Sequence<sal_Int32> aResolution(
        std::max<sal_Int32>(m_xCooSysModel->getDimension(), 2));
    auto aResolutionRange = asNonConstRange(aResolution);
    forauto& i : aResolutionRange )
        i = 1000;

    ::basegfx::B3DTuple aScale( BaseGFXHelper::GetScaleFromMatrix(
        BaseGFXHelper::HomogenMatrixToB3DHomMatrix(
            m_aMatrixSceneToScreen ) ) );

    double fCoosysWidth = fabs(aScale.getX()*FIXED_SIZE_FOR_3D_CHART_VOLUME);
    double fCoosysHeight = fabs(aScale.getY()*FIXED_SIZE_FOR_3D_CHART_VOLUME);

    double fPageWidth = rPageSize.Width;
    double fPageHeight = rPageSize.Height;

    //factor 2 to avoid rounding problems
    sal_Int32 nXResolution = static_cast<sal_Int32>(2.0*static_cast<double>(rPageResolution.Width)*fCoosysWidth/fPageWidth);
    sal_Int32 nYResolution = static_cast<sal_Int32>(2.0*static_cast<double>(rPageResolution.Height)*fCoosysHeight/fPageHeight);

    if( nXResolution < 10 )
        nXResolution = 10;
    if( nYResolution < 10 )
        nYResolution = 10;

    if( getPropertySwapXAndYAxis() )
        std::swap(nXResolution,nYResolution);

    //2D
    if( aResolution.getLength() == 2 )
    {
        aResolutionRange[0]=nXResolution;
        aResolutionRange[1]=nYResolution;
    }
    else
    {
        //this maybe can be optimized further ...
        sal_Int32 nMaxResolution = std::max( nXResolution, nYResolution );
        nMaxResolution*=2;
        forauto& i : asNonConstRange(aResolution) )
            i = nMaxResolution;
    }

    return aResolution;
}

rtl::Reference< Axis > VCoordinateSystem::getAxisByDimension( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
{
    if( m_xCooSysModel.is() )
        return m_xCooSysModel->getAxisByDimension2( nDimensionIndex, nAxisIndex );
    return nullptr;
}

std::vector< rtl::Reference< ::chart::GridProperties > > VCoordinateSystem::getGridListFromAxis( const rtl::Reference< Axis >& xAxis )
{
    std::vector< rtl::Reference< ::chart::GridProperties > > aRet;

    if( xAxis.is() )
    {
        aRet.push_back( xAxis->getGridProperties2() );
        std::vector<rtl::Reference<::chart::GridProperties>> aSubGrids = xAxis->getSubGridProperties2();
        aRet.insert( aRet.end(), aSubGrids.begin(), aSubGrids.end() );
    }

    return aRet;
}

void VCoordinateSystem::impl_adjustDimension( sal_Int32& rDimensionIndex )
{
    rDimensionIndex = std::clamp<sal_Int32>(rDimensionIndex, 0, 2);
}

void VCoordinateSystem::impl_adjustDimensionAndIndex( sal_Int32& rDimensionIndex, sal_Int32& rAxisIndex ) const
{
    impl_adjustDimension( rDimensionIndex );

    if( rAxisIndex < 0 || rAxisIndex > getMaximumAxisIndexByDimension(rDimensionIndex) )
        rAxisIndex = 0;
}

void VCoordinateSystem::setExplicitCategoriesProvider( ExplicitCategoriesProvider* pExplicitCategoriesProvider /*takes ownership*/ )
{
    m_apExplicitCategoriesProvider.reset(pExplicitCategoriesProvider);
}

ExplicitCategoriesProvider* VCoordinateSystem::getExplicitCategoriesProvider()
{
    return m_apExplicitCategoriesProvider.get();
}

std::vector< ExplicitScaleData > VCoordinateSystem::getExplicitScales( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
{
    std::vector< ExplicitScaleData > aRet(m_aExplicitScales);

    impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );
    aRet[nDimensionIndex]=getExplicitScale( nDimensionIndex, nAxisIndex );

    return aRet;
}

std::vector< ExplicitIncrementData > VCoordinateSystem::getExplicitIncrements( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
{
    std::vector< ExplicitIncrementData > aRet(m_aExplicitIncrements);

    impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );
    aRet[nDimensionIndex]=getExplicitIncrement( nDimensionIndex, nAxisIndex );

    return aRet;
}

ExplicitScaleData VCoordinateSystem::getExplicitScale( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
{
    ExplicitScaleData aRet;

    impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );

    if( nAxisIndex == 0)
    {
        aRet = m_aExplicitScales[nDimensionIndex];
    }
    else
    {
        tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
        tFullExplicitScaleMap::const_iterator aIt = m_aSecondaryExplicitScales.find( aFullAxisIndex );
        if( aIt != m_aSecondaryExplicitScales.end() )
            aRet = aIt->second;
        else
            aRet = m_aExplicitScales[nDimensionIndex];
    }

    return aRet;
}

ExplicitIncrementData VCoordinateSystem::getExplicitIncrement( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
{
    ExplicitIncrementData aRet;

    impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );

    if( nAxisIndex == 0)
    {
        aRet = m_aExplicitIncrements[nDimensionIndex];
    }
    else
    {
        tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
        tFullExplicitIncrementMap::const_iterator aIt = m_aSecondaryExplicitIncrements.find( aFullAxisIndex );
        if( aIt != m_aSecondaryExplicitIncrements.end() )
            aRet = aIt->second;
        else
            aRet = m_aExplicitIncrements[nDimensionIndex];
    }

    return aRet;
}

OUString VCoordinateSystem::createCIDForAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
{
    OUString aAxisParticle( ObjectIdentifier::createParticleForAxis( nDimensionIndex, nAxisIndex ) );
    return ObjectIdentifier::createClassifiedIdentifierForParticles( m_aCooSysParticle, aAxisParticle );
}
OUString VCoordinateSystem::createCIDForGrid( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
{
    OUString aGridParticle( ObjectIdentifier::createParticleForGrid( nDimensionIndex, nAxisIndex ) );
    return ObjectIdentifier::createClassifiedIdentifierForParticles( m_aCooSysParticle, aGridParticle );
}

sal_Int32 VCoordinateSystem::getMaximumAxisIndexByDimension( sal_Int32 nDimensionIndex ) const
{
    sal_Int32 nRet = 0;
    for (auto const& elem : m_aSecondaryExplicitScales)
    {
        if(elem.first.first==nDimensionIndex)
        {
            sal_Int32 nLocalIdx = elem.first.second;
            if( nRet < nLocalIdx )
                nRet = nLocalIdx;
        }
    }
    return nRet;
}

void VCoordinateSystem::createVAxisList(
            const rtl::Reference<::chart::ChartModel> & /* xChartDoc */,
            const awt::Size& /* rFontReferenceSize */,
            const awt::Rectangle& /* rMaximumSpaceForLabels */,
            bool /* bLimitSpaceForLabels */,
            std::vector<std::unique_ptr<VSeriesPlotter>>& /*rSeriesPlotterList*/,
            uno::Reference<uno::XComponentContext> const/*rComponentContext*/)
{
}

void VCoordinateSystem::initVAxisInList()
{
}
void VCoordinateSystem::updateScalesAndIncrementsOnAxes()
{
}

void VCoordinateSystem::prepareAutomaticAxisScaling( ScaleAutomatism& rScaleAutomatism, sal_Int32 nDimIndex, sal_Int32 nAxisIndex )
{
    bool bDateAxisX = (rScaleAutomatism.getScale().AxisType == AxisType::DATE) && (nDimIndex == 0);
    if( bDateAxisX )
    {
        // This is a date X dimension.  Determine proper time resolution.
        sal_Int32 nTimeResolution = css::chart::TimeUnit::MONTH;
        if( !(rScaleAutomatism.getScale().TimeIncrement.TimeResolution >>= nTimeResolution) )
        {
            nTimeResolution = m_aMergedMinMaxSupplier.calculateTimeResolutionOnXAxis();
            rScaleAutomatism.setAutomaticTimeResolution( nTimeResolution );
        }
        m_aMergedMinMaxSupplier.setTimeResolutionOnXAxis( nTimeResolution, rScaleAutomatism.getNullDate() );
    }

    double fMin = std::numeric_limits<double>::infinity();
    double fMax = -std::numeric_limits<double>::infinity();
    if( nDimIndex == 0 )
    {
        // x dimension
        fMin = m_aMergedMinMaxSupplier.getMinimumX();
        fMax = m_aMergedMinMaxSupplier.getMaximumX();
    }
    else if( nDimIndex == 1 )
    {
        // y dimension
        ExplicitScaleData aScale = getExplicitScale( 0, 0 );
        if (!aScale.m_bShiftedCategoryPosition && aScale.AxisType == AxisType::DATE)
        {
            double fMaximum = aScale.Maximum;
            // tdf#146066 Increase maximum date value by one month/year,
            //            because the automatic scaling of the Y axis was incorrect when the last Y value was the highest value.
            Date aMaxDate(aScale.NullDate);
            aMaxDate.AddDays(::rtl::math::approxFloor(fMaximum));
            switch (aScale.TimeResolution)
            {
                case css::chart::TimeUnit::MONTH:
                    aMaxDate = DateHelper::GetDateSomeMonthsAway(aMaxDate, 1);
                    break;
                case css::chart::TimeUnit::YEAR:
                    aMaxDate = DateHelper::GetDateSomeYearsAway(aMaxDate, 1);
                    break;
            }
            fMaximum = aMaxDate - aScale.NullDate;
            fMin = m_aMergedMinMaxSupplier.getMinimumAndMaximumYInRange(aScale.Minimum, aScale.Maximum, nAxisIndex).first;
            fMax = m_aMergedMinMaxSupplier.getMinimumAndMaximumYInRange(aScale.Minimum, fMaximum, nAxisIndex).second;
        }
        else
        {
            auto fTmp = m_aMergedMinMaxSupplier.getMinimumAndMaximumYInRange(aScale.Minimum, aScale.Maximum, nAxisIndex);
            fMin = fTmp.first;
            fMax = fTmp.second;
        }
    }
    else if( nDimIndex == 2 )
    {
        // z dimension
        fMin = m_aMergedMinMaxSupplier.getMinimumZ();
        fMax = m_aMergedMinMaxSupplier.getMaximumZ();
    }

    //merge our values with those already contained in rScaleAutomatism
    rScaleAutomatism.expandValueRange( fMin, fMax );

    rScaleAutomatism.setAutoScalingOptions(
        m_aMergedMinMaxSupplier.isExpandBorderToIncrementRhythm( nDimIndex ),
        m_aMergedMinMaxSupplier.isExpandIfValuesCloseToBorder( nDimIndex ),
        m_aMergedMinMaxSupplier.isExpandWideValuesToZero( nDimIndex ),
        m_aMergedMinMaxSupplier.isExpandNarrowValuesTowardZero( nDimIndex ) );

    if (bDateAxisX)
        return;

    VAxisBase* pVAxis = getVAxis(nDimIndex, nAxisIndex);
    if( pVAxis )
        rScaleAutomatism.setMaximumAutoMainIncrementCount( pVAxis->estimateMaximumAutoMainIncrementCount() );
}

VAxisBase* VCoordinateSystem::getVAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
{
    VAxisBase* pRet = nullptr;

    tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );

    tVAxisMap::const_iterator aIt = m_aAxisMap.find( aFullAxisIndex );
    if (aIt != m_aAxisMap.cend())
        pRet = aIt->second.get();

    return pRet;
}

void VCoordinateSystem::setExplicitScaleAndIncrement(
          sal_Int32 nDimensionIndex
        , sal_Int32 nAxisIndex
        , const ExplicitScaleData& rExplicitScale
        , const ExplicitIncrementData& rExplicitIncrement )
{
    impl_adjustDimension( nDimensionIndex );

    if( nAxisIndex==0 )
    {
        m_aExplicitScales[nDimensionIndex]=rExplicitScale;
        m_aExplicitIncrements[nDimensionIndex]=rExplicitIncrement;
    }
    else
    {
        tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
        m_aSecondaryExplicitScales[aFullAxisIndex] = rExplicitScale;
        m_aSecondaryExplicitIncrements[aFullAxisIndex] = rExplicitIncrement;
    }
}

void VCoordinateSystem::set3DWallPositions( CuboidPlanePosition eLeftWallPos, CuboidPlanePosition eBackWallPos, CuboidPlanePosition eBottomPos )
{
    m_eLeftWallPos = eLeftWallPos;
    m_eBackWallPos = eBackWallPos;
    m_eBottomPos = eBottomPos;
}

void VCoordinateSystem::createMaximumAxesLabels()
{
    for (auto const&[unused, pVAxis] : m_aAxisMap)
    {
        (void)unused;
        if (pVAxis)
        {
            if (pVAxis->getDimensionCount() == 2)
                pVAxis->setTransformationSceneToScreen(m_aMatrixSceneToScreen);
            pVAxis->createMaximumLabels();
        }
    }
}
void VCoordinateSystem::createAxesLabels()
{
    for (auto const&[unused, pVAxis] : m_aAxisMap)
    {
        (void)unused;
        if (pVAxis)
        {
            if (pVAxis->getDimensionCount() == 2)
                pVAxis->setTransformationSceneToScreen(m_aMatrixSceneToScreen);
            pVAxis->createLabels();
        }
    }
}

void VCoordinateSystem::updatePositions()
{
    for (auto const&[unused, pVAxis] : m_aAxisMap)
    {
        (void)unused;
        if (pVAxis)
        {
            if (pVAxis->getDimensionCount() == 2)
                pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
            pVAxis->updatePositions();
        }
    }
}

void VCoordinateSystem::createAxesShapes()
{
    for (auto const&[aFullAxisIndex, pVAxis] : m_aAxisMap)
    {
        if (pVAxis)
        {
            auto const&[nDimensionIndex, nAxisIndex] = aFullAxisIndex;

            if (pVAxis->getDimensionCount() == 2)
                pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );

            if (nAxisIndex == 0)
            {
                if (nDimensionIndex == 0)
                {
                    if( m_aExplicitScales[1].AxisType!=AxisType::CATEGORY )
                        pVAxis->setExtraLinePositionAtOtherAxis(
                            m_aExplicitScales[1].Origin );
                }
                else if (nDimensionIndex == 1)
                {
                    if( m_aExplicitScales[0].AxisType!=AxisType::CATEGORY )
                        pVAxis->setExtraLinePositionAtOtherAxis(
                            m_aExplicitScales[0].Origin );
                }
            }

            pVAxis->createShapes();
        }
    }
}
void VCoordinateSystem::createGridShapes()
{
}
void VCoordinateSystem::addMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
{
    m_aMergedMinMaxSupplier.addMinimumAndMaximumSupplier(pMinimumAndMaximumSupplier);
}

bool VCoordinateSystem::hasMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
{
    return m_aMergedMinMaxSupplier.hasMinimumAndMaximumSupplier(pMinimumAndMaximumSupplier);
}

void VCoordinateSystem::clearMinimumAndMaximumSupplierList()
{
    m_aMergedMinMaxSupplier.clearMinimumAndMaximumSupplierList();
}

bool VCoordinateSystem::getPropertySwapXAndYAxis() const
{
    bool bSwapXAndY = false;
    if( m_xCooSysModel.is()) try
    {
        m_xCooSysModel->getPropertyValue( u"SwapXAndYAxis"_ustr ) >>= bSwapXAndY;
    }
    catchconst uno::Exception& )
    {
        TOOLS_WARN_EXCEPTION("chart2""" );
    }
    return bSwapXAndY;
}

bool VCoordinateSystem::needSeriesNamesForAxis() const
{
    return ( m_xCooSysModel.is() && m_xCooSysModel->getDimension() == 3 );
}
void VCoordinateSystem::setSeriesNamesForAxis( const Sequence< OUString >& rSeriesNames )
{
    m_aSeriesNamesForZAxis = rSeriesNames;
}

sal_Int32 VCoordinateSystem::getNumberFormatKeyForAxis(
        const rtl::Reference< Axis >& xAxis
        , const rtl::Reference<::chart::ChartModel>& xChartDoc)
{
    return ChartView::getExplicitNumberFormatKeyForAxis(
                xAxis, m_xCooSysModel, xChartDoc);
}

//namespace chart

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

Messung V0.5
C=93 H=87 G=89

¤ Dauer der Verarbeitung: 0.17 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.