| 393 | } |
| 394 | |
| 395 | void edgeColoringByDistance(Shape &shape, double angleThreshold, unsigned long long seed) { |
| 396 | |
| 397 | std::vector<EdgeSegment *> edgeSegments; |
| 398 | std::vector<int> splineStarts; |
| 399 | |
| 400 | double crossThreshold = sin(angleThreshold); |
| 401 | std::vector<int> corners; |
| 402 | for (std::vector<Contour>::iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour) |
| 403 | if (!contour->edges.empty()) { |
| 404 | // Identify corners |
| 405 | corners.clear(); |
| 406 | Vector2 prevDirection = contour->edges.back()->direction(1); |
| 407 | int index = 0; |
| 408 | for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge, ++index) { |
| 409 | if (isCorner(prevDirection.normalize(), (*edge)->direction(0).normalize(), crossThreshold)) |
| 410 | corners.push_back(index); |
| 411 | prevDirection = (*edge)->direction(1); |
| 412 | } |
| 413 | |
| 414 | splineStarts.push_back((int) edgeSegments.size()); |
| 415 | // Smooth contour |
| 416 | if (corners.empty()) |
| 417 | for (std::vector<EdgeHolder>::iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) |
| 418 | edgeSegments.push_back(&**edge); |
| 419 | // "Teardrop" case |
| 420 | else if (corners.size() == 1) { |
| 421 | int corner = corners[0]; |
| 422 | if (contour->edges.size() >= 3) { |
| 423 | int m = (int) contour->edges.size(); |
| 424 | for (int i = 0; i < m; ++i) { |
| 425 | if (i == m/2) |
| 426 | splineStarts.push_back((int) edgeSegments.size()); |
| 427 | if (symmetricalTrichotomy(i, m)) |
| 428 | edgeSegments.push_back(&*contour->edges[(corner+i)%m]); |
| 429 | else |
| 430 | contour->edges[(corner+i)%m]->color = WHITE; |
| 431 | } |
| 432 | } else if (contour->edges.size() >= 1) { |
| 433 | // Less than three edge segments for three colors => edges must be split |
| 434 | EdgeSegment *parts[7] = { }; |
| 435 | contour->edges[0]->splitInThirds(parts[0+3*corner], parts[1+3*corner], parts[2+3*corner]); |
| 436 | if (contour->edges.size() >= 2) { |
| 437 | contour->edges[1]->splitInThirds(parts[3-3*corner], parts[4-3*corner], parts[5-3*corner]); |
| 438 | edgeSegments.push_back(parts[0]); |
| 439 | edgeSegments.push_back(parts[1]); |
| 440 | parts[2]->color = parts[3]->color = WHITE; |
| 441 | splineStarts.push_back((int) edgeSegments.size()); |
| 442 | edgeSegments.push_back(parts[4]); |
| 443 | edgeSegments.push_back(parts[5]); |
| 444 | } else { |
| 445 | edgeSegments.push_back(parts[0]); |
| 446 | parts[1]->color = WHITE; |
| 447 | splineStarts.push_back((int) edgeSegments.size()); |
| 448 | edgeSegments.push_back(parts[2]); |
| 449 | } |
| 450 | contour->edges.clear(); |
| 451 | for (int i = 0; parts[i]; ++i) |
| 452 | contour->edges.push_back(EdgeHolder(parts[i])); |
nothing calls this directly
no test coverage detected