/* -*- 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 .
*/
sal_uInt32 getIndexOfSuccessor(sal_uInt32 nIndex, const B3DPolygon& rCandidate)
{
OSL_ENSURE(nIndex < rCandidate.count(), "getIndexOfPredecessor: Access to polygon out of range (!)");
staticvoid implHandleFirstLast( const std::function<void(const basegfx::B3DPolygon& rSnippet)>& rTargetCallback,
B3DPolygon& rFirst,
B3DPolygon& rLast)
{ if(rFirst.count() && rLast.count()
&& rFirst.getB3DPoint(0).equal(rLast.getB3DPoint(rLast.count() - 1)))
{ // start of first and end of last are the same -> merge them
rLast.append(rFirst);
rLast.removeDoublePoints();
rFirst.clear();
}
if(fDotDashLength <= 0.0 || !rLineTargetCallback || !nPointCount)
{ // parameters make no sense, just add source to targets if (rLineTargetCallback)
rLineTargetCallback(rCandidate); return;
}
// precalculate maximal acceptable length of candidate polygon assuming // we want to create a maximum of fNumberOfAllowedSnippets. In 3D // use less for fNumberOfAllowedSnippets, ca. 6553.6, double due to line & gap. // Less in 3D due to potentially blowing up to rounded line segments. staticconstdouble fNumberOfAllowedSnippets(6553.5 * 2.0); constdouble fAllowedLength((fNumberOfAllowedSnippets * fDotDashLength) / double(rDotDashArray.size())); constdouble fCandidateLength(basegfx::utils::getLength(rCandidate));
std::vector<double> aDotDashArray(rDotDashArray);
if(fCandidateLength > fAllowedLength)
{ // we would produce more than fNumberOfAllowedSnippets, so // adapt aDotDashArray to exactly produce assumed number. Also // assert this to let the caller know about it. // If this asserts: Please think about checking your DotDashArray // before calling this function or evtl. use the callback version // to *not* produce that much of data. Even then, you may still // think about producing too much runtime (!)
assert(true && "applyLineDashing: potentially too expensive to do the requested dismantle - please consider stretched LineDash pattern (!)");
// calculate correcting factor, apply to aDotDashArray and fDotDashLength // to enlarge these as needed constdouble fFactor(fCandidateLength / fAllowedLength);
std::for_each(aDotDashArray.begin(), aDotDashArray.end(), [&fFactor](double &f){ f *= fFactor; });
}
if(bChangeX || bChangeY)
{ // create texture coordinates using sphere projection to cartesian coordinates, // use object's center as base constdouble fOne(1.0); const sal_uInt32 nPointCount(aRetval.count()); bool bPolarPoints(false);
sal_uInt32 a;
// create center cartesian coordinates to have a possibility to decide if on boundary // transitions which value to choose const B3DRange aPlaneRange(getRange(rCandidate)); const B3DPoint aPlaneCenter(aPlaneRange.getCenter() - rCenter); constdouble fXCenter(fOne - ((atan2(aPlaneCenter.getZ(), aPlaneCenter.getX()) + M_PI) / (2 * M_PI)));
if(fTools::equalZero(fY))
{ // point is a north polar point, no useful X-coordinate can be created. if(bChangeY)
{
aTexCoor.setY(0.0);
if(bChangeX)
{
bPolarPoints = true;
}
}
} elseif(fTools::equal(fY, fOne))
{ // point is a south polar point, no useful X-coordinate can be created. Set // Y-coordinate, though if(bChangeY)
{
aTexCoor.setY(fOne);
// correct cartesian point coordinate dependent from center value if(fX > fXCenter + 0.5)
{
fX -= fOne;
} elseif(fX < fXCenter - 0.5)
{
fX += fOne;
}
if(bChangeX)
{
aTexCoor.setX(fX);
}
if(bChangeY)
{
aTexCoor.setY(fY);
}
}
aRetval.setTextureCoordinate(a, aTexCoor);
}
if(bPolarPoints)
{ // correct X-texture coordinates if polar points are contained. Those // coordinates cannot be correct, so use prev or next X-coordinate for(a = 0; a < nPointCount; a++)
{
B2DPoint aTexCoor(aRetval.getTextureCoordinate(a));
if(fTools::equalZero(aTexCoor.getY()) || fTools::equal(aTexCoor.getY(), fOne))
{ // get prev, next TexCoor and test for pole const B2DPoint aPrevTexCoor(aRetval.getTextureCoordinate(a ? a - 1 : nPointCount - 1)); const B2DPoint aNextTexCoor(aRetval.getTextureCoordinate((a + 1) % nPointCount)); constbool bPrevPole(fTools::equalZero(aPrevTexCoor.getY()) || fTools::equal(aPrevTexCoor.getY(), fOne)); constbool bNextPole(fTools::equalZero(aNextTexCoor.getY()) || fTools::equal(aNextTexCoor.getY(), fOne));
if(!bPrevPole && !bNextPole)
{ // both no poles, mix them
aTexCoor.setX((aPrevTexCoor.getX() + aNextTexCoor.getX()) / 2.0);
} elseif(!bNextPole)
{ // copy next
aTexCoor.setX(aNextTexCoor.getX());
} else
{ // copy prev, even if it's a pole, hopefully it is already corrected
aTexCoor.setX(aPrevTexCoor.getX());
}
if(fAbsX > fAbsY && fAbsX > fAbsZ)
{ // normal points mostly in X-Direction, use YZ-Polygon projection for check // x -> y, y -> z for(sal_uInt32 a(0); a < nPointCount; a++)
{ const B3DPoint aPreviousPoint(aCurrentPoint);
aCurrentPoint = rCandidate.getB3DPoint(a);
// cross-over in Z? constbool bCompZA(fTools::more(aPreviousPoint.getZ(), rPoint.getZ())); constbool bCompZB(fTools::more(aCurrentPoint.getZ(), rPoint.getZ()));
// snap points of horizontal or vertical edges to discrete values
B3DPolygon snapPointsOfHorizontalOrVerticalEdges(const B3DPolygon& rCandidate)
{ const sal_uInt32 nPointCount(rCandidate.count());
if(nPointCount > 1)
{ // Start by copying the source polygon to get a writeable copy. The closed state is // copied by aRetval's initialisation, too, so no need to copy it in this method
B3DPolygon aRetval(rCandidate);
// prepare geometry data. Get rounded from original
B3ITuple aPrevTuple(basegfx::fround(rCandidate.getB3DPoint(nPointCount - 1)));
B3DPoint aCurrPoint(rCandidate.getB3DPoint(0));
B3ITuple aCurrTuple(basegfx::fround(aCurrPoint));
// loop over all points. This will also snap the implicit closing edge // even when not closed, but that's no problem here for(sal_uInt32 a(0); a < nPointCount; a++)
{ // get next point. Get rounded from original constbool bLastRun(a + 1 == nPointCount); const sal_uInt32 nNextIndex(bLastRun ? 0 : a + 1); const B3DPoint aNextPoint(rCandidate.getB3DPoint(nNextIndex)); const B3ITuple aNextTuple(basegfx::fround(aNextPoint));
// get the states constbool bPrevVertical(aPrevTuple.getX() == aCurrTuple.getX()); constbool bNextVertical(aNextTuple.getX() == aCurrTuple.getX()); constbool bPrevHorizontal(aPrevTuple.getY() == aCurrTuple.getY()); constbool bNextHorizontal(aNextTuple.getY() == aCurrTuple.getY()); constbool bSnapX(bPrevVertical || bNextVertical); constbool bSnapY(bPrevHorizontal || bNextHorizontal);
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.