improve rotation
This commit is contained in:
parent
2a28064a68
commit
6582eb990c
4 changed files with 49 additions and 8 deletions
|
@ -2,7 +2,7 @@ import { v4 as uuid } from "uuid"
|
|||
import * as vec from "utils/vec"
|
||||
import { EllipseShape, ShapeType } from "types"
|
||||
import { registerShapeUtils } from "./index"
|
||||
import { boundsContained } from "utils/bounds"
|
||||
import { boundsContained, getRotatedEllipseBounds } from "utils/bounds"
|
||||
import { intersectEllipseBounds } from "utils/intersections"
|
||||
import { pointInEllipse } from "utils/hitTests"
|
||||
import {
|
||||
|
@ -47,8 +47,8 @@ const ellipse = registerShapeUtils<EllipseShape>({
|
|||
|
||||
const bounds = {
|
||||
minX: 0,
|
||||
maxX: radiusX * 2,
|
||||
minY: 0,
|
||||
maxX: radiusX * 2,
|
||||
maxY: radiusY * 2,
|
||||
width: radiusX * 2,
|
||||
height: radiusY * 2,
|
||||
|
@ -61,7 +61,13 @@ const ellipse = registerShapeUtils<EllipseShape>({
|
|||
},
|
||||
|
||||
getRotatedBounds(shape) {
|
||||
return getBoundsFromPoints(getRotatedCorners(shape))
|
||||
return getRotatedEllipseBounds(
|
||||
shape.point[0],
|
||||
shape.point[1],
|
||||
shape.radiusX,
|
||||
shape.radiusY,
|
||||
shape.rotation
|
||||
)
|
||||
},
|
||||
|
||||
getCenter(shape) {
|
||||
|
@ -79,8 +85,6 @@ const ellipse = registerShapeUtils<EllipseShape>({
|
|||
},
|
||||
|
||||
hitTestBounds(this, shape, brushBounds) {
|
||||
// TODO: Account for rotation
|
||||
|
||||
const shapeBounds = this.getBounds(shape)
|
||||
|
||||
return (
|
||||
|
@ -108,11 +112,16 @@ const ellipse = registerShapeUtils<EllipseShape>({
|
|||
return shape
|
||||
},
|
||||
|
||||
transform(shape, bounds) {
|
||||
transform(shape, bounds, { scaleX, scaleY, initialShape }) {
|
||||
shape.point = [bounds.minX, bounds.minY]
|
||||
shape.radiusX = bounds.width / 2
|
||||
shape.radiusY = bounds.height / 2
|
||||
|
||||
shape.rotation =
|
||||
(scaleX < 0 && scaleY >= 0) || (scaleY < 0 && scaleX >= 0)
|
||||
? -initialShape.rotation
|
||||
: initialShape.rotation
|
||||
|
||||
return shape
|
||||
},
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import BaseSession from "./base-session"
|
|||
import commands from "state/commands"
|
||||
import { current } from "immer"
|
||||
import {
|
||||
clampToRotationToSegments,
|
||||
getBoundsCenter,
|
||||
getCommonBounds,
|
||||
getPage,
|
||||
|
@ -31,10 +32,10 @@ export default class RotateSession extends BaseSession {
|
|||
const a1 = vec.angle(boundsCenter, this.origin)
|
||||
const a2 = vec.angle(boundsCenter, point)
|
||||
|
||||
let rot = (PI2 + (a2 - a1)) % PI2
|
||||
let rot = a2 - a1
|
||||
|
||||
if (isLocked) {
|
||||
rot = Math.floor((rot + Math.PI / 8) / (Math.PI / 4)) * (Math.PI / 4)
|
||||
rot = clampToRotationToSegments(rot, 24)
|
||||
}
|
||||
|
||||
data.boundsRotation = (PI2 + (this.snapshot.boundsRotation + rot)) % PI2
|
||||
|
|
|
@ -82,3 +82,25 @@ export function boundsAreEqual(a: Bounds, b: Bounds) {
|
|||
export function pointInBounds(A: number[], b: Bounds) {
|
||||
return !(A[0] < b.minX || A[0] > b.maxX || A[1] < b.minY || A[1] > b.maxY)
|
||||
}
|
||||
|
||||
export function getRotatedEllipseBounds(
|
||||
x: number,
|
||||
y: number,
|
||||
rx: number,
|
||||
ry: number,
|
||||
rotation: number
|
||||
) {
|
||||
const c = Math.cos(rotation)
|
||||
const s = Math.sin(rotation)
|
||||
const w = Math.hypot(rx * c, ry * s)
|
||||
const h = Math.hypot(rx * s, ry * c)
|
||||
|
||||
return {
|
||||
minX: x + rx - w,
|
||||
minY: y + ry - h,
|
||||
maxX: x + rx + w,
|
||||
maxY: y + ry + h,
|
||||
width: w * 2,
|
||||
height: h * 2,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1366,3 +1366,12 @@ export function getShapeBounds(shape: Shape) {
|
|||
export function getBoundsCenter(bounds: Bounds) {
|
||||
return [bounds.minX + bounds.width / 2, bounds.minY + bounds.height / 2]
|
||||
}
|
||||
|
||||
export function clampRadians(r: number) {
|
||||
return (Math.PI * 2 + r) % (Math.PI * 2)
|
||||
}
|
||||
|
||||
export function clampToRotationToSegments(r: number, segments: number) {
|
||||
const seg = (Math.PI * 2) / segments
|
||||
return Math.floor((clampRadians(r) + seg / 2) / seg) * seg
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue