123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- import * as d3 from "d3-scale";
- import { formatDefaultLocale } from "d3-format";
- import "@kitware/vtk.js/Rendering/Profiles/Geometry";
- import vtkFullScreenRenderWindow from "@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow";
- import vtkActor from "@kitware/vtk.js/Rendering/Core/Actor";
- import vtkMapper from "@kitware/vtk.js/Rendering/Core/Mapper";
- import vtkScalarBarActor from "@kitware/vtk.js/Rendering/Core/ScalarBarActor";
- import vtkColorTransferFunction from "@kitware/vtk.js/Rendering/Core/ColorTransferFunction";
- import { Representation } from "@kitware/vtk.js/Rendering/Core/Property/Constants";
- import vtkPolyData from "@kitware/vtk.js/Common/DataModel/PolyData";
- import { throttle } from '@kitware/vtk.js/macros';
- import {
- FieldDataTypes,
- FieldAssociations,
- } from '@kitware/vtk.js/Common/DataModel/DataSet/Constants';
- import vtkSphereSource from '@kitware/vtk.js/Filters/Sources/SphereSource';
- import vtkLineSource from '@kitware/vtk.js/Filters/Sources/LineSource';
- import vtkSphereMapper from '@kitware/vtk.js/Rendering/Core/SphereMapper';
- export class VtkModel {
- constructor() {
- //当前显示 模版 还是结果
- this.isJg = false;
- /**
- * 选择点线
- */
- this.isSelectNode = false;
- /**
- * 选择管道
- */
- this.isSelectPipe = false;
- //管道节点选择对象
- this.selectObj = null;
- //结果选择的点数据
- this.selectJgPointId=0;
- this.validNodes = [];//节点数据
- this.pipes = [];//管道数据
- this.renderWindowWith = vtkFullScreenRenderWindow.newInstance();
- this.renderer = this.renderWindowWith.getRenderer();
- this.renderWindow = this.renderWindowWith.getRenderWindow();
- //模板数据
- this.polyData = vtkPolyData.newInstance();
- this.mapper = vtkMapper.newInstance();
- this.actor = vtkActor.newInstance();
- this.actor.getProperty().setRepresentation(Representation.SURFACE); //线
- this.actor.getProperty().setColor(WHITE);
- this.mapper.setInputData(this.polyData);
- this.actor.setMapper(this.mapper);
- //点数据
- this.actor2 = vtkActor.newInstance();
- this.actor2.getProperty().setRepresentation(Representation.POINTS); //点
- this.actor2.getProperty().setColor(WHITE);
- this.actor2.getProperty().setPointSize(2);
- this.actor2.setMapper(this.mapper);
- //选取
- this.lastActor = null;
- this.nodeActors = []; //节点actor 数据
- this.pipeActors = []; //管道actor 数据
- this.interactor = this.renderer.getRenderWindow().getInteractor();
- this.apiSpecificRenderWindow = this.interactor.getView();
- this.hardwareSelector = this.apiSpecificRenderWindow.getSelector();
- this.hardwareSelector.setCaptureZValues(true);
- this.hardwareSelector.setFieldAssociation(FieldAssociations.FIELD_ASSOCIATION_POINTS);
- document.addEventListener("mousemove", throttleMouseHandler);
- //结果数据
- this.jgActor = vtkActor.newInstance();
- this.jgMapper = vtkMapper.newInstance();
- this.jgActor.getProperty().setRepresentation(Representation.SURFACE); //面
- this.scalarBarActor = vtkScalarBarActor.newInstance();
- this.scalarBarActor.setGenerateTicks(this.generateTicks(5));
- this.scalarBarActor.setDrawAboveRangeSwatch(true);
- this.scalarBarActor.setDrawNanAnnotation(false);
- this.scalarBarActor.setBoxPosition([1, 0]);
- // 修改设条颜色
- const ctf = vtkColorTransferFunction.newInstance();
- ctf.addRGBPoint(0.0, 0.0, 0.0, 1.0);
- ctf.addRGBPoint(1.0, 0.0, 1.0, 0.5);
- ctf.addRGBPoint(2.0, 0.0, 1.0, 0.0);
- ctf.addRGBPoint(3.0, 1.0, 0.5, 0.0);
- ctf.addRGBPoint(4.0, 1.0, 0.0, 0.0);
- this.jgMapper.setLookupTable(ctf);
- const lut = this.jgMapper.getLookupTable();
- this.scalarBarActor.setScalarsToColors(lut);
- this.jgActor.setMapper(this.jgMapper);
- }
- generateTicks(numberOfTicks) {
- return (helper) => {
- const lastTickBounds = helper.getLastTickBounds();
- // compute tick marks for axes
- const scale = d3
- .scaleLinear()
- .domain([0.0, 1.0])
- .range([lastTickBounds[0], lastTickBounds[1]]);
- const samples = scale.ticks(numberOfTicks);
- const ticks = samples.map((tick) => scale(tick));
- // Replace minus "\u2212" with hyphen-minus "\u002D" so that parseFloat() works
- formatDefaultLocale({ minus: "\u002D" });
- const format = scale.tickFormat(ticks[0], ticks[ticks.length - 1], numberOfTicks);
- const tickStrings = ticks
- .map(format)
- .map((tick) => Number(parseFloat(tick).toPrecision(12)).toPrecision()); // d3 sometimes adds unwanted whitespace
- helper.setTicks(ticks);
- helper.setTickStrings(tickStrings);
- };
- }
- modelInit(validNodes, pipes) {
- this.validNodes = validNodes;
- this.pipes = pipes;
- this.modelCreate();
- }
- modelCreate() {
- console.log("modelInit..");
- const points = this.polyData.getPoints();
- const lines = this.polyData.getLines();
- //无节点actor
- this.validNodes.forEach((node) => {
- points.insertNextPoint(parseFloat(node.x), parseFloat(node.y), parseFloat(node.z));
- });
- //无管道actor
- this.pipes.forEach((pipe) => {
- let sid = this.indexIdByPipeNodeId(pipe.snId);
- let eid = this.indexIdByPipeNodeId(pipe.enId);
- lines.insertNextCell([sid, eid]);
- });
- //有节点actors
- const sphereSource = vtkSphereSource.newInstance({
- center: [0, 0, 0],
- radius: 4.0,
- });
- const mapper = vtkMapper.newInstance();
- mapper.setInputConnection(sphereSource.getOutputPort());
- this.validNodes.forEach((node) => {
- const actor = vtkActor.newInstance();
- actor.setMapper(mapper);
- actor.setPosition(parseFloat(node.x), parseFloat(node.y), parseFloat(node.z));
- actor.getProperty().setColor(WHITE);
- const nodeActor = {};
- nodeActor.node = node;
- nodeActor.actor = actor;
- this.nodeActors.push(nodeActor);
- });
- //有管道actors
- this.pipes.forEach((pipe) => {
- const lineSource = vtkLineSource.newInstance();
- let point1 = this.pointByPipeNodeId(pipe.snId);
- let point2 = this.pointByPipeNodeId(pipe.enId);
- lineSource.setPoint1(point1);
- lineSource.setPoint2(point2);
- lineSource.setResolution(12);
- const actor = vtkActor.newInstance();
- const mapper = vtkMapper.newInstance();
- actor.setMapper(mapper);
- actor.getProperty().setLineWidth(3);//设置线宽
- actor.getProperty().setColor(WHITE);
- mapper.setInputConnection(lineSource.getOutputPort());
- const pipeActor = {};
- pipeActor.pipe = pipe;
- pipeActor.actor = actor;
- this.pipeActors.push(pipeActor);
- });
- this.modelShow();
- this.renderer.resetCamera();
- this.renderWindow.render();
- }
- modelClearShow() {
- this.renderer.removeActor(this.actor);
- this.renderer.removeActor(this.actor2);
- this.nodeActors.forEach((nodeActor) => {
- this.renderer.removeActor(nodeActor.actor);
- });
- this.pipeActors.forEach((pipeActor) => {
- this.renderer.removeActor(pipeActor.actor);
- });
- }
- modelShow() {
- this.modelClearShow();
- if (!this.isSelectNode) {//不选择节点
- this.renderer.addActor(this.actor2);
- }
- if (!this.isSelectPipe) {//不选择管道
- this.renderer.addActor(this.actor);
- }
- if (this.isSelectNode) {//选择节点
- this.nodeActors.forEach((nodeActor) => {
- this.renderer.addActor(nodeActor.actor);
- });
- }
- if (this.isSelectPipe) {//选择管道
- this.pipeActors.forEach((pipeActor) => {
- this.renderer.addActor(pipeActor.actor);
- });
- }
- }
- selectNodes() {
- this.isSelectNode = true;
- this.isSelectPipe = false;
- this.modelShow();
- this.renderWindow.render();
- }
- selectPipes() {
- this.isSelectNode = false;
- this.isSelectPipe = true;
- this.modelShow();
- this.renderWindow.render();
- }
- selectNoting(){
- this.isSelectNode = false;
- this.isSelectPipe = false;
- this.modelShow();
- this.renderWindow.render();
- }
- /**
- * 根据id 获取对应的编号
- */
- indexIdByPipeNodeId(nid) {
- for (let index = 0; index < this.validNodes.length; index++) {
- const node = this.validNodes[index];
- if (node.id == nid) {
- return index;
- }
- }
- return 0;
- }
- pointByPipeNodeId(nid) {
- for (let index = 0; index < this.validNodes.length; index++) {
- const node = this.validNodes[index];
- if (node.id == nid) {
- return [parseFloat(node.x), parseFloat(node.y), parseFloat(node.z)];
- }
- }
- return 0;
- }
- clearModeAddJg() {
- this.renderer.addActor(this.jgActor);
- this.renderer.addActor(this.scalarBarActor);
- this.modelClearShow();
- this.isJg = true; //显示结果
- }
- clearJgAddMode() {
- this.renderer.removeActor(this.scalarBarActor);
- this.renderer.removeActor(this.jgActor);
- this.modelShow();
- this.isJg = false; //不显示结果
- }
- }
- function pickOnMouseEvent(event) {
- if (vtkmodel.interactor.isAnimating()) {
- // We should not do picking when interacting with the scene
- return;
- }
- const [x, y] = eventToWindowXY(event);
- // console.log([x,y]);
- // vtkmodel.pointerActor.setVisibility(false);
- vtkmodel.hardwareSelector
- .getSourceDataAsync(vtkmodel.renderer, x, y, x, y)
- .then((result) => {
- if (result) {
- processSelections(result.generateSelection(x, y, x, y));
- // processSelections(result.generateSelection(x, y, x, y));
- } else {
- // processSelections(null);
- }
- });
- }
- function eventToWindowXY(event) {
- // We know we are full screen => window.innerXXX
- // Otherwise we can use pixel device ratio or else...
- const { clientX, clientY } = event;
- const [width, height] = vtkmodel.apiSpecificRenderWindow.getSize();
- const x = Math.round((width * clientX) / window.innerWidth);
- const y = Math.round(height * (1 - clientY / window.innerHeight)); // Need to flip Y
- return [x, y];
- }
- function processSelections(selections) {
- if (!selections || selections.length === 0) {//没有选择
- if (vtkmodel.lastActor == null) {
- } else {
- // vtkmodel.lastActor.getProperty().setColor(WHITE);
- // vtkmodel.renderWindow.render();
- }
- // vtkmodel.lastActor = null;
- return;
- }
- const {
- worldPosition: rayHitWorldPosition,
- compositeID,
- prop,
- propID,
- attributeID,
- } = selections[0].getProperties();
- if (vtkmodel.lastActor != null) {
- vtkmodel.lastActor.getProperty().setColor(WHITE);
- vtkmodel.renderWindow.render();
- }
- vtkmodel.nodeActors.forEach((nodeActor) => {
- if (prop == nodeActor.actor) {
- vtkmodel.selectObj = nodeActor.node;
- prop.getProperty().setColor(GREEN);
- vtkmodel.lastActor = prop;
- console.log(vtkmodel.selectObj );
- }
- });
- vtkmodel.pipeActors.forEach((pipeActor) => {
- if (prop == pipeActor.actor) {
- vtkmodel.selectObj = pipeActor.pipe;
- prop.getProperty().setColor(GREEN);
- vtkmodel.lastActor = prop;
- console.log(vtkmodel.selectObj );
- }
- });
- if (vtkmodel.isJg) {//结果数据选择cell
- //选择Cell
- const input = prop.getMapper().getInputData();
- if (!input.getCells()) {
- input.buildCells();
- }
- const cellPoints = input.getCellPoints(attributeID);
- if (cellPoints) {
- const pointIds = cellPoints.cellPointIds;
- // Find the closest cell point, and use that as cursor position
- const points = Array.from(pointIds).map((pointId) =>
- input.getPoints().getPoint(pointId)
- );
- // const scalarDataArray=input.getPointData().getScalars().getData();
- // pointIds.forEach(pointId=>{
- // console.log(input.getPointData().getScalars().getName());
- // console.log(scalarDataArray[pointId]);//节点标量数据
- // });
- vtkmodel.selectJgPointId =pointIds[0];
- }
- }
- vtkmodel.renderWindow.render();
-
- }
- const throttleMouseHandler = throttle(pickOnMouseEvent, 20);
- const WHITE = [0, 0, 1];
- const GREEN = [0.1, 0.8, 0.1];
- const vtkmodel = new VtkModel();
- export { vtkmodel };
|