这个要注册不然emscripten编译不起来
---------------
行不通
----------------
结构体
using LineSegment = std::pair<gp_Pnt, gp_Pnt>;
using LineSegmentList = std::vector<LineSegment>;
EMSCRIPTEN_BINDINGS(Shape_Projection) {
value_object<LineSegment>("LineSegment")
.field("first", &LineSegment::first)
.field("second", &LineSegment::second);
// 绑定 LineSegmentList (std::vector<LineSegment>)
register_vector<LineSegment>("LineSegmentList");
class_<ProjectionResult>("ProjectionResult")
.property("visible", &ProjectionResult::visible)
.property("hidden", &ProjectionResult::hidden);
class_<ShapeProjection>("ShapeProjection")
.class_function("projection", &ShapeProjection::GetProjectionEdges);
}
printf无效,要用cout
deepwiki写occ代码真的强
视图偏移还有点问题
import { IApplication, Logger, PubSub, ShapeNode } from "chili-core";
import { getProjectionEdges, gp_Pnt, LineSegmentList, OccShape, ProjectionResult2 } from "chili-wasm";
interface Segment {
first: gp_Pnt;
second: gp_Pnt;
}
export class njsgcs_drawingView extends HTMLElement {
private viewportCanvas2d: HTMLCanvasElement | null = null;
private app: IApplication | null = null;
constructor() {
super();
PubSub.default.sub("njsgcs_drawview", async (app: IApplication) => {
Logger.info("njsgcs_drawview event triggered");
if (this.viewportCanvas2d) {
this.removeChild(this.viewportCanvas2d);
this.viewportCanvas2d = null;
}
this.app = app;
const canvas = this.createCanvas();
this.appendChild(canvas);
});
}
private drawProjectionEdges(ctx: CanvasRenderingContext2D, projection: ProjectionResult2) {
// 清除画布
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
// 获取所有线段并合并用于自动缩放计算
const allSegments = [
...this.toArray(projection.f_visible),
...this.toArray(projection.f_hidden),
...this.toArray(projection.s_visible),
...this.toArray(projection.s_hidden),
...this.toArray(projection.t_visible),
...this.toArray(projection.t_hidden),
];
// 自动计算缩放和偏移
const { minX, maxX, minY, maxY } = this.calculateBounds(allSegments);
const margin = 50;
const availableWidth = ctx.canvas.width - 2 * margin;
const availableHeight = ctx.canvas.height - 2 * margin;
const scaleX = availableWidth / (maxX - minX || 1);
const scaleY = availableHeight / (maxY - minY || 1);
const scale = Math.min(scaleX, scaleY) * 0.9; // 留点边距
const offsetX = ctx.canvas.width / 2;
const offsetY = ctx.canvas.height / 2;
// 定义各视图偏移
const views = [
{
name: 'front',
segmentsVisible: this.toArray(projection.f_visible),
segmentsHidden: this.toArray(projection.f_hidden),
offset: { x: -availableWidth / 3, y: 0 },
},
{
name: 'side',
segmentsVisible: this.toArray(projection.s_visible),
segmentsHidden: this.toArray(projection.s_hidden),
offset: { x: 0, y: 0 },
},
{
name: 'top',
segmentsVisible: this.toArray(projection.t_visible),
segmentsHidden: this.toArray(projection.t_hidden),
offset: { x: availableWidth / 3, y: 0 },
},
];
// 绘制每个视图
for (const view of views) {
// 实线:可见线
this.drawSegments(
ctx,
view.segmentsVisible,
false,
scale,
offsetX + view.offset.x,
offsetY + view.offset.y
);
// 虚线:隐藏线
this.drawSegments(
ctx,
view.segmentsHidden,
true,
scale,
offsetX + view.offset.x,
offsetY + view.offset.y
);
}
}
private calculateBounds(segments: Segment[]) {
let minX = Infinity;
let maxX = -Infinity;
let minY = Infinity;
let maxY = -Infinity;
for (const segment of segments) {
if (segment && segment.first && segment.second) {
const points = [segment.first, segment.second];
for (const p of points) {
minX = Math.min(minX, p.x);
maxX = Math.max(maxX, p.x);
minY = Math.min(minY, p.y);
maxY = Math.max(maxY, p.y);
}
}
}
return {
minX: minX === Infinity ? 0 : minX,
maxX: maxX === -Infinity ? 0 : maxX,
minY: minY === Infinity ? 0 : minY,
maxY: maxY === -Infinity ? 0 : maxY,
};
}
private drawSegments(
ctx: CanvasRenderingContext2D,
segments: Segment[],
isHidden: boolean,
scale: number,
offsetX: number,
offsetY: number
) {
ctx.strokeStyle = isHidden ? "gray" : "black";
ctx.lineWidth = isHidden ? 1 : 2;
ctx.setLineDash(isHidden ? [5, 5] : []);
for (const segment of segments) {
if (segment && segment.first && segment.second) {
ctx.beginPath();
ctx.moveTo(
segment.first.x * scale + offsetX,
-segment.first.y * scale + offsetY
);
ctx.lineTo(
segment.second.x * scale + offsetX,
-segment.second.y * scale + offsetY
);
ctx.stroke();
}
}
}
private toArray(segmentList: LineSegmentList): Segment[] {
const result = [];
for (let i = 0; i < segmentList.size(); i++) {
const segment = segmentList.get(i);
if (segment) {
result.push(segment);
}
}
return result;
}
private createCanvas(): HTMLCanvasElement {
if (!this.viewportCanvas2d) {
this.viewportCanvas2d = document.createElement("canvas");
this.viewportCanvas2d.width = 900;
this.viewportCanvas2d.height = 600;
this.viewportCanvas2d.style.border = "1px solid #000";
const ctx = this.viewportCanvas2d.getContext("2d");
if (ctx) {
const document = this.app!.activeView?.document;
if (!document) return this.viewportCanvas2d;
const geometries = document.selection.getSelectedNodes();
const entities = geometries.filter((x) => x instanceof ShapeNode);
for (const entity of entities) {
const shapeResult = entity.shape;
if (shapeResult.isOk) {
const shape = shapeResult.value; // 获取IShape
// 检查是否为OccShape实例
if (shape instanceof OccShape) {
const topoShape = shape.shape; // 访问TopoDS_Shape
const ProjectionEdges=getProjectionEdges(topoShape);
this.drawProjectionEdges(ctx,ProjectionEdges)
}
}
}
}
}
return this.viewportCanvas2d!;
}
}
customElements.define("njsgcs-drawing-view", njsgcs_drawingView);
import { LineSegmentList, TopoDS_Shape } from "../lib/chili-wasm";
export { LineSegmentList, ProjectionResult2 };
interface ProjectionResult2 {
f_visible:LineSegmentList ,
f_hidden: LineSegmentList ,
s_visible: LineSegmentList ,
s_hidden: LineSegmentList ,
t_visible: LineSegmentList ,
t_hidden:LineSegmentList ,
}
export function getProjectionEdges(
shape: TopoDS_Shape,
): { f_visible: LineSegmentList; f_hidden: LineSegmentList,s_visible: LineSegmentList; s_hidden: LineSegmentList,t_visible: LineSegmentList; t_hidden: LineSegmentList} {
console.info("test1");
const f_result = wasm.ShapeProjection.projection(shape, new wasm.gp_Dir(0, 1, 0));
console.info("first:"+f_result.visible.get(0)?.first);
const s_result = wasm.ShapeProjection.projection(shape, new wasm.gp_Dir( 1,0, 0));
const t_result = wasm.ShapeProjection.projection(shape, new wasm.gp_Dir( 0, 0,1));
return {
f_visible: f_result.visible,
f_hidden: f_result.hidden,
s_visible: s_result.visible,
s_hidden: s_result.hidden,
t_visible: t_result.visible,
t_hidden: t_result.hidden,
};
}
#include <BRepPrimAPI_MakeBox.hxx>
#include <BRepPrimAPI_MakeCylinder.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <gp_Pnt.hxx>
#include <gp_Dir.hxx>
#include <gp_Ax2.hxx>
#include <HLRBRep_Algo.hxx>
#include <HLRBRep_HLRToShape.hxx>
#include <HLRAlgo_Projector.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <GCPnts_UniformDeflection.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <vector>
#include <emscripten/bind.h>
#include <tuple>
#include <BRep_Tool.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS_Edge.hxx>
#include <Geom_Line.hxx>
using namespace emscripten;
std::vector<std::pair<gp_Pnt, gp_Pnt>> ExtractLineSegments(const TopoDS_Shape& shape) {
std::vector<std::pair<gp_Pnt, gp_Pnt>> lineSegments;
for (TopExp_Explorer edgeExplorer(shape, TopAbs_EDGE); edgeExplorer.More(); edgeExplorer.Next()) {
TopoDS_Edge edge = TopoDS::Edge(edgeExplorer.Current());
// 优先使用顶点方法
TopoDS_Vertex aFirst, aLast;
TopExp::Vertices(edge, aFirst, aLast, Standard_True);
if (!aFirst.IsNull() && !aLast.IsNull()) {
gp_Pnt startPnt = BRep_Tool::Pnt(aFirst);
gp_Pnt endPnt = BRep_Tool::Pnt(aLast);
lineSegments.emplace_back(startPnt, endPnt);
//std::cout << "startPnt: X=" << startPnt.X() << " Y=" << startPnt.Y() << " Z=" << startPnt.Z() << std::endl;
}
}
return lineSegments;
}
// Convert 3D edge to 2D points
struct ProjectionResult {
std::vector<std::pair<gp_Pnt, gp_Pnt>> visible;
std::vector<std::pair<gp_Pnt, gp_Pnt>> hidden;
ProjectionResult(
const std::vector<std::pair<gp_Pnt, gp_Pnt>>& vis,
const std::vector<std::pair<gp_Pnt, gp_Pnt>>& hid
) : visible(vis), hidden(hid) {}
};
class ShapeProjection {
public:
static ProjectionResult GetProjectionEdges(const TopoDS_Shape& shape, const gp_Dir& direction) {
// Create projector
gp_Ax3 viewAxis(gp_Pnt(0, 0, 0), direction);
gp_Trsf transformation;
transformation.SetTransformation(viewAxis);
HLRAlgo_Projector projector(transformation, Standard_False, 0.0);
// Create HLR algorithm
Handle(HLRBRep_Algo) hlr_algo = new HLRBRep_Algo();
hlr_algo->Add(shape);
hlr_algo->Projector(projector);
hlr_algo->Update();
hlr_algo->Hide();
// Extract visible and hidden edges
HLRBRep_HLRToShape hlr_to_shape(hlr_algo);
TopoDS_Shape visible_edges = hlr_to_shape.VCompound();
TopoDS_Shape hidden_edges = hlr_to_shape.HCompound();
auto visible_line_segments = ExtractLineSegments(visible_edges);
auto hidden_line_segments = ExtractLineSegments(hidden_edges);
return ProjectionResult(visible_line_segments, hidden_line_segments);
}
};
using LineSegment = std::pair<gp_Pnt, gp_Pnt>;
using LineSegmentList = std::vector<LineSegment>;
EMSCRIPTEN_BINDINGS(Shape_Projection) {
value_object<LineSegment>("LineSegment")
.field("first", &LineSegment::first)
.field("second", &LineSegment::second);
register_vector<LineSegment>("LineSegmentList");
class_<ProjectionResult>("ProjectionResult")
.property("visible", &ProjectionResult::visible)
.property("hidden", &ProjectionResult::hidden);
class_<ShapeProjection>("ShapeProjection")
.class_function("projection", &ShapeProjection::GetProjectionEdges);
}