Skip to content

Commit

Permalink
opt: merge render.
Browse files Browse the repository at this point in the history
  • Loading branch information
liihuu committed Mar 29, 2024
1 parent 7a4f045 commit 0eaf30f
Show file tree
Hide file tree
Showing 9 changed files with 296 additions and 238 deletions.
53 changes: 32 additions & 21 deletions src/extension/figure/arc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,34 @@ import { type FigureTemplate, DEVIATION } from '../../component/Figure'

import { type CircleAttrs } from './circle'

export function checkCoordinateOnArc (coordinate: Coordinate, arc: ArcAttrs): boolean {
if (Math.abs(getDistance(coordinate, arc) - arc.r) < DEVIATION) {
const { r, startAngle, endAngle } = arc
const startCoordinateX = r * Math.cos(startAngle) + arc.x
const startCoordinateY = r * Math.sin(startAngle) + arc.y
const endCoordinateX = r * Math.cos(endAngle) + arc.x
const endCoordinateY = r * Math.sin(endAngle) + arc.y
return (
coordinate.x <= Math.max(startCoordinateX, endCoordinateX) + DEVIATION &&
coordinate.x >= Math.min(startCoordinateX, endCoordinateX) - DEVIATION &&
coordinate.y <= Math.max(startCoordinateY, endCoordinateY) + DEVIATION &&
coordinate.y >= Math.min(startCoordinateY, endCoordinateY) - DEVIATION
)
export function checkCoordinateOnArc (coordinate: Coordinate, attrs: ArcAttrs | ArcAttrs[]): boolean {
let arcs: ArcAttrs[] = []
arcs = arcs.concat(attrs)
for (let i = 0; i < arcs.length; i++) {
const arc = arcs[i]
if (Math.abs(getDistance(coordinate, arc) - arc.r) < DEVIATION) {
const { r, startAngle, endAngle } = arc
const startCoordinateX = r * Math.cos(startAngle) + arc.x
const startCoordinateY = r * Math.sin(startAngle) + arc.y
const endCoordinateX = r * Math.cos(endAngle) + arc.x
const endCoordinateY = r * Math.sin(endAngle) + arc.y
if (
coordinate.x <= Math.max(startCoordinateX, endCoordinateX) + DEVIATION &&
coordinate.x >= Math.min(startCoordinateX, endCoordinateX) - DEVIATION &&
coordinate.y <= Math.max(startCoordinateY, endCoordinateY) + DEVIATION &&
coordinate.y >= Math.min(startCoordinateY, endCoordinateY) - DEVIATION
) {
return true
}
}
}

return false
}

export function drawArc (ctx: CanvasRenderingContext2D, attrs: ArcAttrs, styles: Partial<LineStyle>): void {
const { x, y, r, startAngle, endAngle } = attrs
export function drawArc (ctx: CanvasRenderingContext2D, attrs: ArcAttrs | ArcAttrs[], styles: Partial<LineStyle>): void {
let arcs: ArcAttrs[] = []
arcs = arcs.concat(attrs)
const { style = LineType.Solid, size = 1, color = 'currentColor', dashedValue = [2, 2] } = styles
ctx.lineWidth = size
ctx.strokeStyle = color
Expand All @@ -47,21 +56,23 @@ export function drawArc (ctx: CanvasRenderingContext2D, attrs: ArcAttrs, styles:
} else {
ctx.setLineDash([])
}
ctx.beginPath()
ctx.arc(x, y, r, startAngle, endAngle)
ctx.stroke()
ctx.closePath()
arcs.forEach(({ x, y, r, startAngle, endAngle }) => {
ctx.beginPath()
ctx.arc(x, y, r, startAngle, endAngle)
ctx.stroke()
ctx.closePath()
})
}

export interface ArcAttrs extends CircleAttrs {
startAngle: number
endAngle: number
}

const arc: FigureTemplate<ArcAttrs, Partial<LineStyle>> = {
const arc: FigureTemplate<ArcAttrs | ArcAttrs[], Partial<LineStyle>> = {
name: 'arc',
checkEventOn: checkCoordinateOnArc,
draw: (ctx: CanvasRenderingContext2D, attrs: ArcAttrs, styles: Partial<LineStyle>) => {
draw: (ctx: CanvasRenderingContext2D, attrs: ArcAttrs | ArcAttrs[], styles: Partial<LineStyle>) => {
drawArc(ctx, attrs, styles)
}
}
Expand Down
48 changes: 31 additions & 17 deletions src/extension/figure/circle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,25 @@ import { isTransparent } from '../../common/utils/color'

import { type FigureTemplate } from '../../component/Figure'

export function checkCoordinateOnCircle (coordinate: Coordinate, circle: CircleAttrs): boolean {
const difX = coordinate.x - circle.x
const difY = coordinate.y - circle.y
const r = circle.r
return !(difX * difX + difY * difY > r * r)
export function checkCoordinateOnCircle (coordinate: Coordinate, attrs: CircleAttrs | CircleAttrs[]): boolean {
let circles: CircleAttrs[] = []
circles = circles.concat(attrs)

for (let i = 0; i < circles.length; i++) {
const { x, y, r } = circles[i]
const difX = coordinate.x - x
const difY = coordinate.y - y
if (!(difX * difX + difY * difY > r * r)) {
return true
}
}
return false
}

export function drawCircle (ctx: CanvasRenderingContext2D, attrs: CircleAttrs, styles: Partial<PolygonStyle>): void {
const { x, y, r } = attrs
export function drawCircle (ctx: CanvasRenderingContext2D, attrs: CircleAttrs | CircleAttrs[], styles: Partial<PolygonStyle>): void {
let circles: CircleAttrs[] = []
circles = circles.concat(attrs)

const {
style = PolygonType.Fill,
color = 'currentColor',
Expand All @@ -41,10 +51,12 @@ export function drawCircle (ctx: CanvasRenderingContext2D, attrs: CircleAttrs, s
(!isString(color) || !isTransparent(color))
) {
ctx.fillStyle = color
ctx.beginPath()
ctx.arc(x, y, r, 0, Math.PI * 2)
ctx.closePath()
ctx.fill()
circles.forEach(({ x, y, r }) => {
ctx.beginPath()
ctx.arc(x, y, r, 0, Math.PI * 2)
ctx.closePath()
ctx.fill()
})
}
if ((style === PolygonType.Stroke || styles.style === PolygonType.StrokeFill) && borderSize > 0 && !isTransparent(borderColor)) {
ctx.strokeStyle = borderColor
Expand All @@ -54,10 +66,12 @@ export function drawCircle (ctx: CanvasRenderingContext2D, attrs: CircleAttrs, s
} else {
ctx.setLineDash([])
}
ctx.beginPath()
ctx.arc(x, y, r, 0, Math.PI * 2)
ctx.closePath()
ctx.stroke()
circles.forEach(({ x, y, r }) => {
ctx.beginPath()
ctx.arc(x, y, r, 0, Math.PI * 2)
ctx.closePath()
ctx.stroke()
})
}
}

Expand All @@ -67,10 +81,10 @@ export interface CircleAttrs {
r: number
}

const circle: FigureTemplate<CircleAttrs, Partial<PolygonStyle>> = {
const circle: FigureTemplate<CircleAttrs | CircleAttrs[], Partial<PolygonStyle>> = {
name: 'circle',
checkEventOn: checkCoordinateOnCircle,
draw: (ctx: CanvasRenderingContext2D, attrs: CircleAttrs, styles: Partial<PolygonStyle>) => {
draw: (ctx: CanvasRenderingContext2D, attrs: CircleAttrs | CircleAttrs[], styles: Partial<PolygonStyle>) => {
drawCircle(ctx, attrs, styles)
}
}
Expand Down
88 changes: 48 additions & 40 deletions src/extension/figure/line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,33 @@ import { type SmoothLineStyle, LineType } from '../../common/Styles'
import { type FigureTemplate, DEVIATION } from '../../component/Figure'
import { isNumber } from '../../common/utils/typeChecks'

export function checkCoordinateOnLine (coordinate: Coordinate, line: LineAttrs): boolean {
const coordinates = line.coordinates
if (coordinates.length > 1) {
for (let i = 1; i < coordinates.length; i++) {
const prevCoordinate = coordinates[i - 1]
const currentCoordinate = coordinates[i]
if (prevCoordinate.x === currentCoordinate.x) {
if (
Math.abs(prevCoordinate.y - coordinate.y) + Math.abs(currentCoordinate.y - coordinate.y) - Math.abs(prevCoordinate.y - currentCoordinate.y) < DEVIATION + DEVIATION &&
Math.abs(coordinate.x - prevCoordinate.x) < DEVIATION
) {
return true
}
} else {
const kb = getLinearSlopeIntercept(prevCoordinate, currentCoordinate)!
const y = getLinearYFromSlopeIntercept(kb, coordinate)
const yDif = Math.abs(y - coordinate.y)
if (
Math.abs(prevCoordinate.x - coordinate.x) + Math.abs(currentCoordinate.x - coordinate.x) - Math.abs(prevCoordinate.x - currentCoordinate.x) < DEVIATION + DEVIATION &&
yDif * yDif / (kb[0] * kb[0] + 1) < DEVIATION * DEVIATION
) {
return true
export function checkCoordinateOnLine (coordinate: Coordinate, attrs: LineAttrs | LineAttrs[]): boolean {
let lines: LineAttrs[] = []
lines = lines.concat(attrs)

for (let i = 0; i < lines.length; i++) {
const { coordinates } = lines[i]
if (coordinates.length > 1) {
for (let i = 1; i < coordinates.length; i++) {
const prevCoordinate = coordinates[i - 1]
const currentCoordinate = coordinates[i]
if (prevCoordinate.x === currentCoordinate.x) {
if (
Math.abs(prevCoordinate.y - coordinate.y) + Math.abs(currentCoordinate.y - coordinate.y) - Math.abs(prevCoordinate.y - currentCoordinate.y) < DEVIATION + DEVIATION &&
Math.abs(coordinate.x - prevCoordinate.x) < DEVIATION
) {
return true
}
} else {
const kb = getLinearSlopeIntercept(prevCoordinate, currentCoordinate)!
const y = getLinearYFromSlopeIntercept(kb, coordinate)
const yDif = Math.abs(y - coordinate.y)
if (
Math.abs(prevCoordinate.x - coordinate.x) + Math.abs(currentCoordinate.x - coordinate.x) - Math.abs(prevCoordinate.x - currentCoordinate.x) < DEVIATION + DEVIATION &&
yDif * yDif / (kb[0] * kb[0] + 1) < DEVIATION * DEVIATION
) {
return true
}
}
}
}
Expand Down Expand Up @@ -133,33 +138,36 @@ export function lineTo (ctx: CanvasRenderingContext2D, coordinates: Coordinate[]
}
}

export function drawLine (ctx: CanvasRenderingContext2D, attrs: LineAttrs, styles: Partial<SmoothLineStyle>): void {
const { coordinates } = attrs
if (coordinates.length > 1) {
const { style = LineType.Solid, smooth = false, size = 1, color = 'currentColor', dashedValue = [2, 2] } = styles
ctx.lineWidth = size
ctx.strokeStyle = color
if (style === LineType.Dashed) {
ctx.setLineDash(dashedValue)
} else {
ctx.setLineDash([])
}
ctx.beginPath()
ctx.moveTo(coordinates[0].x, coordinates[0].y)
lineTo(ctx, coordinates, smooth)
ctx.stroke()
ctx.closePath()
export function drawLine (ctx: CanvasRenderingContext2D, attrs: LineAttrs | LineAttrs[], styles: Partial<SmoothLineStyle>): void {
let lines: LineAttrs[] = []
lines = lines.concat(attrs)
const { style = LineType.Solid, smooth = false, size = 1, color = 'currentColor', dashedValue = [2, 2] } = styles
ctx.lineWidth = size
ctx.strokeStyle = color
if (style === LineType.Dashed) {
ctx.setLineDash(dashedValue)
} else {
ctx.setLineDash([])
}
lines.forEach(({ coordinates }) => {
if (coordinates.length > 1) {
ctx.beginPath()
ctx.moveTo(coordinates[0].x, coordinates[0].y)
lineTo(ctx, coordinates, smooth)
ctx.stroke()
ctx.closePath()
}
})
}

export interface LineAttrs {
coordinates: Coordinate[]
}

const line: FigureTemplate<LineAttrs, Partial<SmoothLineStyle>> = {
const line: FigureTemplate<LineAttrs | LineAttrs[], Partial<SmoothLineStyle>> = {
name: 'line',
checkEventOn: checkCoordinateOnLine,
draw: (ctx: CanvasRenderingContext2D, attrs: LineAttrs, styles: Partial<SmoothLineStyle>) => {
draw: (ctx: CanvasRenderingContext2D, attrs: LineAttrs | LineAttrs[], styles: Partial<SmoothLineStyle>) => {
drawLine(ctx, attrs, styles)
}
}
Expand Down
68 changes: 40 additions & 28 deletions src/extension/figure/polygon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,30 @@ import { isTransparent } from '../../common/utils/color'

import { type FigureTemplate } from '../../component/Figure'

export function checkCoordinateOnPolygon (coordinate: Coordinate, polygon: PolygonAttrs): boolean {
let on = false
const coordinates = polygon.coordinates
for (let i = 0, j = coordinates.length - 1; i < coordinates.length; j = i++) {
if (
(coordinates[i].y > coordinate.y) !== (coordinates[j].y > coordinate.y) &&
(coordinate.x < (coordinates[j].x - coordinates[i].x) * (coordinate.y - coordinates[i].y) / (coordinates[j].y - coordinates[i].y) + coordinates[i].x)
) {
on = !on
export function checkCoordinateOnPolygon (coordinate: Coordinate, attrs: PolygonAttrs | PolygonAttrs[]): boolean {
let polygons: PolygonAttrs[] = []
polygons = polygons.concat(attrs)
for (let i = 0; i < polygons.length; i++) {
let on = false
const { coordinates } = polygons[i]
for (let i = 0, j = coordinates.length - 1; i < coordinates.length; j = i++) {
if (
(coordinates[i].y > coordinate.y) !== (coordinates[j].y > coordinate.y) &&
(coordinate.x < (coordinates[j].x - coordinates[i].x) * (coordinate.y - coordinates[i].y) / (coordinates[j].y - coordinates[i].y) + coordinates[i].x)
) {
on = !on
}
}
if (on) {
return true
}
}
return on
return false
}

export function drawPolygon (ctx: CanvasRenderingContext2D, attrs: PolygonAttrs, styles: Partial<PolygonStyle>): void {
const { coordinates } = attrs
export function drawPolygon (ctx: CanvasRenderingContext2D, attrs: PolygonAttrs | PolygonAttrs[], styles: Partial<PolygonStyle>): void {
let polygons: PolygonAttrs[] = []
polygons = polygons.concat(attrs)
const {
style = PolygonType.Fill,
color = 'currentColor',
Expand All @@ -47,13 +55,15 @@ export function drawPolygon (ctx: CanvasRenderingContext2D, attrs: PolygonAttrs,
(style === PolygonType.Fill || styles.style === PolygonType.StrokeFill) &&
(!isString(color) || !isTransparent(color))) {
ctx.fillStyle = color
ctx.beginPath()
ctx.moveTo(coordinates[0].x, coordinates[0].y)
for (let i = 1; i < coordinates.length; i++) {
ctx.lineTo(coordinates[i].x, coordinates[i].y)
}
ctx.closePath()
ctx.fill()
polygons.forEach(({ coordinates }) => {
ctx.beginPath()
ctx.moveTo(coordinates[0].x, coordinates[0].y)
for (let i = 1; i < coordinates.length; i++) {
ctx.lineTo(coordinates[i].x, coordinates[i].y)
}
ctx.closePath()
ctx.fill()
})
}
if ((style === PolygonType.Stroke || styles.style === PolygonType.StrokeFill) && borderSize > 0 && !isTransparent(borderColor)) {
ctx.strokeStyle = borderColor
Expand All @@ -63,24 +73,26 @@ export function drawPolygon (ctx: CanvasRenderingContext2D, attrs: PolygonAttrs,
} else {
ctx.setLineDash([])
}
ctx.beginPath()
ctx.moveTo(coordinates[0].x, coordinates[0].y)
for (let i = 1; i < coordinates.length; i++) {
ctx.lineTo(coordinates[i].x, coordinates[i].y)
}
ctx.closePath()
ctx.stroke()
polygons.forEach(({ coordinates }) => {
ctx.beginPath()
ctx.moveTo(coordinates[0].x, coordinates[0].y)
for (let i = 1; i < coordinates.length; i++) {
ctx.lineTo(coordinates[i].x, coordinates[i].y)
}
ctx.closePath()
ctx.stroke()
})
}
}

export interface PolygonAttrs {
coordinates: Coordinate[]
}

const polygon: FigureTemplate<PolygonAttrs, Partial<PolygonStyle>> = {
const polygon: FigureTemplate<PolygonAttrs | PolygonAttrs[], Partial<PolygonStyle>> = {
name: 'polygon',
checkEventOn: checkCoordinateOnPolygon,
draw: (ctx: CanvasRenderingContext2D, attrs: PolygonAttrs, styles: Partial<PolygonStyle>) => {
draw: (ctx: CanvasRenderingContext2D, attrs: PolygonAttrs | PolygonAttrs[], styles: Partial<PolygonStyle>) => {
drawPolygon(ctx, attrs, styles)
}
}
Expand Down
Loading

0 comments on commit 0eaf30f

Please sign in to comment.