feat(shortcut): ,/
This commit is contained in:
@@ -2866,6 +2866,96 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
return nextData
|
||||
}
|
||||
|
||||
const getSegmentPoint = (segment: any): [number, number] | null => {
|
||||
if (
|
||||
Array.isArray(segment) &&
|
||||
segment.length >= 2 &&
|
||||
typeof segment[0] === "number" &&
|
||||
typeof segment[1] === "number"
|
||||
) {
|
||||
return [segment[0], segment[1]]
|
||||
}
|
||||
if (
|
||||
Array.isArray(segment) &&
|
||||
Array.isArray(segment[0]) &&
|
||||
segment[0].length >= 2 &&
|
||||
typeof segment[0][0] === "number" &&
|
||||
typeof segment[0][1] === "number"
|
||||
) {
|
||||
return [segment[0][0], segment[0][1]]
|
||||
}
|
||||
if (
|
||||
segment?.point &&
|
||||
typeof segment.point.x === "number" &&
|
||||
typeof segment.point.y === "number"
|
||||
) {
|
||||
return [segment.point.x, segment.point.y]
|
||||
}
|
||||
if (
|
||||
segment?.point &&
|
||||
Array.isArray(segment.point) &&
|
||||
segment.point.length >= 2 &&
|
||||
typeof segment.point[0] === "number" &&
|
||||
typeof segment.point[1] === "number"
|
||||
) {
|
||||
return [segment.point[0], segment.point[1]]
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
const normalizePolygonFromSegments = (segments: any[]) => {
|
||||
const polygon = (segments || [])
|
||||
.map((segment) => getSegmentPoint(segment))
|
||||
.filter((point): point is [number, number] => !!point)
|
||||
|
||||
if (polygon.length > 1) {
|
||||
const [firstX, firstY] = polygon[0]
|
||||
const [lastX, lastY] = polygon[polygon.length - 1]
|
||||
if (
|
||||
Math.abs(firstX - lastX) < 0.000001 &&
|
||||
Math.abs(firstY - lastY) < 0.000001
|
||||
) {
|
||||
polygon.pop()
|
||||
}
|
||||
}
|
||||
return polygon
|
||||
}
|
||||
|
||||
const isPointInPolygon = (
|
||||
point: [number, number],
|
||||
polygon: [number, number][]
|
||||
) => {
|
||||
if (polygon.length < 3) return false
|
||||
const [x, y] = point
|
||||
let inside = false
|
||||
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
||||
const [xi, yi] = polygon[i]
|
||||
const [xj, yj] = polygon[j]
|
||||
const dy = yj - yi
|
||||
if (yi > y !== yj > y) {
|
||||
const crossX = ((xj - xi) * (y - yi)) / (dy || 0.000001) + xi
|
||||
if (x < crossX) inside = !inside
|
||||
}
|
||||
}
|
||||
return inside
|
||||
}
|
||||
|
||||
const getHollowFlagsByContainment = (allSegments: any[][]) => {
|
||||
const polygons = allSegments.map((segments) =>
|
||||
normalizePolygonFromSegments(segments)
|
||||
)
|
||||
return polygons.map((polygon, index) => {
|
||||
if (polygon.length < 3) return false
|
||||
const samplePoint = polygon[0]
|
||||
let containDepth = 0
|
||||
polygons.forEach((otherPolygon, otherIndex) => {
|
||||
if (otherIndex === index || otherPolygon.length < 3) return
|
||||
if (isPointInPolygon(samplePoint, otherPolygon)) containDepth += 1
|
||||
})
|
||||
return containDepth % 2 === 1
|
||||
})
|
||||
}
|
||||
|
||||
const handleSelectedPolygonSubtract = (draftPath: paper.Path) => {
|
||||
const activeImage = useBottomToolsStore.getState().activeImage
|
||||
const selectedIds =
|
||||
@@ -2915,36 +3005,37 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
clippedDraft = null
|
||||
targetShape.remove()
|
||||
|
||||
if (nextPolygon instanceof paper.CompoundPath) {
|
||||
nextPolygon.data = Object.assign({}, targetData)
|
||||
;(nextPolygon.children as paper.Path[]).forEach((child) => {
|
||||
child.data = Object.assign({}, targetData, {
|
||||
isHollowPolygon: !child.clockwise,
|
||||
})
|
||||
})
|
||||
} else {
|
||||
nextPolygon.data = Object.assign({}, targetData)
|
||||
}
|
||||
|
||||
const points: any[] = []
|
||||
const hollowPoints: any[] = []
|
||||
const collectPathPoints = (path: paper.Path) => {
|
||||
if (!path.segments?.length) return
|
||||
const nextPaths =
|
||||
nextPolygon instanceof paper.CompoundPath
|
||||
? (nextPolygon.children as paper.Path[])
|
||||
: ([nextPolygon] as paper.Path[])
|
||||
const nextPathSegments = nextPaths.map((path) => {
|
||||
if (!path.segments?.length) return null
|
||||
const pathData = JSON.parse(path.exportJSON({ precision: 20 }))
|
||||
if (path.clockwise) {
|
||||
points.push(pathData[1]?.segments)
|
||||
} else {
|
||||
hollowPoints.push(pathData[1]?.segments)
|
||||
}
|
||||
}
|
||||
return pathData?.[1]?.segments || null
|
||||
})
|
||||
const hollowFlags = getHollowFlagsByContainment(
|
||||
nextPathSegments.map((segments) => segments || [])
|
||||
)
|
||||
|
||||
if (nextPolygon instanceof paper.CompoundPath) {
|
||||
;(nextPolygon.children as paper.Path[]).forEach((child) => {
|
||||
collectPathPoints(child)
|
||||
})
|
||||
} else {
|
||||
collectPathPoints(nextPolygon)
|
||||
nextPolygon.data = Object.assign({}, targetData)
|
||||
}
|
||||
nextPaths.forEach((path, index) => {
|
||||
const segments = nextPathSegments[index]
|
||||
if (!segments?.length) return
|
||||
const isHollowPolygon = !!hollowFlags[index]
|
||||
path.data = Object.assign({}, targetData, {
|
||||
isHollowPolygon,
|
||||
})
|
||||
if (isHollowPolygon) {
|
||||
hollowPoints.push(segments)
|
||||
} else {
|
||||
points.push(segments)
|
||||
}
|
||||
})
|
||||
|
||||
const operationId = (
|
||||
targetData.operationId ||
|
||||
|
||||
Reference in New Issue
Block a user