fix(label): ,/

This commit is contained in:
zhangheng
2026-04-17 11:43:19 +08:00
parent 47b56412b7
commit 99a4542d46
2 changed files with 611 additions and 512 deletions

View File

@@ -1692,29 +1692,6 @@ const LabelPage = ({
[]
)
const removeObjectFromGroupMap = useCallback(
(imageId: string, id: number) => {
const nextPathGroupMap = safeClone(
useRightToolsStore.getState().pathGroupMap
)
const imageGroupMap = nextPathGroupMap.get(imageId)
if (!imageGroupMap) return
for (let [groupId, pathIds] of imageGroupMap.entries()) {
const nextPathIds = pathIds.filter((pathId) => pathId !== id)
if (nextPathIds.length > 1) {
imageGroupMap.set(groupId, nextPathIds)
} else {
imageGroupMap.delete(groupId)
}
}
if (!imageGroupMap.size) nextPathGroupMap.delete(imageId)
useRightToolsStore.getState().setPathGroupMap(nextPathGroupMap)
},
[]
)
const handleContinueSelectedPolygon = useCallback(() => {
const selectedContext = resolveSelectedObjectContext()
if (!selectedContext) {
@@ -1758,70 +1735,6 @@ const LabelPage = ({
setPressA,
])
const hasShapeSegments = useCallback((shape: any) => {
if (!shape) return false
if (shape instanceof paper.CompoundPath) {
return (shape.children as paper.Path[]).some(
(child) => child.segments?.length
)
}
if (shape instanceof paper.Path) {
return !!shape.segments?.length
}
return false
}, [])
const createWorkingPolygonShape = useCallback((items: any[]) => {
const compound = items.find((item) => item instanceof paper.CompoundPath)
if (compound) {
return (compound as paper.CompoundPath).clone({ insert: false }) as
| paper.Path
| paper.CompoundPath
}
const paths = items.filter(
(item) => item instanceof paper.Path
) as paper.Path[]
if (!paths.length) return null
if (paths.length === 1) {
return paths[0].clone({ insert: false }) as
| paper.Path
| paper.CompoundPath
}
const merged = new paper.CompoundPath({ insert: false })
paths.forEach((path) => {
merged.addChild(path.clone({ insert: false }))
})
return merged as paper.Path | paper.CompoundPath
}, [])
const collectPolygonPoints = useCallback(
(shape: paper.Path | paper.CompoundPath) => {
const polygonPoints: any[] = []
const polygonHollowPoints: any[] = []
const collectPath = (path: paper.Path) => {
if (!path.segments?.length) return
const pathData = JSON.parse(path.exportJSON({ precision: 20 }))
if (path.clockwise) {
polygonPoints.push(pathData[1]?.segments)
} else {
polygonHollowPoints.push(pathData[1]?.segments)
}
}
if (shape instanceof paper.CompoundPath) {
;(shape.children as paper.Path[]).forEach((path) => collectPath(path))
} else {
collectPath(shape)
}
return { polygonPoints, polygonHollowPoints }
},
[]
)
const applySelectedPolygonOverlap = useCallback(
(mode: "subtract" | "unite") => {
const selectedContext = resolveSelectedObjectContext()
@@ -1842,138 +1755,9 @@ const LabelPage = ({
})
return
}
const group = usePaperStore.getState().group
if (!group) return
const targetItems = group
.getItems({ data: { id: selectedContext.objectId } })
.filter((item) => item.data?.type === "polygon")
if (!targetItems.length) return
let workingShape = createWorkingPolygonShape(targetItems)
if (!workingShape || !hasShapeSegments(workingShape)) return
const otherPolygonPaths: paper.Path[] = []
group.children.forEach((item: any) => {
if (
!item.visible ||
!item.data?.id ||
item.data.id === selectedContext.objectId ||
item.data.type !== "polygon"
)
return
if (item instanceof paper.Path) {
if (item.segments?.length) otherPolygonPaths.push(item)
} else if (item instanceof paper.CompoundPath) {
;(item.children as paper.Path[]).forEach((child) => {
if (child.segments?.length) otherPolygonPaths.push(child)
})
}
})
let changed = false
for (const eachPath of otherPolygonPaths) {
if (!workingShape || !hasShapeSegments(workingShape)) break
const eachPathClone = eachPath.clone({ insert: false }) as paper.Path
const intersectionPath = (workingShape as any).intersect(
eachPathClone,
{
insert: false,
}
) as paper.Path | paper.CompoundPath
const hasIntersection = hasShapeSegments(intersectionPath)
intersectionPath?.remove()
if (!hasIntersection) {
eachPathClone.remove()
continue
}
const nextShape: paper.Path | paper.CompoundPath =
mode === "subtract"
? ((workingShape as any).subtract(eachPathClone, {
insert: false,
}) as paper.Path | paper.CompoundPath)
: ((workingShape as any).unite(eachPathClone, {
insert: false,
}) as paper.Path | paper.CompoundPath)
eachPathClone.remove()
workingShape?.remove()
workingShape = nextShape
changed = true
}
if (!changed) {
workingShape?.remove()
return
}
if (!workingShape) return
const raster = usePaperStore.getState().rasterPath
if (raster && hasShapeSegments(workingShape)) {
const clippedShape = (workingShape as any).intersect(raster, {
insert: false,
trace: false,
}) as paper.Path | paper.CompoundPath
workingShape?.remove()
workingShape = clippedShape
}
if (!workingShape) return
const { polygonPoints, polygonHollowPoints } =
collectPolygonPoints(workingShape)
workingShape?.remove()
const nextLabel = safeClone(useLabelStore.getState().label)
const imageLabel = nextLabel.get(selectedContext.imageId)
if (!imageLabel) return
const operationPaths = safeClone(
imageLabel.get(selectedContext.operationId) || []
)
const selectedIndex = operationPaths.findIndex(
(item) => item[0] === selectedContext.objectId
)
if (selectedIndex === -1) return
const currentTuple = operationPaths[selectedIndex]
if (polygonPoints.length) {
operationPaths[selectedIndex] = [
selectedContext.objectId,
polygonPoints,
safeClone(currentTuple?.[2] || {}),
polygonHollowPoints,
]
imageLabel.set(selectedContext.operationId, operationPaths)
} else {
imageLabel.set(
selectedContext.operationId,
operationPaths.filter((item) => item[0] !== selectedContext.objectId)
)
removeObjectFromGroupMap(
selectedContext.imageId,
selectedContext.objectId
)
}
useLabelStore.getState().setLabel(nextLabel)
useLabelStore.getState().pushStateStack(nextLabel)
rerenderActiveImageByLabel(
selectedContext.imageId,
imageLabel,
polygonPoints.length ? [selectedContext.objectId] : []
)
usePaperStore.getState().applySelectedPolygonBooleanOperation(mode)
},
[
collectPolygonPoints,
createWorkingPolygonShape,
hasShapeSegments,
removeObjectFromGroupMap,
rerenderActiveImageByLabel,
resolveSelectedObjectContext,
]
[resolveSelectedObjectContext]
)
const applySelectedBrushIntersectUnite = useCallback(() => {
@@ -2638,7 +2422,7 @@ const LabelPage = ({
useEffect(() => {
if (!isView) {
const delay = 10 * 60000
const delay = 5 * 60000
// 编辑模式下修改labelData时启动或更新定时器
useTimerStore.getState().startTimer(() => {
useTopToolsStore.getState().setIsView(true)

File diff suppressed because it is too large Load Diff