Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
21 : #include <osl/diagnose.h>
22 : #include <basegfx/numeric/ftools.hxx>
23 : #include <basegfx/point/b2dpoint.hxx>
24 : #include <basegfx/vector/b2dvector.hxx>
25 : #include <basegfx/range/b2drange.hxx>
26 : #include <basegfx/polygon/b2dpolygontools.hxx>
27 : #include <basegfx/polygon/b2dpolypolygontools.hxx>
28 : #include <basegfx/curve/b2dcubicbezier.hxx>
29 :
30 : #include <vector>
31 : #include <algorithm>
32 :
33 : #define SUBDIVIDE_FOR_CUT_TEST_COUNT (50)
34 :
35 : namespace basegfx
36 : {
37 : namespace
38 : {
39 :
40 28112 : class temporaryPoint
41 : {
42 : B2DPoint maPoint; // the new point
43 : sal_uInt32 mnIndex; // index after which to insert
44 : double mfCut; // parametric cut description [0.0 .. 1.0]
45 :
46 : public:
47 5664 : temporaryPoint(const B2DPoint& rNewPoint, sal_uInt32 nIndex, double fCut)
48 : : maPoint(rNewPoint),
49 : mnIndex(nIndex),
50 5664 : mfCut(fCut)
51 : {
52 5664 : }
53 :
54 2917 : bool operator<(const temporaryPoint& rComp) const
55 : {
56 2917 : if(mnIndex == rComp.mnIndex)
57 : {
58 593 : return (mfCut < rComp.mfCut);
59 : }
60 :
61 2324 : return (mnIndex < rComp.mnIndex);
62 : }
63 :
64 3396 : const B2DPoint& getPoint() const { return maPoint; }
65 7814 : sal_uInt32 getIndex() const { return mnIndex; }
66 857 : double getCut() const { return mfCut; }
67 : };
68 :
69 : typedef ::std::vector< temporaryPoint > temporaryPointVector;
70 :
71 4386 : class temporaryPolygonData
72 : {
73 : B2DPolygon maPolygon;
74 : B2DRange maRange;
75 : temporaryPointVector maPoints;
76 :
77 : public:
78 51975 : const B2DPolygon& getPolygon() const { return maPolygon; }
79 2193 : void setPolygon(const B2DPolygon& rNew) { maPolygon = rNew; maRange = tools::getRange(maPolygon); }
80 86988 : const B2DRange& getRange() const { return maRange; }
81 35381 : temporaryPointVector& getTemporaryPointVector() { return maPoints; }
82 : };
83 :
84 7697 : B2DPolygon mergeTemporaryPointsAndPolygon(const B2DPolygon& rCandidate, temporaryPointVector& rTempPoints)
85 : {
86 : // #i76891# mergeTemporaryPointsAndPolygon redesigned to be able to correctly handle
87 : // single edges with/without control points
88 : // #i101491# added counter for non-changing element count
89 7697 : const sal_uInt32 nTempPointCount(rTempPoints.size());
90 :
91 7697 : if(nTempPointCount)
92 : {
93 1461 : B2DPolygon aRetval;
94 1461 : const sal_uInt32 nCount(rCandidate.count());
95 :
96 1461 : if(nCount)
97 : {
98 : // sort temp points to assure increasing fCut values and increasing indices
99 1461 : ::std::sort(rTempPoints.begin(), rTempPoints.end());
100 :
101 : // prepare loop
102 1461 : B2DCubicBezier aEdge;
103 1461 : sal_uInt32 nNewInd(0L);
104 :
105 : // add start point
106 1461 : aRetval.append(rCandidate.getB2DPoint(0));
107 :
108 9413 : for(sal_uInt32 a(0L); a < nCount; a++)
109 : {
110 : // get edge
111 7952 : rCandidate.getBezierSegment(a, aEdge);
112 :
113 7952 : if(aEdge.isBezier())
114 : {
115 : // control vectors involved for this edge
116 962 : double fLeftStart(0.0);
117 :
118 : // now add all points targeted to be at this index
119 2189 : while(nNewInd < nTempPointCount && rTempPoints[nNewInd].getIndex() == a)
120 : {
121 265 : const temporaryPoint& rTempPoint = rTempPoints[nNewInd++];
122 :
123 : // split curve segment. Splits need to come sorted and need to be < 1.0. Also,
124 : // since original segment is consumed from left to right, the cut values need
125 : // to be scaled to the remaining part
126 265 : B2DCubicBezier aLeftPart;
127 265 : const double fRelativeSplitPoint((rTempPoint.getCut() - fLeftStart) / (1.0 - fLeftStart));
128 265 : aEdge.split(fRelativeSplitPoint, &aLeftPart, &aEdge);
129 265 : fLeftStart = rTempPoint.getCut();
130 :
131 : // add left bow
132 265 : aRetval.appendBezierSegment(aLeftPart.getControlPointA(), aLeftPart.getControlPointB(), rTempPoint.getPoint());
133 265 : }
134 :
135 : // add remaining bow
136 962 : aRetval.appendBezierSegment(aEdge.getControlPointA(), aEdge.getControlPointB(), aEdge.getEndPoint());
137 : }
138 : else
139 : {
140 : // add all points targeted to be at this index
141 16784 : while(nNewInd < nTempPointCount && rTempPoints[nNewInd].getIndex() == a)
142 : {
143 2804 : const temporaryPoint& rTempPoint = rTempPoints[nNewInd++];
144 2804 : const B2DPoint aNewPoint(rTempPoint.getPoint());
145 :
146 : // do not add points double
147 2804 : if(!aRetval.getB2DPoint(aRetval.count() - 1L).equal(aNewPoint))
148 : {
149 2419 : aRetval.append(aNewPoint);
150 : }
151 2804 : }
152 :
153 : // add edge end point
154 6990 : aRetval.append(aEdge.getEndPoint());
155 : }
156 1461 : }
157 : }
158 :
159 1461 : if(rCandidate.isClosed())
160 : {
161 : // set closed flag and correct last point (which is added double now).
162 1091 : tools::closeWithGeometryChange(aRetval);
163 : }
164 :
165 1461 : return aRetval;
166 : }
167 : else
168 : {
169 6236 : return rCandidate;
170 : }
171 : }
172 :
173 213 : void adaptAndTransferCutsWithBezierSegment(
174 : const temporaryPointVector& rPointVector, const B2DPolygon& rPolygon,
175 : sal_uInt32 nInd, temporaryPointVector& rTempPoints)
176 : {
177 : // assuming that the subdivision to create rPolygon used aequidistant pieces
178 : // (as in adaptiveSubdivideByCount) it is now possible to calculate back the
179 : // cut positions in the polygon to relative cut positions on the original bezier
180 : // segment.
181 213 : const sal_uInt32 nTempPointCount(rPointVector.size());
182 213 : const sal_uInt32 nEdgeCount(rPolygon.count() ? rPolygon.count() - 1L : 0L);
183 :
184 213 : if(nTempPointCount && nEdgeCount)
185 : {
186 474 : for(sal_uInt32 a(0L); a < nTempPointCount; a++)
187 : {
188 261 : const temporaryPoint& rTempPoint = rPointVector[a];
189 261 : const double fCutPosInPolygon((double)rTempPoint.getIndex() + rTempPoint.getCut());
190 261 : const double fRelativeCutPos(fCutPosInPolygon / (double)nEdgeCount);
191 261 : rTempPoints.push_back(temporaryPoint(rTempPoint.getPoint(), nInd, fRelativeCutPos));
192 : }
193 : }
194 213 : }
195 :
196 : } // end of anonymous namespace
197 : } // end of namespace basegfx
198 :
199 : namespace basegfx
200 : {
201 : namespace
202 : {
203 :
204 : // predefines for calls to this methods before method implementation
205 :
206 : void findCuts(const B2DPolygon& rCandidate, temporaryPointVector& rTempPoints);
207 : void findTouches(const B2DPolygon& rEdgePolygon, const B2DPolygon& rPointPolygon, temporaryPointVector& rTempPoints);
208 : void findCuts(const B2DPolygon& rCandidateA, const B2DPolygon& rCandidateB, temporaryPointVector& rTempPointsA, temporaryPointVector& rTempPointsB);
209 :
210 53095 : void findEdgeCutsTwoEdges(
211 : const B2DPoint& rCurrA, const B2DPoint& rNextA,
212 : const B2DPoint& rCurrB, const B2DPoint& rNextB,
213 : sal_uInt32 nIndA, sal_uInt32 nIndB,
214 : temporaryPointVector& rTempPointsA, temporaryPointVector& rTempPointsB)
215 : {
216 : // no null length edges
217 53095 : if(!(rCurrA.equal(rNextA) || rCurrB.equal(rNextB)))
218 : {
219 : // no common start/end points, this can be no cuts
220 44070 : if(!(rCurrB.equal(rCurrA) || rCurrB.equal(rNextA) || rNextB.equal(rCurrA) || rNextB.equal(rNextA)))
221 : {
222 40751 : const B2DVector aVecA(rNextA - rCurrA);
223 81502 : const B2DVector aVecB(rNextB - rCurrB);
224 40751 : double fCut(aVecA.cross(aVecB));
225 :
226 40751 : if(!fTools::equalZero(fCut))
227 : {
228 39561 : const double fZero(0.0);
229 39561 : const double fOne(1.0);
230 39561 : fCut = (aVecB.getY() * (rCurrB.getX() - rCurrA.getX()) + aVecB.getX() * (rCurrA.getY() - rCurrB.getY())) / fCut;
231 :
232 39561 : if(fTools::moreOrEqual(fCut, fZero) && fTools::lessOrEqual(fCut, fOne))
233 : {
234 : // it's a candidate, but also need to test parameter value of cut on line 2
235 : double fCut2;
236 :
237 : // choose the more precise version
238 7032 : if(fabs(aVecB.getX()) > fabs(aVecB.getY()))
239 : {
240 3555 : fCut2 = (rCurrA.getX() + (fCut * aVecA.getX()) - rCurrB.getX()) / aVecB.getX();
241 : }
242 : else
243 : {
244 3477 : fCut2 = (rCurrA.getY() + (fCut * aVecA.getY()) - rCurrB.getY()) / aVecB.getY();
245 : }
246 :
247 7032 : if(fTools::moreOrEqual(fCut2, fZero) && fTools::lessOrEqual(fCut2, fOne))
248 : {
249 : // cut is in range, add point. Two edges can have only one cut, but
250 : // add a cut point to each list. The lists may be the same for
251 : // self intersections.
252 2475 : const B2DPoint aCutPoint(interpolate(rCurrA, rNextA, fCut));
253 2475 : rTempPointsA.push_back(temporaryPoint(aCutPoint, nIndA, fCut));
254 2475 : rTempPointsB.push_back(temporaryPoint(aCutPoint, nIndB, fCut2));
255 : }
256 : }
257 40751 : }
258 : }
259 : }
260 53095 : }
261 :
262 15272 : void findCutsAndTouchesAndCommonForBezier(const B2DPolygon& rCandidateA, const B2DPolygon& rCandidateB, temporaryPointVector& rTempPointsA, temporaryPointVector& rTempPointsB)
263 : {
264 : // #i76891#
265 : // This new method is necessary since in findEdgeCutsBezierAndEdge and in findEdgeCutsTwoBeziers
266 : // it is not sufficient to use findCuts() recursively. This will indeed find the cuts between the
267 : // segments of the two temporarily adaptive subdivided bezier segments, but not the touches or
268 : // equal points of them.
269 : // It would be possible to find the toches using findTouches(), but at last with commpn points
270 : // the adding of cut points (temporary points) would fail. But for these temporarily adaptive
271 : // subdivided bezier segments, common points may be not very likely, but the bug shows that it
272 : // happens.
273 : // Touch points are a little bit more likely than common points. All in all it is best to use
274 : // a specialized method here which can profit from knowing that it is working on a special
275 : // family of B2DPolygons: no curve segments included and not closed.
276 : OSL_ENSURE(!rCandidateA.areControlPointsUsed() && !rCandidateB.areControlPointsUsed(), "findCutsAndTouchesAndCommonForBezier only works with subdivided polygons (!)");
277 : OSL_ENSURE(!rCandidateA.isClosed() && !rCandidateB.isClosed(), "findCutsAndTouchesAndCommonForBezier only works with opened polygons (!)");
278 15272 : const sal_uInt32 nPointCountA(rCandidateA.count());
279 15272 : const sal_uInt32 nPointCountB(rCandidateB.count());
280 :
281 15272 : if(nPointCountA > 1 && nPointCountB > 1)
282 : {
283 15272 : const sal_uInt32 nEdgeCountA(nPointCountA - 1);
284 15272 : const sal_uInt32 nEdgeCountB(nPointCountB - 1);
285 15272 : B2DPoint aCurrA(rCandidateA.getB2DPoint(0L));
286 :
287 794144 : for(sal_uInt32 a(0L); a < nEdgeCountA; a++)
288 : {
289 778872 : const B2DPoint aNextA(rCandidateA.getB2DPoint(a + 1L));
290 778872 : const B2DRange aRangeA(aCurrA, aNextA);
291 1557744 : B2DPoint aCurrB(rCandidateB.getB2DPoint(0L));
292 :
293 15791844 : for(sal_uInt32 b(0L); b < nEdgeCountB; b++)
294 : {
295 15012972 : const B2DPoint aNextB(rCandidateB.getB2DPoint(b + 1L));
296 15012972 : const B2DRange aRangeB(aCurrB, aNextB);
297 :
298 15012972 : if(aRangeA.overlaps(aRangeB))
299 : {
300 : // no null length edges
301 160954 : if(!(aCurrA.equal(aNextA) || aCurrB.equal(aNextB)))
302 : {
303 157903 : const B2DVector aVecA(aNextA - aCurrA);
304 315806 : const B2DVector aVecB(aNextB - aCurrB);
305 157903 : double fCutA(aVecA.cross(aVecB));
306 :
307 157903 : if(!fTools::equalZero(fCutA))
308 : {
309 156388 : const double fZero(0.0);
310 156388 : const double fOne(1.0);
311 156388 : fCutA = (aVecB.getY() * (aCurrB.getX() - aCurrA.getX()) + aVecB.getX() * (aCurrA.getY() - aCurrB.getY())) / fCutA;
312 :
313 : // use range [0.0 .. 1.0[, thus in the loop, all direct aCurrA cuts will be registered
314 : // as 0.0 cut. The 1.0 cut will be registered in the next loop step
315 156388 : if(fTools::moreOrEqual(fCutA, fZero) && fTools::less(fCutA, fOne))
316 : {
317 : // it's a candidate, but also need to test parameter value of cut on line 2
318 : double fCutB;
319 :
320 : // choose the more precise version
321 6244 : if(fabs(aVecB.getX()) > fabs(aVecB.getY()))
322 : {
323 2859 : fCutB = (aCurrA.getX() + (fCutA * aVecA.getX()) - aCurrB.getX()) / aVecB.getX();
324 : }
325 : else
326 : {
327 3385 : fCutB = (aCurrA.getY() + (fCutA * aVecA.getY()) - aCurrB.getY()) / aVecB.getY();
328 : }
329 :
330 : // use range [0.0 .. 1.0[, thus in the loop, all direct aCurrA cuts will be registered
331 : // as 0.0 cut. The 1.0 cut will be registered in the next loop step
332 6244 : if(fTools::moreOrEqual(fCutB, fZero) && fTools::less(fCutB, fOne))
333 : {
334 : // cut is in both ranges. Add points for A and B
335 : // #i111715# use fTools::equal instead of fTools::equalZero for better accuracy
336 165 : if(fTools::equal(fCutA, fZero))
337 : {
338 : // ignore for start point in first edge; this is handled
339 : // by outer methods and would just produce a double point
340 27 : if(a)
341 : {
342 23 : rTempPointsA.push_back(temporaryPoint(aCurrA, a, 0.0));
343 : }
344 : }
345 : else
346 : {
347 138 : const B2DPoint aCutPoint(interpolate(aCurrA, aNextA, fCutA));
348 138 : rTempPointsA.push_back(temporaryPoint(aCutPoint, a, fCutA));
349 : }
350 :
351 : // #i111715# use fTools::equal instead of fTools::equalZero for better accuracy
352 165 : if(fTools::equal(fCutB, fZero))
353 : {
354 : // ignore for start point in first edge; this is handled
355 : // by outer methods and would just produce a double point
356 28 : if(b)
357 : {
358 23 : rTempPointsB.push_back(temporaryPoint(aCurrB, b, 0.0));
359 : }
360 : }
361 : else
362 : {
363 137 : const B2DPoint aCutPoint(interpolate(aCurrB, aNextB, fCutB));
364 137 : rTempPointsB.push_back(temporaryPoint(aCutPoint, b, fCutB));
365 : }
366 : }
367 : }
368 157903 : }
369 : }
370 : }
371 :
372 : // prepare next step
373 15012972 : aCurrB = aNextB;
374 15012972 : }
375 :
376 : // prepare next step
377 778872 : aCurrA = aNextA;
378 794144 : }
379 : }
380 15272 : }
381 :
382 9690 : void findEdgeCutsBezierAndEdge(
383 : const B2DCubicBezier& rCubicA,
384 : const B2DPoint& rCurrB, const B2DPoint& rNextB,
385 : sal_uInt32 nIndA, sal_uInt32 nIndB,
386 : temporaryPointVector& rTempPointsA, temporaryPointVector& rTempPointsB)
387 : {
388 : // find all cuts between given bezier segment and edge. Add an entry to the tempPoints
389 : // for each common point with the cut value describing the relative position on given
390 : // bezier segment and edge.
391 9690 : B2DPolygon aTempPolygonA;
392 19380 : B2DPolygon aTempPolygonEdge;
393 19380 : temporaryPointVector aTempPointVectorA;
394 19380 : temporaryPointVector aTempPointVectorEdge;
395 :
396 : // create subdivided polygons and find cuts between them
397 : // Keep adaptiveSubdivideByCount due to needed quality
398 9690 : aTempPolygonA.reserve(SUBDIVIDE_FOR_CUT_TEST_COUNT + 8);
399 9690 : aTempPolygonA.append(rCubicA.getStartPoint());
400 9690 : rCubicA.adaptiveSubdivideByCount(aTempPolygonA, SUBDIVIDE_FOR_CUT_TEST_COUNT);
401 9690 : aTempPolygonEdge.append(rCurrB);
402 9690 : aTempPolygonEdge.append(rNextB);
403 :
404 : // #i76891# using findCuts recursively is not sufficient here
405 9690 : findCutsAndTouchesAndCommonForBezier(aTempPolygonA, aTempPolygonEdge, aTempPointVectorA, aTempPointVectorEdge);
406 :
407 9690 : if(!aTempPointVectorA.empty())
408 : {
409 : // adapt tempVector entries to segment
410 67 : adaptAndTransferCutsWithBezierSegment(aTempPointVectorA, aTempPolygonA, nIndA, rTempPointsA);
411 : }
412 :
413 : // append remapped tempVector entries for edge to tempPoints for edge
414 9756 : for(sal_uInt32 a(0L); a < aTempPointVectorEdge.size(); a++)
415 : {
416 66 : const temporaryPoint& rTempPoint = aTempPointVectorEdge[a];
417 66 : rTempPointsB.push_back(temporaryPoint(rTempPoint.getPoint(), nIndB, rTempPoint.getCut()));
418 9690 : }
419 9690 : }
420 :
421 5582 : void findEdgeCutsTwoBeziers(
422 : const B2DCubicBezier& rCubicA,
423 : const B2DCubicBezier& rCubicB,
424 : sal_uInt32 nIndA, sal_uInt32 nIndB,
425 : temporaryPointVector& rTempPointsA, temporaryPointVector& rTempPointsB)
426 : {
427 : // find all cuts between the two given bezier segments. Add an entry to the tempPoints
428 : // for each common point with the cut value describing the relative position on given
429 : // bezier segments.
430 5582 : B2DPolygon aTempPolygonA;
431 11164 : B2DPolygon aTempPolygonB;
432 11164 : temporaryPointVector aTempPointVectorA;
433 11164 : temporaryPointVector aTempPointVectorB;
434 :
435 : // create subdivided polygons and find cuts between them
436 : // Keep adaptiveSubdivideByCount due to needed quality
437 5582 : aTempPolygonA.reserve(SUBDIVIDE_FOR_CUT_TEST_COUNT + 8);
438 5582 : aTempPolygonA.append(rCubicA.getStartPoint());
439 5582 : rCubicA.adaptiveSubdivideByCount(aTempPolygonA, SUBDIVIDE_FOR_CUT_TEST_COUNT);
440 5582 : aTempPolygonB.reserve(SUBDIVIDE_FOR_CUT_TEST_COUNT + 8);
441 5582 : aTempPolygonB.append(rCubicB.getStartPoint());
442 5582 : rCubicB.adaptiveSubdivideByCount(aTempPolygonB, SUBDIVIDE_FOR_CUT_TEST_COUNT);
443 :
444 : // #i76891# using findCuts recursively is not sufficient here
445 5582 : findCutsAndTouchesAndCommonForBezier(aTempPolygonA, aTempPolygonB, aTempPointVectorA, aTempPointVectorB);
446 :
447 5582 : if(!aTempPointVectorA.empty())
448 : {
449 : // adapt tempVector entries to segment
450 70 : adaptAndTransferCutsWithBezierSegment(aTempPointVectorA, aTempPolygonA, nIndA, rTempPointsA);
451 : }
452 :
453 5582 : if(!aTempPointVectorB.empty())
454 : {
455 : // adapt tempVector entries to segment
456 70 : adaptAndTransferCutsWithBezierSegment(aTempPointVectorB, aTempPolygonB, nIndB, rTempPointsB);
457 5582 : }
458 5582 : }
459 :
460 13391 : void findEdgeCutsOneBezier(
461 : const B2DCubicBezier& rCubicA,
462 : sal_uInt32 nInd, temporaryPointVector& rTempPoints)
463 : {
464 : // avoid expensive part of this method if possible
465 : // TODO: use hasAnyExtremum() method instead when it becomes available
466 : double fDummy;
467 13391 : const bool bHasAnyExtremum = rCubicA.getMinimumExtremumPosition( fDummy );
468 13391 : if( !bHasAnyExtremum )
469 24486 : return;
470 :
471 : // find all self-intersections on the given bezier segment. Add an entry to the tempPoints
472 : // for each self intersection point with the cut value describing the relative position on given
473 : // bezier segment.
474 2296 : B2DPolygon aTempPolygon;
475 4592 : temporaryPointVector aTempPointVector;
476 :
477 : // create subdivided polygon and find cuts on it
478 : // Keep adaptiveSubdivideByCount due to needed quality
479 2296 : aTempPolygon.reserve(SUBDIVIDE_FOR_CUT_TEST_COUNT + 8);
480 2296 : aTempPolygon.append(rCubicA.getStartPoint());
481 2296 : rCubicA.adaptiveSubdivideByCount(aTempPolygon, SUBDIVIDE_FOR_CUT_TEST_COUNT);
482 2296 : findCuts(aTempPolygon, aTempPointVector);
483 :
484 2296 : if(!aTempPointVector.empty())
485 : {
486 : // adapt tempVector entries to segment
487 0 : adaptAndTransferCutsWithBezierSegment(aTempPointVector, aTempPolygon, nInd, rTempPoints);
488 2296 : }
489 : }
490 :
491 6666 : void findCuts(const B2DPolygon& rCandidate, temporaryPointVector& rTempPoints)
492 : {
493 : // find out if there are edges with intersections (self-cuts). If yes, add
494 : // entries to rTempPoints accordingly
495 6666 : const sal_uInt32 nPointCount(rCandidate.count());
496 :
497 6666 : if(nPointCount)
498 : {
499 6666 : const sal_uInt32 nEdgeCount(rCandidate.isClosed() ? nPointCount : nPointCount - 1L);
500 :
501 6666 : if(nEdgeCount)
502 : {
503 6666 : const bool bCurvesInvolved(rCandidate.areControlPointsUsed());
504 :
505 6666 : if(bCurvesInvolved)
506 : {
507 2576 : B2DCubicBezier aCubicA;
508 5152 : B2DCubicBezier aCubicB;
509 :
510 31719 : for(sal_uInt32 a(0L); a < nEdgeCount - 1L; a++)
511 : {
512 29143 : rCandidate.getBezierSegment(a, aCubicA);
513 29143 : aCubicA.testAndSolveTrivialBezier();
514 29143 : const bool bEdgeAIsCurve(aCubicA.isBezier());
515 29143 : const B2DRange aRangeA(aCubicA.getRange());
516 :
517 29143 : if(bEdgeAIsCurve)
518 : {
519 : // curved segments may have self-intersections, do not forget those (!)
520 13391 : findEdgeCutsOneBezier(aCubicA, a, rTempPoints);
521 : }
522 :
523 462554 : for(sal_uInt32 b(a + 1L); b < nEdgeCount; b++)
524 : {
525 433411 : rCandidate.getBezierSegment(b, aCubicB);
526 433411 : aCubicB.testAndSolveTrivialBezier();
527 433411 : const B2DRange aRangeB(aCubicB.getRange());
528 :
529 : // only overlapping segments need to be tested
530 : // consecutive segments touch of course
531 433411 : bool bOverlap = false;
532 433411 : if( b > a+1)
533 404268 : bOverlap = aRangeA.overlaps(aRangeB);
534 : else
535 29143 : bOverlap = aRangeA.overlapsMore(aRangeB);
536 433411 : if( bOverlap)
537 : {
538 12168 : const bool bEdgeBIsCurve(aCubicB.isBezier());
539 12168 : if(bEdgeAIsCurve && bEdgeBIsCurve)
540 : {
541 : // test for bezier-bezier cuts
542 2516 : findEdgeCutsTwoBeziers(aCubicA, aCubicB, a, b, rTempPoints, rTempPoints);
543 : }
544 9652 : else if(bEdgeAIsCurve)
545 : {
546 : // test for bezier-edge cuts
547 4146 : findEdgeCutsBezierAndEdge(aCubicA, aCubicB.getStartPoint(), aCubicB.getEndPoint(), a, b, rTempPoints, rTempPoints);
548 : }
549 5506 : else if(bEdgeBIsCurve)
550 : {
551 : // test for bezier-edge cuts
552 1427 : findEdgeCutsBezierAndEdge(aCubicB, aCubicA.getStartPoint(), aCubicA.getEndPoint(), b, a, rTempPoints, rTempPoints);
553 : }
554 : else
555 : {
556 : // test for simple edge-edge cuts
557 : findEdgeCutsTwoEdges(aCubicA.getStartPoint(), aCubicA.getEndPoint(), aCubicB.getStartPoint(), aCubicB.getEndPoint(),
558 4079 : a, b, rTempPoints, rTempPoints);
559 : }
560 : }
561 : }
562 2576 : }
563 : }
564 : else
565 : {
566 4090 : B2DPoint aCurrA(rCandidate.getB2DPoint(0L));
567 :
568 127518 : for(sal_uInt32 a(0L); a < nEdgeCount - 1L; a++)
569 : {
570 123428 : const B2DPoint aNextA(rCandidate.getB2DPoint(a + 1L == nPointCount ? 0L : a + 1L));
571 123428 : const B2DRange aRangeA(aCurrA, aNextA);
572 246856 : B2DPoint aCurrB(rCandidate.getB2DPoint(a + 1L));
573 :
574 3087472 : for(sal_uInt32 b(a + 1L); b < nEdgeCount; b++)
575 : {
576 2964044 : const B2DPoint aNextB(rCandidate.getB2DPoint(b + 1L == nPointCount ? 0L : b + 1L));
577 2964044 : const B2DRange aRangeB(aCurrB, aNextB);
578 :
579 : // consecutive segments touch of course
580 2964044 : bool bOverlap = false;
581 2964044 : if( b > a+1)
582 2840616 : bOverlap = aRangeA.overlaps(aRangeB);
583 : else
584 123428 : bOverlap = aRangeA.overlapsMore(aRangeB);
585 2964044 : if( bOverlap)
586 : {
587 5127 : findEdgeCutsTwoEdges(aCurrA, aNextA, aCurrB, aNextB, a, b, rTempPoints, rTempPoints);
588 : }
589 :
590 : // prepare next step
591 2964044 : aCurrB = aNextB;
592 2964044 : }
593 :
594 : // prepare next step
595 123428 : aCurrA = aNextA;
596 127518 : }
597 : }
598 : }
599 : }
600 6666 : }
601 :
602 : } // end of anonymous namespace
603 : } // end of namespace basegfx
604 :
605 : namespace basegfx
606 : {
607 : namespace
608 : {
609 :
610 1574377 : void findTouchesOnEdge(
611 : const B2DPoint& rCurr, const B2DPoint& rNext, const B2DPolygon& rPointPolygon,
612 : sal_uInt32 nInd, temporaryPointVector& rTempPoints)
613 : {
614 : // find out if points from rPointPolygon are positioned on given edge. If Yes, add
615 : // points there to represent touches (which may be enter or leave nodes later).
616 1574377 : const sal_uInt32 nPointCount(rPointPolygon.count());
617 :
618 1574377 : if(nPointCount)
619 : {
620 1574377 : const B2DRange aRange(rCurr, rNext);
621 1574377 : const B2DVector aEdgeVector(rNext - rCurr);
622 3148754 : B2DVector aNormalizedEdgeVector(aEdgeVector);
623 1574377 : aNormalizedEdgeVector.normalize();
624 1574377 : bool bTestUsingX(fabs(aEdgeVector.getX()) > fabs(aEdgeVector.getY()));
625 :
626 36539726 : for(sal_uInt32 a(0L); a < nPointCount; a++)
627 : {
628 34965349 : const B2DPoint aTestPoint(rPointPolygon.getB2DPoint(a));
629 :
630 34965349 : if(aRange.isInside(aTestPoint))
631 : {
632 127836 : if(!aTestPoint.equal(rCurr) && !aTestPoint.equal(rNext))
633 : {
634 43601 : const B2DVector aTestVector(aTestPoint - rCurr);
635 :
636 43601 : if(areParallel(aNormalizedEdgeVector, aTestVector))
637 : {
638 : const double fCut((bTestUsingX)
639 31 : ? aTestVector.getX() / aEdgeVector.getX()
640 97 : : aTestVector.getY() / aEdgeVector.getY());
641 66 : const double fZero(0.0);
642 66 : const double fOne(1.0);
643 :
644 66 : if(fTools::more(fCut, fZero) && fTools::less(fCut, fOne))
645 : {
646 66 : rTempPoints.push_back(temporaryPoint(aTestPoint, nInd, fCut));
647 : }
648 43601 : }
649 : }
650 : }
651 36539726 : }
652 : }
653 1574377 : }
654 :
655 29101 : void findTouchesOnCurve(
656 : const B2DCubicBezier& rCubicA, const B2DPolygon& rPointPolygon,
657 : sal_uInt32 nInd, temporaryPointVector& rTempPoints)
658 : {
659 : // find all points from rPointPolygon which touch the given bezier segment. Add an entry
660 : // for each touch to the given pointVector. The cut for that entry is the relative position on
661 : // the given bezier segment.
662 29101 : B2DPolygon aTempPolygon;
663 58202 : temporaryPointVector aTempPointVector;
664 :
665 : // create subdivided polygon and find cuts on it
666 : // Keep adaptiveSubdivideByCount due to needed quality
667 29101 : aTempPolygon.reserve(SUBDIVIDE_FOR_CUT_TEST_COUNT + 8);
668 29101 : aTempPolygon.append(rCubicA.getStartPoint());
669 29101 : rCubicA.adaptiveSubdivideByCount(aTempPolygon, SUBDIVIDE_FOR_CUT_TEST_COUNT);
670 29101 : findTouches(aTempPolygon, rPointPolygon, aTempPointVector);
671 :
672 29101 : if(!aTempPointVector.empty())
673 : {
674 : // adapt tempVector entries to segment
675 6 : adaptAndTransferCutsWithBezierSegment(aTempPointVector, aTempPolygon, nInd, rTempPoints);
676 29101 : }
677 29101 : }
678 :
679 50065 : void findTouches(const B2DPolygon& rEdgePolygon, const B2DPolygon& rPointPolygon, temporaryPointVector& rTempPoints)
680 : {
681 : // find out if points from rPointPolygon touch edges from rEdgePolygon. If yes,
682 : // add entries to rTempPoints
683 50065 : const sal_uInt32 nPointCount(rPointPolygon.count());
684 50065 : const sal_uInt32 nEdgePointCount(rEdgePolygon.count());
685 :
686 50065 : if(nPointCount && nEdgePointCount)
687 : {
688 50065 : const sal_uInt32 nEdgeCount(rEdgePolygon.isClosed() ? nEdgePointCount : nEdgePointCount - 1L);
689 50065 : B2DPoint aCurr(rEdgePolygon.getB2DPoint(0));
690 :
691 1676516 : for(sal_uInt32 a(0L); a < nEdgeCount; a++)
692 : {
693 1626451 : const sal_uInt32 nNextIndex((a + 1) % nEdgePointCount);
694 1626451 : const B2DPoint aNext(rEdgePolygon.getB2DPoint(nNextIndex));
695 :
696 1626451 : if(!aCurr.equal(aNext))
697 : {
698 1603478 : bool bHandleAsSimpleEdge(true);
699 :
700 1603478 : if(rEdgePolygon.areControlPointsUsed())
701 : {
702 60266 : const B2DPoint aNextControlPoint(rEdgePolygon.getNextControlPoint(a));
703 120532 : const B2DPoint aPrevControlPoint(rEdgePolygon.getPrevControlPoint(nNextIndex));
704 60266 : const bool bEdgeIsCurve(!aNextControlPoint.equal(aCurr) || !aPrevControlPoint.equal(aNext));
705 :
706 60266 : if(bEdgeIsCurve)
707 : {
708 29101 : bHandleAsSimpleEdge = false;
709 29101 : const B2DCubicBezier aCubicA(aCurr, aNextControlPoint, aPrevControlPoint, aNext);
710 29101 : findTouchesOnCurve(aCubicA, rPointPolygon, a, rTempPoints);
711 60266 : }
712 : }
713 :
714 1603478 : if(bHandleAsSimpleEdge)
715 : {
716 1574377 : findTouchesOnEdge(aCurr, aNext, rPointPolygon, a, rTempPoints);
717 : }
718 : }
719 :
720 : // next step
721 1626451 : aCurr = aNext;
722 1676516 : }
723 : }
724 50065 : }
725 :
726 : } // end of anonymous namespace
727 : } // end of namespace basegfx
728 :
729 : namespace basegfx
730 : {
731 : namespace
732 : {
733 :
734 8297 : void findCuts(const B2DPolygon& rCandidateA, const B2DPolygon& rCandidateB, temporaryPointVector& rTempPointsA, temporaryPointVector& rTempPointsB)
735 : {
736 : // find out if edges from both polygons cut. If so, add entries to rTempPoints which
737 : // should be added to the polygons accordingly
738 8297 : const sal_uInt32 nPointCountA(rCandidateA.count());
739 8297 : const sal_uInt32 nPointCountB(rCandidateB.count());
740 :
741 8297 : if(nPointCountA && nPointCountB)
742 : {
743 8297 : const sal_uInt32 nEdgeCountA(rCandidateA.isClosed() ? nPointCountA : nPointCountA - 1L);
744 8297 : const sal_uInt32 nEdgeCountB(rCandidateB.isClosed() ? nPointCountB : nPointCountB - 1L);
745 :
746 8297 : if(nEdgeCountA && nEdgeCountB)
747 : {
748 8297 : const bool bCurvesInvolved(rCandidateA.areControlPointsUsed() || rCandidateB.areControlPointsUsed());
749 :
750 8297 : if(bCurvesInvolved)
751 : {
752 3935 : B2DCubicBezier aCubicA;
753 7870 : B2DCubicBezier aCubicB;
754 :
755 33922 : for(sal_uInt32 a(0L); a < nEdgeCountA; a++)
756 : {
757 29987 : rCandidateA.getBezierSegment(a, aCubicA);
758 29987 : aCubicA.testAndSolveTrivialBezier();
759 29987 : const bool bEdgeAIsCurve(aCubicA.isBezier());
760 29987 : const B2DRange aRangeA(aCubicA.getRange());
761 :
762 301603 : for(sal_uInt32 b(0L); b < nEdgeCountB; b++)
763 : {
764 271616 : rCandidateB.getBezierSegment(b, aCubicB);
765 271616 : aCubicB.testAndSolveTrivialBezier();
766 271616 : const B2DRange aRangeB(aCubicB.getRange());
767 :
768 : // consecutive segments touch of course
769 271616 : bool bOverlap = false;
770 271616 : if( b > a+1)
771 94455 : bOverlap = aRangeA.overlaps(aRangeB);
772 : else
773 177161 : bOverlap = aRangeA.overlapsMore(aRangeB);
774 271616 : if( bOverlap)
775 : {
776 24893 : const bool bEdgeBIsCurve(aCubicB.isBezier());
777 24893 : if(bEdgeAIsCurve && bEdgeBIsCurve)
778 : {
779 : // test for bezier-bezier cuts
780 3066 : findEdgeCutsTwoBeziers(aCubicA, aCubicB, a, b, rTempPointsA, rTempPointsB);
781 : }
782 21827 : else if(bEdgeAIsCurve)
783 : {
784 : // test for bezier-edge cuts
785 2655 : findEdgeCutsBezierAndEdge(aCubicA, aCubicB.getStartPoint(), aCubicB.getEndPoint(), a, b, rTempPointsA, rTempPointsB);
786 : }
787 19172 : else if(bEdgeBIsCurve)
788 : {
789 : // test for bezier-edge cuts
790 1462 : findEdgeCutsBezierAndEdge(aCubicB, aCubicA.getStartPoint(), aCubicA.getEndPoint(), b, a, rTempPointsB, rTempPointsA);
791 : }
792 : else
793 : {
794 : // test for simple edge-edge cuts
795 : findEdgeCutsTwoEdges(aCubicA.getStartPoint(), aCubicA.getEndPoint(), aCubicB.getStartPoint(), aCubicB.getEndPoint(),
796 17710 : a, b, rTempPointsA, rTempPointsB);
797 : }
798 : }
799 : }
800 3935 : }
801 : }
802 : else
803 : {
804 4362 : B2DPoint aCurrA(rCandidateA.getB2DPoint(0L));
805 :
806 27063 : for(sal_uInt32 a(0L); a < nEdgeCountA; a++)
807 : {
808 22701 : const B2DPoint aNextA(rCandidateA.getB2DPoint(a + 1L == nPointCountA ? 0L : a + 1L));
809 22701 : const B2DRange aRangeA(aCurrA, aNextA);
810 45402 : B2DPoint aCurrB(rCandidateB.getB2DPoint(0L));
811 :
812 146361 : for(sal_uInt32 b(0L); b < nEdgeCountB; b++)
813 : {
814 123660 : const B2DPoint aNextB(rCandidateB.getB2DPoint(b + 1L == nPointCountB ? 0L : b + 1L));
815 123660 : const B2DRange aRangeB(aCurrB, aNextB);
816 :
817 : // consecutive segments touch of course
818 123660 : bool bOverlap = false;
819 123660 : if( b > a+1)
820 31634 : bOverlap = aRangeA.overlaps(aRangeB);
821 : else
822 92026 : bOverlap = aRangeA.overlapsMore(aRangeB);
823 123660 : if( bOverlap)
824 : {
825 : // test for simple edge-edge cuts
826 23911 : findEdgeCutsTwoEdges(aCurrA, aNextA, aCurrB, aNextB, a, b, rTempPointsA, rTempPointsB);
827 : }
828 :
829 : // prepare next step
830 123660 : aCurrB = aNextB;
831 123660 : }
832 :
833 : // prepare next step
834 22701 : aCurrA = aNextA;
835 27063 : }
836 : }
837 : }
838 : }
839 8297 : }
840 :
841 : } // end of anonymous namespace
842 : } // end of namespace basegfx
843 :
844 : namespace basegfx
845 : {
846 : namespace tools
847 : {
848 :
849 4370 : B2DPolygon addPointsAtCutsAndTouches(const B2DPolygon& rCandidate)
850 : {
851 4370 : if(rCandidate.count())
852 : {
853 4370 : temporaryPointVector aTempPoints;
854 :
855 4370 : findTouches(rCandidate, rCandidate, aTempPoints);
856 4370 : findCuts(rCandidate, aTempPoints);
857 :
858 4370 : return mergeTemporaryPointsAndPolygon(rCandidate, aTempPoints);
859 : }
860 : else
861 : {
862 0 : return rCandidate;
863 : }
864 : }
865 :
866 821 : B2DPolyPolygon addPointsAtCutsAndTouches(const B2DPolyPolygon& rCandidate, bool bSelfIntersections)
867 : {
868 821 : const sal_uInt32 nCount(rCandidate.count());
869 :
870 821 : if(nCount)
871 : {
872 821 : B2DPolyPolygon aRetval;
873 :
874 821 : if(1L == nCount)
875 : {
876 190 : if(bSelfIntersections)
877 : {
878 : // remove self intersections
879 190 : aRetval.append(addPointsAtCutsAndTouches(rCandidate.getB2DPolygon(0L)));
880 : }
881 : else
882 : {
883 : // copy source
884 0 : aRetval = rCandidate;
885 : }
886 : }
887 : else
888 : {
889 : // first solve self cuts and self touches for all contained single polygons
890 631 : temporaryPolygonData *pTempData = new temporaryPolygonData[nCount];
891 : sal_uInt32 a, b;
892 :
893 2824 : for(a = 0L; a < nCount; a++)
894 : {
895 2193 : if(bSelfIntersections)
896 : {
897 : // use polygons with solved self intersections
898 2193 : pTempData[a].setPolygon(addPointsAtCutsAndTouches(rCandidate.getB2DPolygon(a)));
899 : }
900 : else
901 : {
902 : // copy given polygons
903 0 : pTempData[a].setPolygon(rCandidate.getB2DPolygon(a));
904 : }
905 : }
906 :
907 : // now cuts and touches between the polygons
908 2824 : for(a = 0L; a < nCount; a++)
909 : {
910 33382 : for(b = 0L; b < nCount; b++)
911 : {
912 31189 : if(a != b)
913 : {
914 : // look for touches, compare each edge polygon to all other points
915 28996 : if(pTempData[a].getRange().overlaps(pTempData[b].getRange()))
916 : {
917 16594 : findTouches(pTempData[a].getPolygon(), pTempData[b].getPolygon(), pTempData[a].getTemporaryPointVector());
918 : }
919 : }
920 :
921 31189 : if(a < b)
922 : {
923 : // look for cuts, compare each edge polygon to following ones
924 14498 : if(pTempData[a].getRange().overlaps(pTempData[b].getRange()))
925 : {
926 8297 : findCuts(pTempData[a].getPolygon(), pTempData[b].getPolygon(), pTempData[a].getTemporaryPointVector(), pTempData[b].getTemporaryPointVector());
927 : }
928 : }
929 : }
930 : }
931 :
932 : // consolidate the result
933 2824 : for(a = 0L; a < nCount; a++)
934 : {
935 2193 : aRetval.append(mergeTemporaryPointsAndPolygon(pTempData[a].getPolygon(), pTempData[a].getTemporaryPointVector()));
936 : }
937 :
938 631 : delete[] pTempData;
939 : }
940 :
941 821 : return aRetval;
942 : }
943 : else
944 : {
945 0 : return rCandidate;
946 : }
947 : }
948 :
949 766 : B2DPolygon addPointsAtCuts(const B2DPolygon& rCandidate, const B2DPoint& rStart, const B2DPoint& rEnd)
950 : {
951 766 : const sal_uInt32 nCount(rCandidate.count());
952 :
953 766 : if(nCount && !rStart.equal(rEnd))
954 : {
955 766 : const B2DRange aPolygonRange(rCandidate.getB2DRange());
956 766 : const B2DRange aEdgeRange(rStart, rEnd);
957 :
958 766 : if(aPolygonRange.overlaps(aEdgeRange))
959 : {
960 766 : const sal_uInt32 nEdgeCount(rCandidate.isClosed() ? nCount : nCount - 1);
961 766 : temporaryPointVector aTempPoints;
962 1532 : temporaryPointVector aUnusedTempPoints;
963 1532 : B2DCubicBezier aCubic;
964 :
965 5060 : for(sal_uInt32 a(0); a < nEdgeCount; a++)
966 : {
967 4294 : rCandidate.getBezierSegment(a, aCubic);
968 4294 : B2DRange aCubicRange(aCubic.getStartPoint(), aCubic.getEndPoint());
969 :
970 4294 : if(aCubic.isBezier())
971 : {
972 0 : aCubicRange.expand(aCubic.getControlPointA());
973 0 : aCubicRange.expand(aCubic.getControlPointB());
974 :
975 0 : if(aCubicRange.overlaps(aEdgeRange))
976 : {
977 0 : findEdgeCutsBezierAndEdge(aCubic, rStart, rEnd, a, 0, aTempPoints, aUnusedTempPoints);
978 : }
979 : }
980 : else
981 : {
982 4294 : if(aCubicRange.overlaps(aEdgeRange))
983 : {
984 1532 : findEdgeCutsTwoEdges(aCubic.getStartPoint(), aCubic.getEndPoint(), rStart, rEnd, a, 0, aTempPoints, aUnusedTempPoints);
985 : }
986 : }
987 : }
988 :
989 1532 : return mergeTemporaryPointsAndPolygon(rCandidate, aTempPoints);
990 : }
991 : }
992 :
993 0 : return rCandidate;
994 : }
995 :
996 368 : B2DPolygon addPointsAtCuts(const B2DPolygon& rCandidate, const B2DPolyPolygon& rPolyMask)
997 : {
998 368 : const sal_uInt32 nCountA(rCandidate.count());
999 368 : const sal_uInt32 nCountM(rPolyMask.count());
1000 :
1001 368 : if(nCountA && nCountM)
1002 : {
1003 368 : const B2DRange aRangeA(rCandidate.getB2DRange());
1004 368 : const B2DRange aRangeM(rPolyMask.getB2DRange());
1005 :
1006 368 : if(aRangeA.overlaps(aRangeM))
1007 : {
1008 368 : const sal_uInt32 nEdgeCountA(rCandidate.isClosed() ? nCountA : nCountA - 1);
1009 368 : temporaryPointVector aTempPointsA;
1010 736 : temporaryPointVector aUnusedTempPointsB;
1011 :
1012 736 : for(sal_uInt32 m(0); m < nCountM; m++)
1013 : {
1014 368 : const B2DPolygon aMask(rPolyMask.getB2DPolygon(m));
1015 368 : const sal_uInt32 nCountB(aMask.count());
1016 :
1017 368 : if(nCountB)
1018 : {
1019 368 : B2DCubicBezier aCubicA;
1020 736 : B2DCubicBezier aCubicB;
1021 :
1022 736 : for(sal_uInt32 a(0); a < nEdgeCountA; a++)
1023 : {
1024 368 : rCandidate.getBezierSegment(a, aCubicA);
1025 368 : const bool bCubicAIsCurve(aCubicA.isBezier());
1026 368 : B2DRange aCubicRangeA(aCubicA.getStartPoint(), aCubicA.getEndPoint());
1027 :
1028 368 : if(bCubicAIsCurve)
1029 : {
1030 0 : aCubicRangeA.expand(aCubicA.getControlPointA());
1031 0 : aCubicRangeA.expand(aCubicA.getControlPointB());
1032 : }
1033 :
1034 1840 : for(sal_uInt32 b(0); b < nCountB; b++)
1035 : {
1036 1472 : aMask.getBezierSegment(b, aCubicB);
1037 1472 : const bool bCubicBIsCurve(aCubicB.isBezier());
1038 1472 : B2DRange aCubicRangeB(aCubicB.getStartPoint(), aCubicB.getEndPoint());
1039 :
1040 1472 : if(bCubicBIsCurve)
1041 : {
1042 0 : aCubicRangeB.expand(aCubicB.getControlPointA());
1043 0 : aCubicRangeB.expand(aCubicB.getControlPointB());
1044 : }
1045 :
1046 1472 : if(aCubicRangeA.overlaps(aCubicRangeB))
1047 : {
1048 736 : if(bCubicAIsCurve && bCubicBIsCurve)
1049 : {
1050 0 : findEdgeCutsTwoBeziers(aCubicA, aCubicB, a, b, aTempPointsA, aUnusedTempPointsB);
1051 : }
1052 736 : else if(bCubicAIsCurve)
1053 : {
1054 0 : findEdgeCutsBezierAndEdge(aCubicA, aCubicB.getStartPoint(), aCubicB.getEndPoint(), a, b, aTempPointsA, aUnusedTempPointsB);
1055 : }
1056 736 : else if(bCubicBIsCurve)
1057 : {
1058 0 : findEdgeCutsBezierAndEdge(aCubicB, aCubicA.getStartPoint(), aCubicA.getEndPoint(), b, a, aUnusedTempPointsB, aTempPointsA);
1059 : }
1060 : else
1061 : {
1062 736 : findEdgeCutsTwoEdges(aCubicA.getStartPoint(), aCubicA.getEndPoint(), aCubicB.getStartPoint(), aCubicB.getEndPoint(), a, b, aTempPointsA, aUnusedTempPointsB);
1063 : }
1064 : }
1065 : }
1066 368 : }
1067 : }
1068 368 : }
1069 :
1070 736 : return mergeTemporaryPointsAndPolygon(rCandidate, aTempPointsA);
1071 : }
1072 : }
1073 :
1074 0 : return rCandidate;
1075 : }
1076 :
1077 : } // end of namespace tools
1078 : } // end of namespace basegfx
1079 :
1080 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|