diff --git a/geom/alg_rotated_mbr.go b/geom/alg_rotated_mbr.go index 722bbac4..cecb2b38 100644 --- a/geom/alg_rotated_mbr.go +++ b/geom/alg_rotated_mbr.go @@ -47,14 +47,15 @@ func RotatedMinimumBoundingRectangle(g Geometry) Geometry { } advance := func(idx *int, dist func() float64) { + d0 := dist() for { - d0 := dist() *idx = (*idx + 1) % seq.Length() d1 := dist() if d1 < d0 { - *idx = (*idx + seq.Length() - 1) % seq.Length() + *idx = (*idx - 1) % seq.Length() break } + d0 = d1 } } @@ -66,18 +67,22 @@ func RotatedMinimumBoundingRectangle(g Geometry) Geometry { lhsIdx = farIdx advance(&lhsIdx, lhsDist) - bestBaseLine := getLine() - bestRHSDist := rhsDist() - bestFarDist := farDist() - bestLHSDist := lhsDist() - bestArea := bestFarDist * (bestRHSDist + bestLHSDist) + best := struct { + base int + rhs int + far int + lhs int + area float64 + }{ + lnIdx, rhsIdx, farIdx, lhsIdx, + farDist() * (rhsDist() + lhsDist()), + } for { lnIdx++ if lnIdx+1 == seq.Length() { break } - ln := getLine() // Advance calipers: advance(&rhsIdx, rhsDist) @@ -85,22 +90,29 @@ func RotatedMinimumBoundingRectangle(g Geometry) Geometry { advance(&lhsIdx, lhsDist) area := farDist() * (rhsDist() + lhsDist()) - if area < bestArea { - bestBaseLine = ln - bestArea = area - bestRHSDist = rhsDist() - bestFarDist = farDist() - bestLHSDist = lhsDist() + if area < best.area { + best.base = lnIdx + best.area = area + best.rhs = rhsIdx + best.far = farIdx + best.lhs = lhsIdx } } - rhsBasis := bestBaseLine.b.Sub(bestBaseLine.a).Unit() + lnIdx = best.base + rhsIdx = best.rhs + farIdx = best.far + lhsIdx = best.lhs + + baseLine := getLine() + + rhsBasis := baseLine.b.Sub(baseLine.a).Unit() farBasis := rhsBasis.rotateCCW90() - farVec := farBasis.Scale(bestFarDist) - rhsVec := rhsBasis.Scale(bestRHSDist) - lhsVec := rhsBasis.Scale(-bestLHSDist) - origin := bestBaseLine.a + rhsVec := rhsBasis.Scale(rhsDist()) + farVec := farBasis.Scale(farDist()) + lhsVec := rhsBasis.Scale(-lhsDist()) + origin := baseLine.a pt0 := origin.Add(lhsVec) pt1 := origin.Add(rhsVec)