From def78bb56e21ca3b7d2f26226ef9ac7b541d679f Mon Sep 17 00:00:00 2001 From: RuiAlonso Date: Mon, 28 Mar 2022 10:48:24 +0200 Subject: [PATCH] refactor: rotation on shapes --- packages/geometry/lib/src/geometry.dart | 9 +++-- .../lib/src/components/shapes/arc_shape.dart | 11 +++--- .../src/components/shapes/arc_shape_test.dart | 2 - .../shapes/bezier_curve_shape_test.dart | 37 +++++++++++------- .../components/shapes/ellipse_shape_test.dart | 39 ++++++++++--------- 5 files changed, 53 insertions(+), 45 deletions(-) diff --git a/packages/geometry/lib/src/geometry.dart b/packages/geometry/lib/src/geometry.dart index 8eea9e90..6975f8cb 100644 --- a/packages/geometry/lib/src/geometry.dart +++ b/packages/geometry/lib/src/geometry.dart @@ -5,8 +5,8 @@ import 'package:vector_math/vector_math_64.dart'; /// Calculates all [Vector2]s of a circumference. /// /// A circumference can be achieved by specifying a [center] and a [radius]. -/// In addition, a semi-circle can be achieved by specifying its [angle] in -/// radians. +/// In addition, a semi-circle can be achieved by specifying its [angle] and an +/// [offsetAngle] (both in radians). /// /// The higher the [precision], the more [Vector2]s will be calculated; /// achieving a more rounded arc. @@ -16,14 +16,15 @@ List calculateArc({ required Vector2 center, required double radius, required double angle, + double offsetAngle = 0, int precision = 100, }) { final stepAngle = angle / (precision - 1); final points = []; for (var i = 0; i < precision; i++) { - final x = center.x + radius * math.cos(stepAngle * i); - final y = center.y - radius * math.sin(stepAngle * i); + final x = center.x + radius * math.cos((stepAngle * i) + offsetAngle); + final y = center.y - radius * math.sin((stepAngle * i) + offsetAngle); final point = Vector2(x, y); points.add(point); diff --git a/packages/pinball_components/lib/src/components/shapes/arc_shape.dart b/packages/pinball_components/lib/src/components/shapes/arc_shape.dart index 3cd11cb0..8b31e223 100644 --- a/packages/pinball_components/lib/src/components/shapes/arc_shape.dart +++ b/packages/pinball_components/lib/src/components/shapes/arc_shape.dart @@ -1,6 +1,5 @@ // ignore_for_file: public_member_api_docs -import 'package:flame/extensions.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:geometry/geometry.dart'; @@ -13,12 +12,14 @@ class ArcShape extends ChainShape { required this.center, required this.arcRadius, required this.angle, + this.rotation = 0, }) { createChain( calculateArc( center: center, radius: arcRadius, angle: angle, + offsetAngle: rotation, ), ); } @@ -35,19 +36,19 @@ class ArcShape extends ChainShape { /// For example, two pi returns a complete circumference. final double angle; - /// Rotates the arc by a given [angle] in radians. - void rotate(double angle) { - vertices.map((vector) => vector..rotate(angle)).toList(); - } + /// Angle in radians to rotate the arc around its [center]. + final double rotation; ArcShape copyWith({ Vector2? center, double? arcRadius, double? angle, + double? rotation, }) => ArcShape( center: center ?? this.center, arcRadius: arcRadius ?? this.arcRadius, angle: angle ?? this.angle, + rotation: rotation ?? this.rotation, ); } diff --git a/packages/pinball_components/test/src/components/shapes/arc_shape_test.dart b/packages/pinball_components/test/src/components/shapes/arc_shape_test.dart index e5394d8a..fe778872 100644 --- a/packages/pinball_components/test/src/components/shapes/arc_shape_test.dart +++ b/packages/pinball_components/test/src/components/shapes/arc_shape_test.dart @@ -43,7 +43,6 @@ void main() { center: Vector2.all(10), arcRadius: 15, angle: 2 * math.pi, - rotation: math.pi, ); final arcShapeCopied = ArcShape( center: Vector2.zero(), @@ -53,7 +52,6 @@ void main() { center: Vector2.all(10), arcRadius: 15, angle: 2 * math.pi, - rotation: math.pi, ); for (var index = 0; index < arcShapeCopied.vertices.length; index++) { diff --git a/packages/pinball_components/test/src/components/shapes/bezier_curve_shape_test.dart b/packages/pinball_components/test/src/components/shapes/bezier_curve_shape_test.dart index 72be997d..6a6adeb7 100644 --- a/packages/pinball_components/test/src/components/shapes/bezier_curve_shape_test.dart +++ b/packages/pinball_components/test/src/components/shapes/bezier_curve_shape_test.dart @@ -22,23 +22,30 @@ void main() { ); }); - test('returns vertices rotated', () { - const rotationAngle = 2 * math.pi; + group('rotate', () { + test('returns vertices rotated', () { + const rotationAngle = 2 * math.pi; + final controlPoints = [ + Vector2(0, 0), + Vector2(10, 0), + Vector2(0, 10), + Vector2(10, 10), + ]; - final bezierCurveShape = BezierCurveShape( - controlPoints: controlPoints, - ); - final bezierCurveShapeRotated = BezierCurveShape( - controlPoints: controlPoints, - rotation: rotationAngle, - ); - - for (var index = 0; index < bezierCurveShape.vertices.length; index++) { - expect( - bezierCurveShape.vertices[index]..rotate(rotationAngle), - equals(bezierCurveShapeRotated.vertices[index]), + final bezierCurveShape = BezierCurveShape( + controlPoints: controlPoints, ); - } + final bezierCurveShapeRotated = BezierCurveShape( + controlPoints: controlPoints, + )..rotate(rotationAngle); + + for (var index = 0; index < bezierCurveShape.vertices.length; index++) { + expect( + bezierCurveShape.vertices[index]..rotate(rotationAngle), + equals(bezierCurveShapeRotated.vertices[index]), + ); + } + }); }); }); } diff --git a/packages/pinball_components/test/src/components/shapes/ellipse_shape_test.dart b/packages/pinball_components/test/src/components/shapes/ellipse_shape_test.dart index 45c1acb2..31f45cc1 100644 --- a/packages/pinball_components/test/src/components/shapes/ellipse_shape_test.dart +++ b/packages/pinball_components/test/src/components/shapes/ellipse_shape_test.dart @@ -17,26 +17,27 @@ void main() { ); }); - test('returns vertices rotated', () { - const rotationAngle = 2 * math.pi; - final ellipseShape = EllipseShape( - center: Vector2.zero(), - majorRadius: 10, - minorRadius: 8, - ); - final ellipseShapeRotated = EllipseShape( - center: Vector2.zero(), - majorRadius: 10, - minorRadius: 8, - rotation: rotationAngle, - ); - - for (var index = 0; index < ellipseShape.vertices.length; index++) { - expect( - ellipseShape.vertices[index]..rotate(rotationAngle), - equals(ellipseShapeRotated.vertices[index]), + group('rotate', () { + test('returns vertices rotated', () { + const rotationAngle = 2 * math.pi; + final ellipseShape = EllipseShape( + center: Vector2.zero(), + majorRadius: 10, + minorRadius: 8, ); - } + final ellipseShapeRotated = EllipseShape( + center: Vector2.zero(), + majorRadius: 10, + minorRadius: 8, + )..rotate(rotationAngle); + + for (var index = 0; index < ellipseShape.vertices.length; index++) { + expect( + ellipseShape.vertices[index]..rotate(rotationAngle), + equals(ellipseShapeRotated.vertices[index]), + ); + } + }); }); group('copyWith', () {