| 309 | } |
| 310 | |
| 311 | void ClipperOffset::OffsetPoint(Group& group, const Path64& path, size_t j, size_t k) |
| 312 | { |
| 313 | // Let A = change in angle where edges join |
| 314 | // A == 0: ie no change in angle (flat join) |
| 315 | // A == PI: edges 'spike' |
| 316 | // sin(A) < 0: right turning |
| 317 | // cos(A) < 0: change in angle is more than 90 degree |
| 318 | |
| 319 | if (path[j] == path[k]) return; |
| 320 | |
| 321 | double sin_a = CrossProduct(norms[j], norms[k]); |
| 322 | double cos_a = DotProduct(norms[j], norms[k]); |
| 323 | if (sin_a > 1.0) sin_a = 1.0; |
| 324 | else if (sin_a < -1.0) sin_a = -1.0; |
| 325 | |
| 326 | if (deltaCallback64_) { |
| 327 | group_delta_ = deltaCallback64_(path, norms, j, k); |
| 328 | if (group.is_reversed) group_delta_ = -group_delta_; |
| 329 | } |
| 330 | if (std::fabs(group_delta_) <= floating_point_tolerance) |
| 331 | { |
| 332 | path_out.emplace_back(path[j]); |
| 333 | return; |
| 334 | } |
| 335 | |
| 336 | if (cos_a > -0.999 && (sin_a * group_delta_ < 0)) // test for concavity first (#593) |
| 337 | { |
| 338 | // is concave |
| 339 | // by far the simplest way to construct concave joins, especially those joining very |
| 340 | // short segments, is to insert 3 points that produce negative regions. These regions |
| 341 | // will be removed later by the finishing union operation. This is also the best way |
| 342 | // to ensure that path reversals (ie over-shrunk paths) are removed. |
| 343 | #ifdef USINGZ |
| 344 | path_out.emplace_back(GetPerpendic(path[j], norms[k], group_delta_), path[j].z); |
| 345 | path_out.emplace_back(path[j]); // (#405, #873, #916) |
| 346 | path_out.emplace_back(GetPerpendic(path[j], norms[j], group_delta_), path[j].z); |
| 347 | #else |
| 348 | path_out.emplace_back(GetPerpendic(path[j], norms[k], group_delta_)); |
| 349 | path_out.emplace_back(path[j]); // (#405, #873, #916) |
| 350 | path_out.emplace_back(GetPerpendic(path[j], norms[j], group_delta_)); |
| 351 | #endif |
| 352 | } |
| 353 | else if (cos_a > 0.999 && join_type_ != JoinType::Round) |
| 354 | { |
| 355 | // almost straight - less than 2.5 degree (#424, #482, #526 & #724) |
| 356 | DoMiter(path, j, k, cos_a); |
| 357 | } |
| 358 | else if (join_type_ == JoinType::Miter) |
| 359 | { |
| 360 | // miter unless the angle is sufficiently acute to exceed ML |
| 361 | if (cos_a > temp_lim_ - 1) DoMiter(path, j, k, cos_a); |
| 362 | else DoSquare(path, j, k); |
| 363 | } |
| 364 | else if (join_type_ == JoinType::Round) |
| 365 | DoRound(path, j, k, std::atan2(sin_a, cos_a)); |
| 366 | else if ( join_type_ == JoinType::Bevel) |
| 367 | DoBevel(path, j, k); |
| 368 | else |
nothing calls this directly
no test coverage detected