123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- import { lineVector, Pos, vectorAngle, verticalVector } from "@/utils/math.ts";
- import { BaseItem, generateSnapInfos, getBaseItem } from "../util.ts";
- import { getMouseColors } from "@/utils/colors.ts";
- import { InteractiveFix, InteractiveTo, MatResponseProps } from "../index.ts";
- import { inRevise, onlyId, rangMod } from "@/utils/shared.ts";
- import { MathUtils } from "three";
- import { DrawStore, useStore } from "@/core/store/index.ts";
- import {
- SelectionManageBus,
- UseGetSelectionManage,
- } from "@/core/hook/use-selection.ts";
- import { EntityShape } from "@/deconstruction.js";
- import mitt from "mitt";
- import { watch } from "vue";
- import { getInitCtx, NLineDataCtx, normalLineData } from "./attach-server.ts";
- export { default as Component } from "./line.vue";
- export { default as TempComponent } from "./temp-line.vue";
- export { useDraw } from "./use-draw.ts";
- export const shapeName = "线段";
- export const defaultStyle = {
- stroke: "#000000",
- strokeWidth: 20,
- dash: [30, 0],
- };
- export const addMode = "single-dots";
- export const getMouseStyle = (data: LineData) => {
- const strokeStatus = getMouseColors(data.stroke || defaultStyle.stroke);
- const strokeWidth = data.strokeWidth || defaultStyle.strokeWidth;
- return {
- default: { stroke: data.stroke || defaultStyle.stroke, strokeWidth },
- hover: { stroke: strokeStatus.hover },
- select: { stroke: strokeStatus.select },
- focus: { stroke: strokeStatus.hover },
- press: { stroke: strokeStatus.press },
- };
- };
- export const getSnapInfos = (data: LineData) => {
- const vh = generateSnapInfos(getSnapPoints(data), true, false, true);
- data.lines.forEach((item) => {
- const a = data.points.find((p) => p.id === item.a)!;
- const b = data.points.find((p) => p.id === item.b)!;
- const prevVector = lineVector([a, b]);
- const vLine = verticalVector(prevVector);
- vh.push({
- point: a,
- links: [b],
- linkDirections: [prevVector],
- linkAngle: [rangMod(MathUtils.radToDeg(vectorAngle(vLine)), 180)],
- });
- });
- return vh;
- };
- export const getSnapPoints = (data: LineData) => {
- return data.points;
- };
- export type LineDataLine = {
- id: string;
- a: string;
- b: string;
- strokeWidth: number;
- stroke: string;
- dash: number[];
- };
- export type LineDataPoint = Pos & { id: string }
- export type LineData = Partial<typeof defaultStyle> &
- BaseItem & {
- points: LineDataPoint[];
- lines: LineDataLine[];
- polygon: { points: string[]; id: string }[];
- updateTime?: number;
- calcTime?: number;
- };
- export const interactiveToData: InteractiveTo<"line"> = ({
- info,
- preset = {},
- ...args
- }) => {
- if (info.cur) {
- const baseItem = getBaseItem();
- return interactiveFixData({
- ...args,
- info,
- data: {
- ...defaultStyle,
- ...baseItem,
- ...preset,
- lines: [],
- points: [],
- polygon: [],
- },
- });
- }
- };
- export const interactiveFixData: InteractiveFix<"line"> = ({ data, info }) => {
- const nv = [...info.consumed, info.cur!];
- data.points.length = nv.length;
- for (let i = 0; i < nv.length; i++) {
- if (inRevise(data.points[i], nv[i])) {
- if (!data.points[i]) {
- data.points[i] = {
- id: onlyId(),
- ...nv[i],
- };
- } else {
- data.points[i] = {
- ...data.points[i],
- ...nv[i],
- };
- }
- }
- }
- data.lines.length = nv.length - 1;
- for (let i = 0; i < nv.length - 1; i++) {
- if (!data.lines[i]) {
- data.lines[i] = {
- id: onlyId(),
- ...defaultStyle,
- a: data.points[i].id,
- b: data.points[i + 1].id,
- };
- }
- }
- // data.polygon = [{points: [data.lines.map((item) => item.id)], id: onlyId()}];
- return data;
- };
- const matResPoints = new Set<string>();
- let matCtx: NLineDataCtx | null;
- export const startMatResponse = () => {
- matCtx = getInitCtx();
- };
- export const matResponse = ({
- data,
- mat,
- operId,
- }: MatResponseProps<"line">) => {
- const line = data.lines.find((item) => item.id === operId);
- if (!line) return;
- const ids = [line.a, line.b];
- for (const id of ids) {
- if (matResPoints.has(id)) {
- continue;
- }
- const ndx = data.points.findIndex((item) => item.id === id);
- if (~ndx) {
- const point = data.points[ndx];
- data.points[ndx] = {
- ...point,
- ...mat.point(point),
- };
- matCtx!.update.points[point.id] = data.points[ndx];
- matResPoints.add(id);
- }
- }
- return data;
- };
- export const endMatResponse = () => {
- matResPoints.clear();
- // matCtx && normalLineData(matData, matCtx)
- // console.log(matData, matCtx)
- matCtx = null;
- };
- export const getPredefine = (key: keyof LineData) => {
- if (key === "strokeWidth") {
- return { proportion: true };
- }
- };
- export const childrenDataGetter = (data: LineData, id: string) => {
- const line = data.lines.find((item) => item.id === id);
- if (!line) return;
- const ids = [line.a, line.b];
- return data.points.filter((p) => ids.includes(p.id));
- };
- export const delItem = (store: DrawStore, data: LineData, childId: string) => {
- if (!childId) {
- store.delItem("line", data.id);
- return;
- }
- let ndx;
- if (~(ndx = data.lines.findIndex((item) => item.id === childId))) {
- const delLine = data.lines[ndx];
- const ctx = getInitCtx();
- ctx.del.lines[delLine.id] = delLine;
- data.lines.splice(ndx, 1);
- normalLineData(data, ctx);
- store.setItem("line", { value: data, id: data.id });
- } else if (~(ndx = data.points.findIndex((item) => item.id === childId))) {
- const { ctx } = delPoint(data, childId);
- normalLineData(data, ctx);
- store.setItem("line", { value: data, id: data.id });
- }
- };
- export const delPoint = (data: LineData, id: string, ctx = getInitCtx()) => {
- const p = data.points.find((item) => item.id === id);
- if (!p) return { data, ctx };
- const checkLines = data.lines.filter(
- (item) => item.a === p.id || item.b === p.id
- );
- if (checkLines.length > 1) {
- const joinPoints = new Set<string>();
- checkLines.forEach((item) => {
- joinPoints.add(item.a);
- joinPoints.add(item.b);
- });
- if (joinPoints.size === 3) {
- const prev = checkLines.find((item) => item.b === p.id);
- const next = checkLines.find((item) => item.a === p.id);
- if (prev && next) {
- const l = { ...prev, id: onlyId(), b: next.b };
- ctx.add.lines[l.id] = l;
- data.lines.push(l);
- } else {
- const l = prev || next || checkLines[0];
- const ps = [...joinPoints].filter((item) => item !== p.id);
- const nl = { ...l, id: onlyId(), a: ps[0], b: ps[1] };
- ctx.add.lines[l.id] = nl;
- data.lines.push(nl);
- }
- }
- }
- checkLines.forEach((l) => {
- ctx.del.lines[l.id] = l;
- const ndx = data.lines.findIndex((ln) => ln.id === l.id);
- ~ndx && data.lines.splice(ndx, 1);
- });
- ctx.del.points[p.id] = p;
- const ndx = data.points.findIndex((pn) => pn.id === p.id);
- ~ndx && data.points.splice(ndx, 1);
- return { data, ctx };
- };
- export const useGetSelectionManage: UseGetSelectionManage = () => {
- const store = useStore();
- const canSelect = (shape: EntityShape) => {
- const id = shape.id();
- const line = store.getTypeItems("line")[0];
- return !!(id && line.lines.some((item) => item.id === id));
- };
- const listener = (shape: EntityShape) => {
- const bus: SelectionManageBus = mitt();
- const stop = watch(
- () => canSelect(shape),
- (exixts, _) => {
- if (!exixts) {
- bus.emit("del", shape);
- }
- },
- { immediate: true }
- );
- return { stop, bus };
- };
- return { canSelect, listener };
- };
|