Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/drawinglayer/source/primitive2d/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 14 kB image not shown  

Quelle  gridprimitive2d.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 <drawinglayer/primitive2d/gridprimitive2d.hxx>
#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
#include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <utility>


using namespace com::sun::star;


namespace drawinglayer::primitive2d
{
        Primitive2DReference GridPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
        {
            if(!(!rViewInformation.getViewport().isEmpty() && getWidth() > 0.0 && getHeight() > 0.0))
                return nullptr;

            // decompose grid matrix to get logic size
            basegfx::B2DVector aScale, aTranslate;
            double fRotate, fShearX;
            getTransform().decompose(aScale, aTranslate, fRotate, fShearX);

            // create grid matrix which transforms from scaled logic to view
            basegfx::B2DHomMatrix aRST(basegfx::utils::createShearXRotateTranslateB2DHomMatrix(
                fShearX, fRotate, aTranslate.getX(), aTranslate.getY()));
            aRST *= rViewInformation.getObjectToViewTransformation();

            // get step widths
            double fStepX(getWidth());
            double fStepY(getHeight());
            const double fMinimalStep(10.0);

            // guarantee a step width of 10.0
            if(basegfx::fTools::less(fStepX, fMinimalStep))
            {
                fStepX = fMinimalStep;
            }

            if(basegfx::fTools::less(fStepY, fMinimalStep))
            {
                fStepY = fMinimalStep;
            }

            // get relative distances in view coordinates
            double fViewStepX((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(fStepX, 0.0)).getLength());
            double fViewStepY((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(0.0, fStepY)).getLength());
            double fSmallStepX(1.0), fViewSmallStepX(1.0), fSmallStepY(1.0), fViewSmallStepY(1.0);
            sal_uInt32 nSmallStepsX(0), nSmallStepsY(0);

            // setup subdivisions
            if(getSubdivisionsX())
            {
                fSmallStepX = fStepX / getSubdivisionsX();
                fViewSmallStepX = fViewStepX / getSubdivisionsX();
            }

            if(getSubdivisionsY())
            {
                fSmallStepY = fStepY / getSubdivisionsY();
                fViewSmallStepY = fViewStepY / getSubdivisionsY();
            }

            // correct step width
            while(fViewStepX < getSmallestViewDistance())
            {
                fViewStepX *= 2.0;
                fStepX *= 2.0;
            }

            while(fViewStepY < getSmallestViewDistance())
            {
                fViewStepY *= 2.0;
                fStepY *= 2.0;
            }

            // correct small step width
            if(getSubdivisionsX())
            {
                while(fViewSmallStepX < getSmallestSubdivisionViewDistance())
                {
                    fViewSmallStepX *= 2.0;
                    fSmallStepX *= 2.0;
                }

                nSmallStepsX = static_cast<sal_uInt32>(fStepX / fSmallStepX);
            }

            if(getSubdivisionsY())
            {
                while(fViewSmallStepY < getSmallestSubdivisionViewDistance())
                {
                    fViewSmallStepY *= 2.0;
                    fSmallStepY *= 2.0;
                }

                nSmallStepsY = static_cast<sal_uInt32>(fStepY / fSmallStepY);
            }

            // calculate extended viewport in which grid points may lie at all
            basegfx::B2DRange aExtendedViewport;

            if(rViewInformation.getDiscreteViewport().isEmpty())
            {
                // not set, use logic size to travel over all potential grid points
                aExtendedViewport = basegfx::B2DRange(0.0, 0.0, aScale.getX(), aScale.getY());
            }
            else
            {
                // transform unit range to discrete view
                aExtendedViewport = basegfx::B2DRange(0.0, 0.0, 1.0, 1.0);
                basegfx::B2DHomMatrix aTrans(rViewInformation.getObjectToViewTransformation() * getTransform());
                aExtendedViewport.transform(aTrans);

                // intersect with visible part
                aExtendedViewport.intersect(rViewInformation.getDiscreteViewport());

                if(!aExtendedViewport.isEmpty())
                {
                    // convert back and apply scale
                    aTrans.invert();
                    aTrans.scale(aScale.getX(), aScale.getY());
                    aExtendedViewport.transform(aTrans);

                    // crop start/end in X/Y to multiples of logical step width
                    const double fHalfCrossSize((rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(3.0, 0.0)).getLength());
                    const double fMinX(floor((aExtendedViewport.getMinX() - fHalfCrossSize) / fStepX) * fStepX);
                    const double fMaxX(ceil((aExtendedViewport.getMaxX() + fHalfCrossSize) / fStepX) * fStepX);
                    const double fMinY(floor((aExtendedViewport.getMinY() - fHalfCrossSize) / fStepY) * fStepY);
                    const double fMaxY(ceil((aExtendedViewport.getMaxY() + fHalfCrossSize) / fStepY) * fStepY);

                    // put to aExtendedViewport and crop on object logic size
                    aExtendedViewport = basegfx::B2DRange(
                        std::max(fMinX, 0.0),
                        std::max(fMinY, 0.0),
                        std::min(fMaxX, aScale.getX()),
                        std::min(fMaxY, aScale.getY()));
                }
            }

            if(aExtendedViewport.isEmpty())
                return nullptr;

            // prepare point vectors for point and cross markers
            std::vector< basegfx::B2DPoint > aPositionsPoint;
            std::vector< basegfx::B2DPoint > aPositionsCross;

            for(double fX(aExtendedViewport.getMinX()); fX < aExtendedViewport.getMaxX(); fX += fStepX)
            {
                const bool bXZero(basegfx::fTools::equalZero(fX));

                for(double fY(aExtendedViewport.getMinY()); fY < aExtendedViewport.getMaxY(); fY += fStepY)
                {
                    const bool bYZero(basegfx::fTools::equalZero(fY));

                    if(!bXZero && !bYZero)
                    {
                        // get discrete position and test against 3x3 area surrounding it
                        // since it's a cross
                        const double fHalfCrossSize(3.0 * 0.5);
                        const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fX, fY));
                        const basegfx::B2DRange aDiscreteRangeCross(
                            aViewPos.getX() - fHalfCrossSize, aViewPos.getY() - fHalfCrossSize,
                            aViewPos.getX() + fHalfCrossSize, aViewPos.getY() + fHalfCrossSize);

                        if(rViewInformation.getDiscreteViewport().overlaps(aDiscreteRangeCross))
                        {
                            const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos);
                            aPositionsCross.push_back(aLogicPos);
                        }
                    }

                    if(getSubdivisionsX() && !bYZero)
                    {
                        double fF(fX + fSmallStepX);

                        for(sal_uInt32 a(1); a < nSmallStepsX && fF < aExtendedViewport.getMaxX(); a++, fF += fSmallStepX)
                        {
                            const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fF, fY));

                            if(rViewInformation.getDiscreteViewport().isInside(aViewPos))
                            {
                                const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos);
                                aPositionsPoint.push_back(aLogicPos);
                            }
                        }
                    }

                    if(getSubdivisionsY() && !bXZero)
                    {
                        double fF(fY + fSmallStepY);

                        for(sal_uInt32 a(1); a < nSmallStepsY && fF < aExtendedViewport.getMaxY(); a++, fF += fSmallStepY)
                        {
                            const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fX, fF));

                            if(rViewInformation.getDiscreteViewport().isInside(aViewPos))
                            {
                                const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos);
                                aPositionsPoint.push_back(aLogicPos);
                            }
                        }
                    }
                }
            }

            // prepare return value
            const sal_uInt32 nCountPoint(aPositionsPoint.size());
            const sal_uInt32 nCountCross(aPositionsCross.size());

            // add PointArrayPrimitive2D if point markers were added
            Primitive2DContainer aContainer;
            if(nCountPoint)
            {
                aContainer.push_back(new PointArrayPrimitive2D(std::move(aPositionsPoint), getBColor()));
            }

            // add MarkerArrayPrimitive2D if cross markers were added
            if(!nCountCross)
                return new GroupPrimitive2D(std::move(aContainer));

            if(!getSubdivisionsX() && !getSubdivisionsY())
            {
                // no subdivisions, so fall back to points at grid positions, no need to
                // visualize a difference between divisions and sub-divisions
                aContainer.push_back(new PointArrayPrimitive2D(std::move(aPositionsCross), getBColor()));
            }
            else
            {
                aContainer.push_back(new MarkerArrayPrimitive2D(std::move(aPositionsCross), getCrossMarker()));
            }
            return new GroupPrimitive2D(std::move(aContainer));
        }

        GridPrimitive2D::GridPrimitive2D(
            basegfx::B2DHomMatrix aTransform,
            double fWidth,
            double fHeight,
            double fSmallestViewDistance,
            double fSmallestSubdivisionViewDistance,
            sal_uInt32 nSubdivisionsX,
            sal_uInt32 nSubdivisionsY,
            const basegfx::BColor& rBColor,
            const BitmapEx& rCrossMarker)
        :   maTransform(std::move(aTransform)),
            mfWidth(fWidth),
            mfHeight(fHeight),
            mfSmallestViewDistance(fSmallestViewDistance),
            mfSmallestSubdivisionViewDistance(fSmallestSubdivisionViewDistance),
            mnSubdivisionsX(nSubdivisionsX),
            mnSubdivisionsY(nSubdivisionsY),
            maBColor(rBColor),
            maCrossMarker(rCrossMarker)
        {
        }

        bool GridPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
        {
            if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
            {
                const GridPrimitive2D& rCompare = static_cast<const GridPrimitive2D&>(rPrimitive);

                return (getTransform() == rCompare.getTransform()
                    && getWidth() == rCompare.getWidth()
                    && getHeight() == rCompare.getHeight()
                    && getSmallestViewDistance() == rCompare.getSmallestViewDistance()
                    && getSmallestSubdivisionViewDistance() == rCompare.getSmallestSubdivisionViewDistance()
                    && getSubdivisionsX() == rCompare.getSubdivisionsX()
                    && getSubdivisionsY() == rCompare.getSubdivisionsY()
                    && getBColor() == rCompare.getBColor()
                    && getCrossMarker() == rCompare.getCrossMarker());
            }

            return false;
        }

        basegfx::B2DRange GridPrimitive2D::getB2DRange(const geometry::ViewInformation2D&&nbsp;rViewInformation) const
        {
            // get object's range
            basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
            aUnitRange.transform(getTransform());

            // intersect with visible part
            aUnitRange.intersect(rViewInformation.getViewport());

            return aUnitRange;
        }

        void GridPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const
        {
            if(hasBuffered2DDecomposition())
            {
                if(maLastViewport != rViewInformation.getViewport() || maLastObjectToViewTransformation != rViewInformation.getObjectToViewTransformation())
                {
                    // conditions of last local decomposition have changed, delete
                    const_cast< GridPrimitive2D* >(this)->setBuffered2DDecomposition(nullptr);
                }
            }

            if(!hasBuffered2DDecomposition())
            {
                // remember ViewRange and ViewTransformation
                const_cast< GridPrimitive2D* >(this)->maLastObjectToViewTransformation = rViewInformation.getObjectToViewTransformation();
                const_cast< GridPrimitive2D* >(this)->maLastViewport = rViewInformation.getViewport();
            }

            // use parent implementation
            BufferedDecompositionPrimitive2D::get2DDecomposition(rVisitor, rViewInformation);
        }

        // provide unique ID
        sal_uInt32 GridPrimitive2D::getPrimitive2DID() const
        {
            return PRIMITIVE2D_ID_GRIDPRIMITIVE2D;
        }

// end of namespace

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

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

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