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

Quelle  svdpoev.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 <svx/svdpoev.hxx>
#include <math.h>
#include <svx/svdpagv.hxx>
#include <svx/svdpage.hxx>
#include <svx/svdopath.hxx>
#include <svx/svdundo.hxx>
#include <svx/strings.hrc>
#include <svx/dialmgr.hxx>
#include <svx/svdtrans.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <tools/debug.hxx>
#include <tools/helpers.hxx>

#include <svx/polypolygoneditor.hxx>

using namespace sdr;


void SdrPolyEditView::ImpResetPolyPossibilityFlags()
{
    m_eMarkedPointsSmooth=SdrPathSmoothKind::DontCare;
    m_eMarkedSegmentsKind=SdrPathSegmentKind::DontCare;
    m_bSetMarkedPointsSmoothPossible=false;
    m_bSetMarkedSegmentsKindPossible=false;
}

SdrPolyEditView::SdrPolyEditView(
    SdrModel& rSdrModel,
    OutputDevice* pOut)
:   SdrEditView(rSdrModel, pOut)
{
    ImpResetPolyPossibilityFlags();
}

SdrPolyEditView::~SdrPolyEditView()
{
}

void SdrPolyEditView::ImpCheckPolyPossibilities()
{
    const SdrMarkList& rMarkList = GetMarkedObjectList();
    ImpResetPolyPossibilityFlags();
    const size_t nMarkCount(rMarkList.GetMarkCount());

    if(!nMarkCount || ImpIsFrameHandles())
        return;

    bool b1stSmooth(true);
    bool b1stSegm(true);
    bool bCurve(false);
    bool bSmoothFuz(false);
    bool bSegmFuz(false);
    basegfx::B2VectorContinuity eSmooth = basegfx::B2VectorContinuity::NONE;

    for(size_t nMarkNum = 0; nMarkNum < nMarkCount; ++nMarkNum)
    {
        SdrMark* pM = rMarkList.GetMark(nMarkNum);
        CheckPolyPossibilitiesHelper( pM, b1stSmooth, b1stSegm, bCurve, bSmoothFuz, bSegmFuz, eSmooth );
    }
}

void SdrPolyEditView::CheckPolyPossibilitiesHelper( SdrMark* pM, bool& b1stSmoothbool& b1stSegm, bool& bCurve, bool& bSmoothFuz, bool& bSegmFuz, basegfx::B2VectorContinuity& eSmooth )
{
    SdrObject* pObj = pM->GetMarkedSdrObj();
    SdrPathObj* pPath = dynamic_cast<SdrPathObj*>( pObj );

    if (!pPath)
        return;

    SdrUShortCont& rPts = pM->GetMarkedPoints();
    if (rPts.empty())
        return;

    const bool bClosed(pPath->IsClosed());
    m_bSetMarkedPointsSmoothPossible = true;

    if (bClosed)
    {
        m_bSetMarkedSegmentsKindPossible = true;
    }

    for (const auto& rPt : rPts)
    {
        sal_uInt32 nNum(rPt);
        sal_uInt32 nPolyNum, nPntNum;

        if(PolyPolygonEditor::GetRelativePolyPoint(pPath->GetPathPoly(), nNum, nPolyNum, nPntNum))
        {
            const basegfx::B2DPolygon aLocalPolygon(pPath->GetPathPoly().getB2DPolygon(nPolyNum));
            bool bCanSegment(bClosed || nPntNum < aLocalPolygon.count() - 1);

            if(!m_bSetMarkedSegmentsKindPossible && bCanSegment)
            {
                m_bSetMarkedSegmentsKindPossible = true;
            }

            if(!bSmoothFuz)
            {
                if (b1stSmooth)
                {
                    b1stSmooth = false;
                    eSmooth = basegfx::utils::getContinuityInPoint(aLocalPolygon, nPntNum);
                }
                else
                {
                    bSmoothFuz = (eSmooth != basegfx::utils::getContinuityInPoint(aLocalPolygon, nPntNum));
                }
            }

            if(!bSegmFuz && bCanSegment)
            {
                bool bCrv(aLocalPolygon.isNextControlPointUsed(nPntNum));

                if(b1stSegm)
                {
                    b1stSegm = false;
                    bCurve = bCrv;
                }
                else
                {
                    bSegmFuz = (bCrv != bCurve);
                }
            }
        }
    }

    if(!b1stSmooth && !bSmoothFuz)
    {
        if(basegfx::B2VectorContinuity::NONE == eSmooth)
        {
            m_eMarkedPointsSmooth = SdrPathSmoothKind::Angular;
        }

        if(basegfx::B2VectorContinuity::C1 == eSmooth)
        {
            m_eMarkedPointsSmooth = SdrPathSmoothKind::Asymmetric;
        }

        if(basegfx::B2VectorContinuity::C2 == eSmooth)
        {
            m_eMarkedPointsSmooth = SdrPathSmoothKind::Symmetric;
        }
    }

    if(!b1stSegm && !bSegmFuz)
    {
        m_eMarkedSegmentsKind = bCurve ? SdrPathSegmentKind::Curve : SdrPathSegmentKind::Line;
    }
}

void SdrPolyEditView::SetMarkedPointsSmooth(SdrPathSmoothKind eKind)
{
    basegfx::B2VectorContinuity eFlags;

    if(SdrPathSmoothKind::Angular == eKind)
    {
        eFlags = basegfx::B2VectorContinuity::NONE;
    }
    else if(SdrPathSmoothKind::Asymmetric == eKind)
    {
        eFlags = basegfx::B2VectorContinuity::C1;
    }
    else if(SdrPathSmoothKind::Symmetric == eKind)
    {
        eFlags = basegfx::B2VectorContinuity::C2;
    }
    else
    {
        return;
    }

    if(!HasMarkedPoints())
        return;

    const SdrMarkList& rMarkList = GetMarkedObjectList();
    rMarkList.ForceSort();

    const bool bUndo = IsUndoEnabled();
    if( bUndo )
        BegUndo(SvxResId(STR_EditSetPointsSmooth), rMarkList.GetPointMarkDescription());
    const size_t nMarkCount(rMarkList.GetMarkCount());

    for(size_t nMarkNum(nMarkCount); nMarkNum > 0;)
    {
        --nMarkNum;
        SdrMark* pM = rMarkList.GetMark(nMarkNum);
        SdrPathObj* pPath = dynamic_cast< SdrPathObj* >( pM->GetMarkedSdrObj() );
        if (!pPath)
            continue;

        SdrUShortCont& rPts = pM->GetMarkedPoints();
        PolyPolygonEditor aEditor(pPath->GetPathPoly());
        if (aEditor.SetPointsSmooth(eFlags, rPts))
        {
            if( bUndo )
                AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pPath));
            pPath->SetPathPoly(aEditor.GetPolyPolygon());
        }
    }

    if( bUndo )
        EndUndo();
}

void SdrPolyEditView::SetMarkedSegmentsKind(SdrPathSegmentKind eKind)
{
    if(!HasMarkedPoints())
        return;

    const SdrMarkList& rMarkList = GetMarkedObjectList();
    rMarkList.ForceSort();

    const bool bUndo = IsUndoEnabled();
    if( bUndo )
        BegUndo(SvxResId(STR_EditSetSegmentsKind), rMarkList.GetPointMarkDescription());
    const size_t nMarkCount(rMarkList.GetMarkCount());

    for(size_t nMarkNum=nMarkCount; nMarkNum > 0;)
    {
        --nMarkNum;
        SdrMark* pM = rMarkList.GetMark(nMarkNum);
        SdrPathObj* pPath = dynamic_cast< SdrPathObj* >( pM->GetMarkedSdrObj() );
        if (!pPath)
            continue;
        SdrUShortCont& rPts = pM->GetMarkedPoints();
        PolyPolygonEditor aEditor( pPath->GetPathPoly());
        if (aEditor.SetSegmentsKind(eKind, rPts))
        {
            if( bUndo )
                AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pPath));
            pPath->SetPathPoly(aEditor.GetPolyPolygon());
        }
    }

    if( bUndo )
        EndUndo();
}

bool SdrPolyEditView::IsSetMarkedPointsSmoothPossible() const
{
    ForcePossibilities();
    return m_bSetMarkedPointsSmoothPossible;
}

SdrPathSmoothKind SdrPolyEditView::GetMarkedPointsSmooth() const
{
    ForcePossibilities();
    return m_eMarkedPointsSmooth;
}

bool SdrPolyEditView::IsSetMarkedSegmentsKindPossible() const
{
    ForcePossibilities();
    return m_bSetMarkedSegmentsKindPossible;
}

SdrPathSegmentKind SdrPolyEditView::GetMarkedSegmentsKind() const
{
    ForcePossibilities();
    return m_eMarkedSegmentsKind;
}

bool SdrPolyEditView::IsDeleteMarkedPointsPossible() const
{
    return HasMarkedPoints();
}

void SdrPolyEditView::DeleteMarkedPoints()
{
    if (!HasMarkedPoints())
        return;

    BrkAction();
    const SdrMarkList& rMarkList = GetMarkedObjectList();
    rMarkList.ForceSort();
    const size_t nMarkCount=rMarkList.GetMarkCount();

    const bool bUndo = IsUndoEnabled();
    if( bUndo )
    {
        // Description
        BegUndo(SvxResId(STR_EditDelete),rMarkList.GetPointMarkDescription(),SdrRepeatFunc::Delete);
    }

    for (size_t nMarkNum=nMarkCount; nMarkNum>0;)
    {
        --nMarkNum;
        SdrMark* pM=rMarkList.GetMark(nMarkNum);
        SdrPathObj* pPath = dynamic_cast< SdrPathObj* >( pM->GetMarkedSdrObj() );
        if (!pPath)
            continue;

        SdrUShortCont& rPts = pM->GetMarkedPoints();
        PolyPolygonEditor aEditor( pPath->GetPathPoly());
        if (aEditor.DeletePoints(rPts))
        {
            if( aEditor.GetPolyPolygon().count() )
            {
                if (bUndo)
                    AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pPath));
                pPath->SetPathPoly( aEditor.GetPolyPolygon() );
            }
            else
            {
                if (bUndo)
                    AddUndo(GetModel().GetSdrUndoFactory().CreateUndoDeleteObject(*pPath));
                pM->GetPageView()->GetObjList()->RemoveObject(pPath->GetOrdNum());
            }
        }
    }

    if( bUndo )
        EndUndo();
    UnmarkAllPoints();
    MarkListHasChanged();
}

void SdrPolyEditView::RipUpAtMarkedPoints()
{
    if(!HasMarkedPoints())
        return;

    const SdrMarkList& rMarkList = GetMarkedObjectList();
    rMarkList.ForceSort();
    const size_t nMarkCount(rMarkList.GetMarkCount());

    const bool bUndo = IsUndoEnabled();
    if( bUndo )
        BegUndo(SvxResId(STR_EditRipUp), rMarkList.GetPointMarkDescription());

    for(size_t nMarkNum = nMarkCount; nMarkNum > 0;)
    {
        --nMarkNum;
        SdrMark* pM = rMarkList.GetMark(nMarkNum);
        SdrPathObj* pObj = dynamic_cast<SdrPathObj*>( pM->GetMarkedSdrObj() );
        if (!pObj)
            continue;

        SdrUShortCont& rPts = pM->GetMarkedPoints();

        if (bUndo)
            AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
        bool bCorrectionFlag(false);
        sal_uInt32 nMax(pObj->GetHdlCount());

        for(SdrUShortCont::const_reverse_iterator it = rPts.rbegin(); it != rPts.rend(); ++it)
        {
            sal_uInt32 nNewPt0Idx(0);
            rtl::Reference<SdrPathObj> pNewObj = pObj->RipPoint(*it, nNewPt0Idx);

            if(pNewObj)
            {
                pM->GetPageView()->GetObjList()->InsertObject(pNewObj.get(), pObj->GetOrdNum() + 1);
                if (bUndo)
                    AddUndo(GetModel().GetSdrUndoFactory().CreateUndoNewObject(*pNewObj));
                MarkObj(pNewObj.get(), pM->GetPageView(), falsetrue);
            }

            if(nNewPt0Idx)
            {
                // correction necessary?
                DBG_ASSERT(!bCorrectionFlag,"Multiple index corrections at SdrPolyEditView::RipUp().");
                if(!bCorrectionFlag)
                {
                    bCorrectionFlag = true;

                    SdrUShortCont aReplaceSet;
                    for(const auto& rPt : rPts)
                    {
                        sal_uInt32 nPntNum(rPt);
                        nPntNum += nNewPt0Idx;

                        if(nPntNum >= nMax)
                        {
                            nPntNum -= nMax;
                        }

                        aReplaceSet.insert( static_cast<sal_uInt16>(nPntNum) );
                    }
                    rPts.swap(aReplaceSet);

                    it = rPts.rbegin();
                }
            }
        }
    }

    UnmarkAllPoints();
    if( bUndo )
        EndUndo();
    MarkListHasChanged();
}

bool SdrPolyEditView::IsRipUpAtMarkedPointsPossible() const
{
    bool bRetval(false);
    const SdrMarkList& rMarkList = GetMarkedObjectList();
    const size_t nMarkCount(rMarkList.GetMarkCount());

    for(size_t a = 0; a < nMarkCount; ++a)
    {
        const SdrMark* pMark = rMarkList.GetMark(a);
        const SdrPathObj* pMarkedPathObject = dynamic_castconst SdrPathObj* >(pMark->GetMarkedSdrObj());

        if (!pMarkedPathObject)
            continue;

        const SdrUShortCont& rSelectedPoints = pMark->GetMarkedPoints();
        if (rSelectedPoints.empty())
            continue;

        const basegfx::B2DPolyPolygon& rPathPolyPolygon = pMarkedPathObject->GetPathPoly();

        if(1 == rPathPolyPolygon.count())
        {
            // #i76617# Do not yet use basegfx::B2DPolygon since curve definitions
            // are different and methods need to be changed thoroughly with interaction rework
            const tools::Polygon aPathPolygon(rPathPolyPolygon.getB2DPolygon(0));
            const sal_uInt16 nPointCount(aPathPolygon.GetSize());

            if(nPointCount >= 3)
            {
                bRetval = pMarkedPathObject->IsClosedObj() // #i76617#
                    || std::any_of(rSelectedPoints.begin(), rSelectedPoints.end(),
                        [nPointCount](const sal_uInt16 nMarkedPointNum) {
                            return nMarkedPointNum > 0 && nMarkedPointNum < nPointCount - 1;
                        });
            }
        }
    }

    return bRetval;
}

bool SdrPolyEditView::IsOpenCloseMarkedObjectsPossible() const
{
    bool bRetval(false);
    const SdrMarkList& rMarkList = GetMarkedObjectList();
    const size_t nMarkCount(rMarkList.GetMarkCount());

    for(size_t a = 0; a < nMarkCount; ++a)
    {
        const SdrMark* pMark = rMarkList.GetMark(a);
        const SdrPathObj* pMarkedPathObject = dynamic_castconst SdrPathObj* >(pMark->GetMarkedSdrObj());

        if(pMarkedPathObject)
        {
            // #i76617# Do not yet use basegfx::B2DPolygon since curve definitions
            // are different and methods need to be changed thoroughly with interaction rework
            const tools::PolyPolygon aPathPolyPolygon(pMarkedPathObject->GetPathPoly());
            const sal_uInt16 nPolygonCount(aPathPolyPolygon.Count());

            for(sal_uInt16 b(0); !bRetval && b < nPolygonCount; b++)
            {
                const tools::Polygon& rPathPolygon = aPathPolyPolygon[b];
                const sal_uInt16 nPointCount(rPathPolygon.GetSize());

                bRetval = (nPointCount >= 3);
            }
        }
    }

    return bRetval;
}

SdrObjClosedKind SdrPolyEditView::GetMarkedObjectsClosedState() const
{
    bool bOpen(false);
    bool bClosed(false);
    const SdrMarkList& rMarkList = GetMarkedObjectList();
    const size_t nMarkCount(rMarkList.GetMarkCount());

    for(size_t a = 0; !(bOpen && bClosed) && a < nMarkCount; ++a)
    {
        const SdrMark* pMark = rMarkList.GetMark(a);
        const SdrPathObj* pMarkedPathObject = dynamic_castconst SdrPathObj* >(pMark->GetMarkedSdrObj());

        if(pMarkedPathObject)
        {
            if(pMarkedPathObject->IsClosedObj())
            {
                bClosed = true;
            }
            else
            {
                bOpen = true;
            }
        }
    }

    if(bOpen && bClosed)
    {
        return SdrObjClosedKind::DontCare;
    }
    else if(bOpen)
    {
        return SdrObjClosedKind::Open;
    }
    else
    {
        return SdrObjClosedKind::Closed;
    }
}

void SdrPolyEditView::ImpTransformMarkedPoints(PPolyTrFunc pTrFunc, const void* p1, const void* p2, const void* p3, const void* p4)
{
    const bool bUndo = IsUndoEnabled();

    const SdrMarkList& rMarkList = GetMarkedObjectList();
    const size_t nMarkCount=rMarkList.GetMarkCount();
    for (size_t nm=0; nm<nMarkCount; ++nm)
    {
        SdrMark* pM=rMarkList.GetMark(nm);
        SdrObject* pObj=pM->GetMarkedSdrObj();
        SdrPathObj* pPath=dynamic_cast<SdrPathObj*>( pObj );
        if (!pPath)
            continue;

        const SdrUShortCont& rPts = pM->GetMarkedPoints();
        if (rPts.empty())
            continue;

        if( bUndo )
            AddUndo(GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pObj));

        basegfx::B2DPolyPolygon aXPP(pPath->GetPathPoly());

        for (const auto& rPt : rPts)
        {
            sal_uInt32 nPt = rPt;
            sal_uInt32 nPolyNum, nPointNum;

            if(PolyPolygonEditor::GetRelativePolyPoint(aXPP, nPt, nPolyNum, nPointNum))
            {
                //#i83671# used nLocalPointNum (which was the polygon point count)
                // instead of the point index (nPointNum). This of course led
                // to a wrong point access to the B2DPolygon.
                basegfx::B2DPolygon aNewXP(aXPP.getB2DPolygon(nPolyNum));
                Point aPos, aC1, aC2;
                bool bC1(false);
                bool bC2(false);

                const basegfx::B2DPoint aB2DPos(aNewXP.getB2DPoint(nPointNum));
                aPos = Point(basegfx::fround<tools::Long>(aB2DPos.getX()),
                             basegfx::fround<tools::Long>(aB2DPos.getY()));

                if(aNewXP.isPrevControlPointUsed(nPointNum))
                {
                    const basegfx::B2DPoint aB2DC1(aNewXP.getPrevControlPoint(nPointNum));
                    aC1 = Point(basegfx::fround<tools::Long>(aB2DC1.getX()),
                                basegfx::fround<tools::Long>(aB2DC1.getY()));
                    bC1 = true;
                }

                if(aNewXP.isNextControlPointUsed(nPointNum))
                {
                    const basegfx::B2DPoint aB2DC2(aNewXP.getNextControlPoint(nPointNum));
                    aC2 = Point(basegfx::fround<tools::Long>(aB2DC2.getX()),
                                basegfx::fround<tools::Long>(aB2DC2.getY()));
                    bC2 = true;
                }

                (*pTrFunc)(aPos,&aC1,&aC2,p1,p2,p3,p4);
                aNewXP.setB2DPoint(nPointNum, basegfx::B2DPoint(aPos.X(), aPos.Y()));

                if (bC1)
                {
                    aNewXP.setPrevControlPoint(nPointNum, basegfx::B2DPoint(aC1.X(), aC1.Y()));
                }

                if (bC2)
                {
                    aNewXP.setNextControlPoint(nPointNum, basegfx::B2DPoint(aC2.X(), aC2.Y()));
                }

                aXPP.setB2DPolygon(nPolyNum, aNewXP);
            }
        }

        pPath->SetPathPoly(aXPP);
    }
}


static void ImpMove(Point& rPt, Point* pC1, Point* pC2, const void* p1, const void/*p2*/, const void* /*p3*/, const void* /*p4*/)
{
    rPt.Move(*static_cast<const Size*>(p1));
    if (pC1!=nullptr) pC1->Move(*static_cast<const Size*>(p1));
    if (pC2!=nullptr) pC2->Move(*static_cast<const Size*>(p1));
}

void SdrPolyEditView::MoveMarkedPoints(const Size& rSiz)
{
    ForceUndirtyMrkPnt();
    OUString aStr(SvxResId(STR_EditMove));
    const SdrMarkList& rMarkList = GetMarkedObjectList();
    BegUndo(aStr,rMarkList.GetPointMarkDescription(),SdrRepeatFunc::Move);
    ImpTransformMarkedPoints(ImpMove,&rSiz);
    EndUndo();
    AdjustMarkHdl();
}

static void ImpResize(Point& rPt, Point* pC1, Point* pC2, const void* p1, const void* p2, const void* p3, const void/*p4*/)
{
    ResizePoint(rPt,*static_cast<const Point*>(p1),*static_cast<const Fraction*>(p2),*static_cast<const Fraction*>(p3));
    if (pC1!=nullptr) ResizePoint(*pC1,*static_cast<const Point*>(p1),*static_cast<const Fraction*>(p2),*static_cast<const Fraction*>(p3));
    if (pC2!=nullptr) ResizePoint(*pC2,*static_cast<const Point*>(p1),*static_cast<const Fraction*>(p2),*static_cast<const Fraction*>(p3));
}

void SdrPolyEditView::ResizeMarkedPoints(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
{
    ForceUndirtyMrkPnt();
    OUString aStr(SvxResId(STR_EditResize));
    const SdrMarkList& rMarkList = GetMarkedObjectList();
    BegUndo(aStr,rMarkList.GetPointMarkDescription(),SdrRepeatFunc::Resize);
    ImpTransformMarkedPoints(ImpResize,&rRef,&xFact,&yFact);
    EndUndo();
    AdjustMarkHdl();
}

static void ImpRotate(Point& rPt, Point* pC1, Point* pC2, const void* p1, const void/*p2*/, const void* p3, const void* p4)
{
    RotatePoint(rPt,*static_cast<const Point*>(p1),*static_cast<const double*>(p3),*static_cast<const double*>(p4));
    if (pC1!=nullptr) RotatePoint(*pC1,*static_cast<const Point*>(p1),*static_cast<const double*>(p3),*static_cast<const double*>(p4));
    if (pC2!=nullptr) RotatePoint(*pC2,*static_cast<const Point*>(p1),*static_cast<const double*>(p3),*static_cast<const double*>(p4));
}

void SdrPolyEditView::RotateMarkedPoints(const Point& rRef, Degree100 nAngle)
{
    ForceUndirtyMrkPnt();
    OUString aStr(SvxResId(STR_EditResize));
    const SdrMarkList& rMarkList = GetMarkedObjectList();
    BegUndo(aStr,rMarkList.GetPointMarkDescription(),SdrRepeatFunc::Rotate);
    double nSin = sin(toRadians(nAngle));
    double nCos = cos(toRadians(nAngle));
    ImpTransformMarkedPoints(ImpRotate,&rRef,&nAngle,&nSin,&nCos);
    EndUndo();
    AdjustMarkHdl();
}

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

Messung V0.5
C=98 H=93 G=95

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