Skip to content

Commit

Permalink
Merge pull request #9 from P-yiush07/fixed-issue-08
Browse files Browse the repository at this point in the history
#8 Fixed the issue
  • Loading branch information
bertyhell authored Sep 30, 2024
2 parents 92b8da1 + f42e735 commit 399e406
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 104 deletions.
70 changes: 30 additions & 40 deletions src/entities/ArcEntity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,35 +23,15 @@ export class ArcEntity implements Entity {
}

constructor(
centerPointOrArc?: Point | Arc,
firstPoint?: Point,
secondPoint?: Point,
counterClockWise?: boolean,
centerPoint: Point,
radius: number,
startAngle: number,
endAngle: number,
counterClockwise: boolean = true
) {
if (centerPointOrArc instanceof Arc) {
const arc = centerPointOrArc as Arc;
this.arc = arc;
this.centerPoint = arc.center;
this.firstPoint = arc.start;
} else if (
centerPointOrArc instanceof Point &&
!firstPoint &&
!secondPoint
) {
this.centerPoint = centerPointOrArc;
} else if (centerPointOrArc && firstPoint && !secondPoint) {
this.firstPoint = firstPoint;
} else if (centerPointOrArc && firstPoint && secondPoint) {
const startAngle = ArcEntity.getAngle(centerPointOrArc, firstPoint);
const endAngle = ArcEntity.getAngle(centerPointOrArc, secondPoint);
this.arc = new Arc(
centerPointOrArc,
pointDistance(centerPointOrArc, firstPoint),
startAngle,
endAngle,
counterClockWise,
);
}
this.centerPoint = centerPoint;
this.arc = new Arc(centerPoint, radius, startAngle, endAngle, counterClockwise);
this.firstPoint = this.arc.start;
}

public draw(drawInfo: DrawInfo): void {
Expand Down Expand Up @@ -91,7 +71,8 @@ export class ArcEntity implements Entity {

public clone(): Entity {
if (this.arc) {
return new ArcEntity(this.arc.clone());
const { center, r, startAngle, endAngle, counterClockwise } = this.arc;
return new ArcEntity(center, r.valueOf(), startAngle, endAngle, counterClockwise);
}
return this;
}
Expand Down Expand Up @@ -185,7 +166,7 @@ export class ArcEntity implements Entity {
return this.arc.contains(point);
}

public cutAtPoints(pointsOnShape: Point[]): Entity[] {
public cutAtPoints(pointsOnShape: Point[]): ArcEntity[] {
if (!this.arc) {
return [this];
}
Expand All @@ -201,19 +182,24 @@ export class ArcEntity implements Entity {
this.arc.start,
);

const segmentArcs: Entity[] = [];
const segmentArcs: ArcEntity[] = [];
for (let i = 0; i < sortedPoints.length - 1; i++) {
// Create points from using the 2 points from pointOnLine and the center point of the circle
const point1 = sortedPoints[i];
const point2 = sortedPoints[i + 1];

const arc = new ArcEntity(
this.centerPoint || undefined,
point1,
point2,
this.arc.counterClockwise,
const startAngle = ArcEntity.getAngle(this.arc.center, point1);
const endAngle = ArcEntity.getAngle(this.arc.center, point2);

const newArc = new ArcEntity(
this.arc.center,
Number(this.arc.r),
startAngle,
endAngle,
this.arc.counterClockwise
);
segmentArcs.push(arc);
newArc.lineColor = this.lineColor;
newArc.lineWidth = this.lineWidth;
segmentArcs.push(newArc);
}
return segmentArcs;
}
Expand Down Expand Up @@ -255,8 +241,12 @@ export class ArcEntity implements Entity {
jsonEntity.shapeData.end.x,
jsonEntity.shapeData.end.y,
);
const radius = Number(center.distanceTo(start)[0]);
const startAngle = Number(ArcEntity.getAngle(center, start));
const endAngle = Number(ArcEntity.getAngle(center, end));
const counterClockwise = jsonEntity.shapeData.counterClockwise;
const arcEntity = new ArcEntity(center, start, end, counterClockwise);

const arcEntity = new ArcEntity(center, radius, startAngle, endAngle, counterClockwise);
arcEntity.id = jsonEntity.id;
arcEntity.lineColor = jsonEntity.lineColor;
arcEntity.lineWidth = jsonEntity.lineWidth;
Expand All @@ -269,4 +259,4 @@ export interface ArcJsonData {
start: { x: number; y: number };
end: { x: number; y: number };
counterClockwise: boolean;
}
}
35 changes: 13 additions & 22 deletions src/entities/CircleEntity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { DrawInfo, Shape, SnapPoint, SnapPointType } from '../App.types.ts';
import { Box, Circle, Point, Segment } from '@flatten-js/core';
import { worldToScreen } from '../helpers/world-screen-conversion.ts';
import { ArcEntity } from './ArcEntity.ts';
import { wrapModule } from '../helpers/wrap-module.ts';
import { pointDistance } from '../helpers/distance-between-points.ts';
import { getExportColor } from '../helpers/get-export-color.ts';

Expand Down Expand Up @@ -186,27 +185,15 @@ export class CircleEntity implements Entity {
}

public cutAtPoints(pointsOnShape: Point[]): Entity[] {
if (!this.circle) {
return [this];
}
const segmentArcs: Entity[] = [];

// Go around the circle and also connect the last and first point with an arc
const length = pointsOnShape.length;
for (let i = 0; i < length; i++) {
// Create points from using the 2 points from pointOnLine and the center point of the circle
const point1 = pointsOnShape[wrapModule(i, length)];
const point2 = pointsOnShape[wrapModule(i + 1, length)];

const arc = new ArcEntity(
this.centerPoint || undefined,
point1,
point2,
true,
);
segmentArcs.push(arc);
}
return segmentArcs;
if (!this.circle || !this.centerPoint) return [this];

const { centerPoint, circle } = this;
return pointsOnShape.map((point, i) => {
const nextPoint = pointsOnShape[(i + 1) % pointsOnShape.length];
const angle1 = Math.atan2(point.y - centerPoint.y, point.x - centerPoint.x);
const angle2 = Math.atan2(nextPoint.y - centerPoint.y, nextPoint.x - centerPoint.x);
return new ArcEntity(centerPoint, circle.r, angle1, angle2, true);
});
}

public async toJson(): Promise<JsonEntity<CircleJsonData> | null> {
Expand Down Expand Up @@ -239,6 +226,10 @@ export class CircleEntity implements Entity {
circleEntity.lineWidth = jsonEntity.lineWidth;
return circleEntity;
}

public getRadius(): number {
return this.circle?.r ?? 0;
}
}

export interface CircleJsonData {
Expand Down
77 changes: 35 additions & 42 deletions src/tools/eraser-tool.helpers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Entity } from '../entities/Entity.ts';
import { Point, Segment } from '@flatten-js/core';
import { Circle, Point, Segment } from '@flatten-js/core';
import { compact } from 'es-toolkit';
import { LineEntity } from '../entities/LineEntity.ts';
import { findNeighboringPointsOnLine } from '../helpers/find-neighboring-points-on-line.ts';
Expand Down Expand Up @@ -57,59 +57,52 @@ export function eraseCircleSegment(
clickedPointOnShape: Point,
intersections: Point[],
): void {
if (intersections.length === 0) {
deleteEntity(circle);
return;
}

const [firstCutPoint, secondCutPoint] = findNeighboringPointsOnCircle(
clickedPointOnShape,
circle,
intersections,
);

setDebugEntities(
[firstCutPoint, secondCutPoint].map(point => new PointEntity(point)),
);
const circleShape = circle.getShape() as Circle;
const center = circleShape.center;

const angles = [firstCutPoint, secondCutPoint, clickedPointOnShape].map(p =>
Math.atan2(p.y - center.y, p.x - center.x));

const [startAngle, endAngle] = isAngleBetween(angles[2], angles[0], angles[1])
? [angles[1], angles[0]]
: [angles[0], angles[1]];

const cutArcs: Entity[] = circle.cutAtPoints([firstCutPoint, secondCutPoint]);
const newArc = new ArcEntity(center, circleShape.r, startAngle, endAngle, true);
Object.assign(newArc, { lineColor: circle.lineColor, lineWidth: circle.lineWidth });

// Remove the arc segment that has the clickedPointOnShape point on it
if (isPointEqual(firstCutPoint, secondCutPoint)) {
// If one one intersection, delete the whole circle
deleteEntity(circle);
} else {
// Delete segment that contains the click point
const remainingArcs = cutArcs.filter(
arc => !arc.containsPointOnShape(clickedPointOnShape),
);
deleteEntity(circle);
addEntity(...remainingArcs);
}
deleteEntity(circle);
addEntity(newArc);
}

export function eraseArcSegment(
arc: ArcEntity,
clickedPointOnShape: Point,
intersections: Point[],
): void {
const [firstCutPoint, secondCutPoint] = findNeighboringPointsOnArc(
clickedPointOnShape,
arc,
intersections,
);

setDebugEntities(
[firstCutPoint, secondCutPoint].map(point => new PointEntity(point)),
);
function isAngleBetween(angle: number, start: number, end: number): boolean {
const twoPi = 2 * Math.PI;
return ((angle - start + twoPi) % twoPi) <= ((end - start + twoPi) % twoPi);
}

const cutArcs: Entity[] = arc.cutAtPoints([firstCutPoint, secondCutPoint]);
export function eraseArcSegment(arc: ArcEntity, clickedPointOnShape: Point, intersections: Point[]): void {
const [first, second] = findNeighboringPointsOnArc(clickedPointOnShape, arc, intersections);

// Remove the arc segment that has the clickedPointOnShape point on it
if (isPointEqual(firstCutPoint, secondCutPoint)) {
// If one one intersection, delete the whole circle
if (isPointEqual(first, second)) {
deleteEntity(arc);
} else {
// Delete segment that contains the click point
const remainingArcs = cutArcs.filter(
arc => !arc.containsPointOnShape(clickedPointOnShape),
);
deleteEntity(arc);
addEntity(...remainingArcs);
return;
}

deleteEntity(arc);
arc.cutAtPoints([first, second])
.filter(cutArc => !cutArc.containsPointOnShape(clickedPointOnShape))
.forEach(newArc => {
Object.assign(newArc, { lineColor: arc.lineColor, lineWidth: arc.lineWidth });
addEntity(newArc);
});
}

0 comments on commit 399e406

Please sign in to comment.