View | Details | Raw Unified | Return to issue 115917
Collapse All | Expand All

(-)source/generic/poly.cxx (-9 / +37 lines)
Lines 2106-2112 Link Here
2106
}
2106
}
2107
2107
2108
// -----------------------------------------------------------------------
2108
// -----------------------------------------------------------------------
2109
// #i74631# numerical correction method for B2DPolygon
2109
// numerical correction method for B2DPolygon
2110
void impCorrectContinuity(basegfx::B2DPolygon& roPolygon, sal_uInt32 nIndex, sal_uInt8 nCFlag)
2110
void impCorrectContinuity(basegfx::B2DPolygon& roPolygon, sal_uInt32 nIndex, sal_uInt8 nCFlag)
2111
{
2111
{
2112
	const sal_uInt32 nPointCount(roPolygon.count());
2112
	const sal_uInt32 nPointCount(roPolygon.count());
Lines 2116-2136 Link Here
2116
	{
2116
	{
2117
		if(roPolygon.isPrevControlPointUsed(nIndex) && roPolygon.isNextControlPointUsed(nIndex))
2117
		if(roPolygon.isPrevControlPointUsed(nIndex) && roPolygon.isNextControlPointUsed(nIndex))
2118
		{
2118
		{
2119
            // #115917# Patch from osnola
2120
            //
2121
            // The correction is needed because an integer polygon with control points
2122
            // is converted to double precision. When C1 or C2 is used the involved vectors
2123
            // may not have the same directions/lengths since these come from integer coordinates
2124
            //  and may have been snapped to different nearest integer coordinates. The snap error
2125
            // is in the range of +-1 in y and y, thus 0.0 <= error <= sqrt(2.0). Nonetheless,
2126
            // it needs to be corrected to be able to detect the continuity in this points
2127
            // correctly.
2128
            //
2129
            // We only have the integer data here (already in double precision form, but no mantisses 
2130
            // used), so the best correction is to use:
2131
            //
2132
            // for C1: The longest vector since it potentially has best preserved the original vector.
2133
            //         Even better the sum of the vectors, weighted by their length. This gives the
2134
            //         normal vector addition to get the vector itself, lengths need to be preserved.
2135
            // for C2: The mediated vector(s) since both should be the same, but mirrored
2136
2137
            // extract the point and vectors
2119
			const basegfx::B2DPoint aPoint(roPolygon.getB2DPoint(nIndex));
2138
			const basegfx::B2DPoint aPoint(roPolygon.getB2DPoint(nIndex));
2139
            const basegfx::B2DVector aNext(roPolygon.getNextControlPoint(nIndex) - aPoint);
2140
            const basegfx::B2DVector aPrev(aPoint - roPolygon.getPrevControlPoint(nIndex));
2120
2141
2142
            // calculate common direction vector, normalize
2143
            basegfx::B2DVector aDirection(aNext + aPrev);
2144
            aDirection.normalize();
2145
2121
			if(POLY_SMOOTH == nCFlag)
2146
			if(POLY_SMOOTH == nCFlag)
2122
			{
2147
			{
2123
				// C1: apply inverse direction of prev to next, keep length of next
2148
                // C1: apply common direction vector, preserve individual lengths
2124
				const basegfx::B2DVector aOriginalNext(roPolygon.getNextControlPoint(nIndex) - aPoint);
2149
				roPolygon.setNextControlPoint(nIndex, basegfx::B2DPoint(aPoint + (aDirection * aNext.getLength())));
2125
				basegfx::B2DVector aNewNext(aPoint - roPolygon.getPrevControlPoint(nIndex));
2150
				roPolygon.setPrevControlPoint(nIndex, basegfx::B2DPoint(aPoint - (aDirection * aPrev.getLength())));
2126
2127
				aNewNext.setLength(aOriginalNext.getLength());
2128
				roPolygon.setNextControlPoint(nIndex, basegfx::B2DPoint(aPoint + aNewNext));
2129
			}
2151
			}
2130
			else // POLY_SYMMTR
2152
			else // POLY_SYMMTR
2131
			{
2153
			{
2132
				// C2: apply inverse control point to next
2154
                // C2: get mediated length. Taking half of the unnormalized direction would be
2133
				roPolygon.setNextControlPoint(nIndex, (2.0 * aPoint) - roPolygon.getPrevControlPoint(nIndex));
2155
                // an approximation, but not correct.
2156
                const double fMedLength((aNext.getLength() + aPrev.getLength()) * 0.5);
2157
2158
                // Bring Direction to correct length and apply
2159
                aDirection *= fMedLength;
2160
				roPolygon.setNextControlPoint(nIndex, basegfx::B2DPoint(aPoint + aDirection));
2161
				roPolygon.setPrevControlPoint(nIndex, basegfx::B2DPoint(aPoint - aDirection));
2134
			}
2162
			}
2135
		}
2163
		}
2136
	}
2164
	}

Return to issue 115917