当前位置: 首页 > news >正文

cili3d笔记20 正交投影3d重建笔记1

正交视图转3d

       mostFrequentCluster.lines.forEach(line => {const [x1, y1, x2, y2] = line;let xhat={x1,x2};let yhat={y1,y2};});

 没考虑到侧视图

   const clusters = clusterLines(inputlines, 5);const lines3d:[number,number,number,number,number,number][]=[]const { mostMinX, mostMinY } = getMostFrequentMinXY(clusters);const mostFrequentClusters = clusters.filter(cluster => {return cluster.min_x === mostMinX.value && cluster.min_y === mostMinY.value;
});
const topclusters = clusters.filter(cluster => {return cluster.min_x === mostMinX.value && cluster.min_y > mostMinY.value;
});
;
const rightclusters = clusters.filter(cluster => {return cluster.min_x > mostMinX.value && cluster.min_y === mostMinY.value;
});
const bottomclusters = clusters.filter(cluster => {return cluster.min_x === mostMinX.value && cluster.min_y < mostMinY.value;
});
const leftclusters = clusters.filter(cluster => {return cluster.min_x < mostMinX.value && cluster.min_y === mostMinY.value;
});const mostFrequentCluster= mostFrequentClusters[0];const topcluauster= topclusters[0];const rightcluster= rightclusters[0];const bottomcluster= bottomclusters[0];const leftcluster= leftclusters[0];mostFrequentCluster.lines.forEach(line => {const [x1, y1, x2, y2] = line;const seen = new Set<string>(); // 用于记录已经添加过的线段function addUniqueLine(x1: number, y1: number, z1: number, x2: number, y2: number, z2: number) {const key = `${x1},${y1},${z1},${x2},${y2},${z2}`;if (!seen.has(key)) {seen.add(key);lines3d.push([x1, y1, z1, x2, y2, z2]);}
}topcluauster.lines.forEach(line => {const [tx1, ty1, tx2, ty2] = line;const clusterminy=topcluauster.min_y;if (tx1 <x1 && tx2 > x2) {addUniqueLine(x1, y1, ty1-clusterminy, x2, y2, ty1-clusterminy);
addUniqueLine(x1, y1, ty2-clusterminy, x2, y2, ty2-clusterminy);}rightcluster.lines.forEach(line => {const [rx1, ry1, rx2, ry2] = line;const clusterminx=rightcluster.min_x;if (ry1 <y1 && ry2 > y2) {addUniqueLine(x1, y1, rx1-clusterminx, x2, y2, rx1-clusterminx);
addUniqueLine(x1, y1, rx2-clusterminx, x2, y2, rx2-clusterminx);}});});});
Logger.info(`lines3d completed with ${lines3d.length} lines3d`);lines3d.forEach(line => {PubSub.default.pub("njsgcs_makeline", line[0], line[1],  line[2], line[3], line[4], line[5],1); })

第3 视角0是在外侧

材质全是红色说明侧视图读取可有可无

           topcluauster.lines.forEach(line => {const [tx1, ty1, tx2, ty2] = line;const clusterminy=topcluauster.min_y;if (tx1 <=x1 && tx2 >= x2) {addUniqueLine(x1, y1, ty1-clusterminy, x2, y2, ty1-clusterminy,1);
addUniqueLine(x1, y1, ty2-clusterminy, x2, y2, ty2-clusterminy,1);
addUniqueLine(x1, y1, ty1-clusterminy, x2, y2, ty2-clusterminy,1);}

.............

        topcluauster.lines.forEach(line => {const [tx1, ty1, tx2, ty2] = line;const clusterminy=topcluauster.min_y;if (tx1 <=x1 && tx2 >= x2) {addUniqueLine(x1, y1, ty1-clusterminy, x2, y2, ty1-clusterminy,1);
addUniqueLine(x1, y1, ty2-clusterminy, x2, y2, ty2-clusterminy,1);
addUniqueLine(x1, y1, ty1-clusterminy, x2, y2, ty2-clusterminy,1);
addUniqueLine(x1, y1, ty2-clusterminy, x2, y2, ty1-clusterminy,1);}

               topcluauster.lines.forEach(line => {const [tx1, ty1, tx2, ty2] = line;const clusterminy=topcluauster.min_y;if (tx1 <=x1 && tx2 >= x2) {addUniqueLine(x1, y1, ty1-clusterminy, x2, y2, ty1-clusterminy,1);
addUniqueLine(x1, y1, ty2-clusterminy, x2, y2, ty2-clusterminy,1);if(ty1!=ty2){
addUniqueLine(x1, y1, ty1-clusterminy, x1, y1, ty2-clusterminy,1);
addUniqueLine(x2, y2, ty1-clusterminy, x2, y2, ty2-clusterminy,1);}

旧版本合并会吃线条,不然是可以手动转为实体的

import { Logger, PubSub } from "chili-core";
import DxfParser, { ILineEntity } from 'dxf-parser';
class Cluster {lines: [number, number, number, number][];min_x: number;max_x: number;min_y: number;max_y: number;constructor(lines: [number, number, number, number][] = []) {this.lines = [...lines];this.min_x = Infinity;this.max_x = -Infinity;this.min_y = Infinity;this.max_y = -Infinity;if (lines.length > 0) {this.updateBounds();}}updateBounds(): void {this.min_x = Math.min(...this.lines.flatMap(line => [line[0], line[2]]));this.max_x = Math.max(...this.lines.flatMap(line => [line[0], line[2]]));this.min_y = Math.min(...this.lines.flatMap(line => [line[1], line[3]]));this.max_y = Math.max(...this.lines.flatMap(line => [line[1], line[3]]));}get lengthX(): number {return parseFloat((this.max_x - this.min_x).toFixed(1));}get lengthY(): number {return parseFloat((this.max_y - this.min_y).toFixed(1));}
}
function clusterLines(lines: [number, number, number, number][], expandDistance: number = 5): Cluster[] {const clusters: Cluster[] = [];const remainingLines = [...lines];while (remainingLines.length > 0) {const seed = remainingLines.shift()!;const currentCluster = new Cluster([seed]);currentCluster.updateBounds();let changed = true;while (changed) {changed = false;const expandedMinX = currentCluster.min_x - expandDistance;const expandedMaxX = currentCluster.max_x + expandDistance;const expandedMinY = currentCluster.min_y - expandDistance;const expandedMaxY = currentCluster.max_y + expandDistance;const toAdd: [number, number, number, number][] = [];for (const line of [...remainingLines]) {const [x1, y1, x2, y2] = line;const inBound =(x1 >= expandedMinX && x1 <= expandedMaxX && y1 >= expandedMinY && y1 <= expandedMaxY) ||(x2 >= expandedMinX && x2 <= expandedMaxX && y2 >= expandedMinY && y2 <= expandedMaxY);if (inBound) {toAdd.push(line);changed = true;}}for (const line of toAdd) {currentCluster.lines.push(line);remainingLines.splice(remainingLines.indexOf(line), 1);}currentCluster.updateBounds();}// 合并完全覆盖的聚类for (let i = 0; i < clusters.length; i++) {const cluster = clusters[i];if (currentCluster.min_x <= cluster.min_x &&currentCluster.min_y <= cluster.min_y &&currentCluster.max_x >= cluster.max_x &&currentCluster.max_y >= cluster.max_y) {currentCluster.lines.push(...cluster.lines);clusters.splice(i, 1);break;}}clusters.push(currentCluster);}return clusters;
}
export function rebuild3D(document: Document) {const fileInput = document.createElement("input");fileInput.type = "file";fileInput.accept = ".dxf";fileInput.style.display = "none";fileInput.addEventListener("change", async (event) => {const target = event.target as HTMLInputElement;if (!target.files || target.files.length === 0) return;const file = target.files[0];Logger.info(`Selected file: ${file.name}`);try {const reader = new FileReader();reader.onload = () => {const dxfText = reader.result as string;const parser = new DxfParser();const dxf = parser.parseSync(dxfText);const inputlines: [number, number, number, number][] = [];if (dxf && dxf.entities) {dxf.entities.forEach(entity => {if (entity.type === 'LINE') {const lineEntity = entity as ILineEntity;const start = lineEntity.vertices[0];const end = lineEntity.vertices[1];if (start && end) {inputlines.push([start.x, start.y, end.x, end.y]);}}});}// 执行聚类const clusters = clusterLines(inputlines, 5);const lines3d:[number,number,number,number,number,number,number][]=[]const { mostMinX, mostMinY } = getMostFrequentMinXY(clusters);const mostFrequentClusters = clusters.filter(cluster => {return cluster.min_x === mostMinX.value && cluster.min_y === mostMinY.value;
});
const topclusters = clusters.filter(cluster => {return cluster.min_x === mostMinX.value && cluster.min_y > mostMinY.value;
});
;
const rightclusters = clusters.filter(cluster => {return cluster.min_x > mostMinX.value && cluster.min_y === mostMinY.value;
});
const bottomclusters = clusters.filter(cluster => {return cluster.min_x === mostMinX.value && cluster.min_y < mostMinY.value;
});
const leftclusters = clusters.filter(cluster => {return cluster.min_x < mostMinX.value && cluster.min_y === mostMinY.value;
});const mostFrequentCluster= mostFrequentClusters[0];const topcluauster= topclusters[0];const rightcluster= rightclusters[0];const bottomcluster= bottomclusters[0];const leftcluster= leftclusters[0];const seen = new Set<string>(); // 用于记录已经添加过的线段function addUniqueLine(x1: number, y1: number, z1: number, x2: number, y2: number, z2: number,color:number) {const key = `${x1},${y1},${z1},${x2},${y2},${z2}`;if (!seen.has(key)) {seen.add(key);lines3d.push([x1, y1, z1, x2, y2, z2,color]);}
} const topview3dpoints = [];mostFrequentCluster.lines.forEach(line => {const [x1, y1, x2, y2] = line;topcluauster.lines.forEach(line => {const [tx1, ty1, tx2, ty2] = line;const clusterminy=topcluauster.min_y;if (tx1 <=x1 || tx2 >= x2) {addUniqueLine(x1, y1, ty1-clusterminy, x2, y2, ty1-clusterminy,1);
addUniqueLine(x1, y1, ty2-clusterminy, x2, y2, ty2-clusterminy,1);if(ty1!=ty2){
addUniqueLine(x1, y1, ty1-clusterminy, x1, y1, ty2-clusterminy,1);
addUniqueLine(x2, y2, ty1-clusterminy, x2, y2, ty2-clusterminy,1);}}});});
Logger.info(`lines3d completed with ${lines3d.length} lines3d`);lines3d.forEach(line => {PubSub.default.pub("njsgcs_makeline", line[0], line[1],  line[2], line[3], line[4], line[5],1); })///// let i =0;// // 发送每个线段给 njsgcs_makeline// clusters.forEach(cluster => {//     i++;//     cluster.lines.forEach(line => {//         const [x1, y1, x2, y2] = line;//         PubSub.default.pub("njsgcs_makeline", x1, y1, 0, x2, y2, 0,i); // z=0 假设为俯视图//     });// });///Logger.info(`Clustering completed with ${clusters.length} clusters`);};reader.readAsText(file);} catch (error) {Logger.error("Error reading file:", error);}});fileInput.click();
}
function getMostFrequentMinXY(clusters: Cluster[]) {const minXCounts: Record<number, number> = {};const minYCounts: Record<number, number> = {};let maxXCount = 0, mostX = clusters[0]?.min_x;let maxYCount = 0, mostY = clusters[0]?.min_y;for (const cluster of clusters) {const x = cluster.min_x;const y = cluster.min_y;minXCounts[x] = (minXCounts[x] || 0) + 1;if (minXCounts[x] > maxXCount) {maxXCount = minXCounts[x];mostX = x;}minYCounts[y] = (minYCounts[y] || 0) + 1;if (minYCounts[y] > maxYCount) {maxYCount = minYCounts[y];mostY = y;}}return {mostMinX: { value: mostX, count: maxXCount },mostMinY: { value: mostY, count: maxYCount }};
}

 

 里面开槽会多线

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.dtcms.com/a/255475.html

相关文章:

  • GoFrame的Gtoken--基于电商项目以及GPT-o3的辅助解惑
  • 如何轻松地将联系人从 iPhone 转移到 iPhone?
  • window显示驱动开发—输出合并器阶段
  • django FileSystemStorage is located outside of the base path component
  • 【前端隐蔽 Bug 深度剖析:SVG 组件复用中的 ID 冲突陷阱】
  • QT的一些介绍
  • Pinia在多步骤表单中的实践应用
  • DDoS防护体系构建——从基础限速到智能调度
  • C++容器之 forward_list (单向链表)使用说明
  • 层级冲突的处理,弹窗生成遮罩问题
  • http通信测试,模拟客户端
  • 力扣-169.多数元素
  • 三种经典算法无人机三维路径规划对比(SMA、HHO、GWO三种算法),Matlab代码实现
  • 医学图像处理期末复习
  • Ruoyi(若依)整合websocket实现信息推送功能(消息铃铛)
  • Logback示例解析
  • 云徙科技 OMS:让订单管理变得轻松又高效
  • python高校工作室管理系统
  • 【服务器R环境架构】基于 micromamba下载 R 库包
  • linux的基本运维
  • 【网络安全】文件上传型XSS攻击解析
  • 音视频合并避坑指南,封装过程中的解决办法
  • 云主机远程连接与防火墙安全配置指南:协同防护是关键
  • Web Splats
  • LeetCode 2942.查找包含给定字符的单词
  • 短剧CPS分销系统开发 - 专业内容变现与渠道拓展解决方案
  • Java 集合框架底层数据结构实现深度解析
  • OSI网络通信模型详解
  • 开疆智能ModbusTCP转EtherCAT网关连接穆格伺服阀配置案例
  • Vue2 ElementUI Tree 拖动目标节点能否被放置及获取放置位置