| 343 | } |
| 344 | |
| 345 | func flattenEllipticArc(start Point, rx, ry, phi float64, large, sweep bool, end Point, tolerance float64) *Path { |
| 346 | if Equal(rx, ry) { |
| 347 | // circle |
| 348 | r := rx |
| 349 | cx, cy, theta0, theta1 := ellipseToCenter(start.X, start.Y, rx, ry, phi, large, sweep, end.X, end.Y) |
| 350 | theta0 += phi |
| 351 | theta1 += phi |
| 352 | |
| 353 | // draw line segments from arc+tolerance to arc+tolerance, touching arc-tolerance in between |
| 354 | // we start and end at the arc itself |
| 355 | dtheta := math.Abs(theta1 - theta0) |
| 356 | thetaEnd := math.Acos((r - tolerance) / r) // half angle of first/last segment |
| 357 | thetaMid := math.Acos((r - tolerance) / (r + tolerance)) // half angle of middle segments |
| 358 | n := math.Ceil((dtheta - thetaEnd*2.0) / (thetaMid * 2.0)) |
| 359 | |
| 360 | // evenly space out points along arc |
| 361 | ratio := dtheta / (thetaEnd*2.0 + thetaMid*2.0*n) |
| 362 | thetaEnd *= ratio |
| 363 | thetaMid *= ratio |
| 364 | |
| 365 | // adjust distance from arc to lower total deviation area, add points on the outer circle |
| 366 | // of the tolerance since the middle of the line segment touches the inner circle and thus |
| 367 | // even out. Ratio < 1 is when the line segments are shorter (and thus not touch the inner |
| 368 | // tolerance circle). |
| 369 | r += ratio * tolerance |
| 370 | |
| 371 | p := &Path{} |
| 372 | p.MoveTo(start.X, start.Y) |
| 373 | theta := thetaEnd + thetaMid |
| 374 | for i := 0; i < int(n); i++ { |
| 375 | t := theta0 + math.Copysign(theta, theta1-theta0) |
| 376 | pos := PolarPoint(t, r).Add(Point{cx, cy}) |
| 377 | p.LineTo(pos.X, pos.Y) |
| 378 | theta += 2.0 * thetaMid |
| 379 | } |
| 380 | p.LineTo(end.X, end.Y) |
| 381 | return p |
| 382 | } |
| 383 | // TODO: (flatten ellipse) use direct algorithm |
| 384 | return arcToCube(start, rx, ry, phi, large, sweep, end).Flatten(tolerance) |
| 385 | } |
| 386 | |
| 387 | //////////////////////////////////////////////////////////////// |
| 388 | // Béziers ///////////////////////////////////////////////////// |