mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-06 16:33:15 +01:00
step file import support
This commit is contained in:
parent
ac6e8dc567
commit
9c82d662b0
9 changed files with 96 additions and 50 deletions
|
|
@ -3,7 +3,33 @@ import React from 'react';
|
||||||
export interface LocalFile {
|
export interface LocalFile {
|
||||||
|
|
||||||
fileName: string;
|
fileName: string;
|
||||||
content: string;
|
dataUrl: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export class LocalFileAdapter implements LocalFile {
|
||||||
|
|
||||||
|
localFile: LocalFile;
|
||||||
|
|
||||||
|
constructor(localFile: LocalFile) {
|
||||||
|
this.localFile = localFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
get fileName() {
|
||||||
|
return this.localFile.fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
get dataUrl() {
|
||||||
|
return this.localFile.dataUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
base64Content() {
|
||||||
|
return getBase64FromDataUrl(this.dataUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
rawContent() {
|
||||||
|
return atob(getBase64FromDataUrl(this.dataUrl));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBase64FromDataUrl(dataUrl: string): string {
|
export function getBase64FromDataUrl(dataUrl: string): string {
|
||||||
|
|
@ -29,7 +55,7 @@ export default class FileControl extends React.Component<any> {
|
||||||
const dataUrl = evt.target.result as string;
|
const dataUrl = evt.target.result as string;
|
||||||
onChange({
|
onChange({
|
||||||
fileName: name,
|
fileName: name,
|
||||||
content: dataUrl
|
dataUrl,
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
reader.readAsDataURL(file);
|
reader.readAsDataURL(file);
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,14 @@
|
||||||
import { roundValueForPresentation as r } from 'cad/craft/operationHelper';
|
import {ApplicationContext} from "context";
|
||||||
import { ApplicationContext } from "context";
|
import {OperationDescriptor} from "cad/craft/operationPlugin";
|
||||||
import { EntityKind } from "cad/model/entities";
|
import {LocalFile, LocalFileAdapter} from "ui/components/controls/FileControl";
|
||||||
import { BooleanDefinition } from "cad/craft/schema/common/BooleanDefinition";
|
|
||||||
import { OperationDescriptor } from "cad/craft/operationPlugin";
|
|
||||||
import { param } from 'cypress/types/jquery';
|
|
||||||
import { MObject } from 'cad/model/mobject';
|
|
||||||
import { LocalFile } from "ui/components/controls/FileControl";
|
|
||||||
import CadError from "../../../../../web/app/utils/errors";
|
import CadError from "../../../../../web/app/utils/errors";
|
||||||
import { parseStringPromise } from 'xml2js';
|
import {parseStringPromise} from 'xml2js';
|
||||||
import * as jszip from "jszip";
|
import {importStepFile} from "cad/craft/e0/interact";
|
||||||
import { FcElectricalSensor } from 'react-icons/fc';
|
import {clone} from "gems/objects";
|
||||||
|
import JSZip from "jszip";
|
||||||
|
|
||||||
interface ImportModelParams {
|
interface ImportModelParams {
|
||||||
file: LocalFile;
|
file: LocalFileAdapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ImportModelOpperation: OperationDescriptor<ImportModelParams> = {
|
export const ImportModelOpperation: OperationDescriptor<ImportModelParams> = {
|
||||||
|
|
@ -31,35 +26,31 @@ export const ImportModelOpperation: OperationDescriptor<ImportModelParams> = {
|
||||||
|
|
||||||
|
|
||||||
const FileName = params.file.fileName.toUpperCase();
|
const FileName = params.file.fileName.toUpperCase();
|
||||||
let fileToRead = await atob(await params.file.content.slice(await params.file.content.indexOf(',') + 1));
|
let rawContent = params.file.rawContent();
|
||||||
//console.log(params.file.content);
|
//console.log(params.file.content);
|
||||||
//console.log(fileToRead);
|
//console.log(rawContent);
|
||||||
|
|
||||||
if (FileName.endsWith("BRP") || FileName.endsWith("BREP")) {
|
if (FileName.endsWith("BRP") || FileName.endsWith("BREP")) {
|
||||||
//FreeCAD some times omits this text from the top of BRP files
|
//FreeCAD some times omits this text from the top of BRP files
|
||||||
//as part of the brp files stored in the .FCStf file archive format
|
//as part of the brp files stored in the .FCStf file archive format
|
||||||
if (!fileToRead.startsWith("DBRep_DrawableShape")) {
|
if (!rawContent.startsWith("DBRep_DrawableShape")) {
|
||||||
fileToRead = `DBRep_DrawableShape\n` + fileToRead;
|
rawContent = `DBRep_DrawableShape\n` + rawContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
FS.writeFile("newBREPobject", (fileToRead));
|
FS.writeFile("newBREPobject", rawContent);
|
||||||
oci.readbrep("newBREPobject", "newBREPobject");
|
oci.readbrep("newBREPobject", "newBREPobject");
|
||||||
returnObject.created.push(occ.io.getShell("newBREPobject"));
|
returnObject.created.push(occ.io.getShell("newBREPobject"));
|
||||||
} else if (FileName.endsWith("FCSTD")) {
|
} else if (FileName.endsWith("FCSTD")) {
|
||||||
var JSZip = require("jszip");
|
|
||||||
|
|
||||||
const zipContents = await (await JSZip.loadAsync(btoa(fileToRead), { base64: true })).files;
|
const zipContents = (await JSZip.loadAsync(params.file.base64Content(), { base64: true })).files;
|
||||||
var xmlFreeCADData = await zipContents["Document.xml"].async("string");
|
const xmlFreeCADData = await zipContents["Document.xml"].async("string");
|
||||||
|
|
||||||
let DecodedXmlFreeCADData = (JSON.parse(JSON.stringify(await parseStringPromise(xmlFreeCADData)))).Document.ObjectData[0].Object;
|
|
||||||
//console.log(DecodedXmlFreeCADData);
|
|
||||||
|
|
||||||
|
let DecodedXmlFreeCADData = (clone(await parseStringPromise(xmlFreeCADData))).Document.ObjectData[0].Object;
|
||||||
|
|
||||||
for (const itemToLookAt in DecodedXmlFreeCADData) {
|
for (const itemToLookAt in DecodedXmlFreeCADData) {
|
||||||
const flattenedObject = flattenJSON(DecodedXmlFreeCADData[itemToLookAt]);
|
const flattenedObject = flattenJSON(DecodedXmlFreeCADData[itemToLookAt]);
|
||||||
let importBrepFlag = false;
|
let importBrepFlag = false;
|
||||||
let importBrepShapeName = "";
|
let importBrepShapeName = "";
|
||||||
let visiblePropertyName = "";
|
|
||||||
for (const propertyToLookAt in flattenedObject) {
|
for (const propertyToLookAt in flattenedObject) {
|
||||||
//console.log(propertyToLookAt + " = " + flattenedObject[propertyToLookAt]);
|
//console.log(propertyToLookAt + " = " + flattenedObject[propertyToLookAt]);
|
||||||
importBrepFlag = false;
|
importBrepFlag = false;
|
||||||
|
|
@ -71,12 +62,13 @@ export const ImportModelOpperation: OperationDescriptor<ImportModelParams> = {
|
||||||
console.log(shouldItImport, importBrepShapeName);
|
console.log(shouldItImport, importBrepShapeName);
|
||||||
if (shouldItImport == "true") {
|
if (shouldItImport == "true") {
|
||||||
try {
|
try {
|
||||||
await FS.writeFile(importBrepShapeName, `DBRep_DrawableShape\n` + await zipContents[importBrepShapeName].async("string"));
|
const zipContent = await zipContents[importBrepShapeName].async("string");
|
||||||
|
await FS.writeFile(importBrepShapeName, `DBRep_DrawableShape\n` + zipContent);
|
||||||
await oci.readbrep(importBrepShapeName, importBrepShapeName);
|
await oci.readbrep(importBrepShapeName, importBrepShapeName);
|
||||||
returnObject.created.push(occ.io.getShell(importBrepShapeName));
|
returnObject.created.push(occ.io.getShell(importBrepShapeName));
|
||||||
console.log(importBrepShapeName);
|
console.debug(importBrepShapeName);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e)
|
console.warn(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -87,14 +79,14 @@ export const ImportModelOpperation: OperationDescriptor<ImportModelParams> = {
|
||||||
} else if (FileName.endsWith("STEP") || FileName.endsWith("STP")) {
|
} else if (FileName.endsWith("STEP") || FileName.endsWith("STP")) {
|
||||||
|
|
||||||
//step Import
|
//step Import
|
||||||
FS.writeFile("newStepObject", (params.file.content));
|
FS.writeFile("newStepFile", rawContent);
|
||||||
oci.stepread("newStepObject", "newStepObject");
|
importStepFile("newStepObject", "newStepFile", true);
|
||||||
returnObject.created.push(occ.io.getShell("newStepObject"));
|
returnObject.created.push(occ.io.getShell("newStepObject"));
|
||||||
|
|
||||||
} else if (FileName.endsWith("IGES") || FileName.endsWith("IGS")) {
|
} else if (FileName.endsWith("IGES") || FileName.endsWith("IGS")) {
|
||||||
|
|
||||||
//IGES import
|
//IGES import
|
||||||
FS.writeFile("newIgesObject", (params.file.content));
|
FS.writeFile("newIgesObject", rawContent);
|
||||||
oci.igesread("newIgesObject", "newIgesObject");
|
oci.igesread("newIgesObject", "newIgesObject");
|
||||||
returnObject.created.push(occ.io.getShell("newIgesObject"));
|
returnObject.created.push(occ.io.getShell("newIgesObject"));
|
||||||
|
|
||||||
|
|
@ -103,14 +95,11 @@ export const ImportModelOpperation: OperationDescriptor<ImportModelParams> = {
|
||||||
kind: CadError.KIND.INVALID_INPUT,
|
kind: CadError.KIND.INVALID_INPUT,
|
||||||
code: 'File type not supported at this time'
|
code: 'File type not supported at this time'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return returnObject;
|
return returnObject;
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
form: [
|
form: [
|
||||||
{
|
{
|
||||||
type: 'file',
|
type: 'file',
|
||||||
|
|
@ -122,12 +111,12 @@ export const ImportModelOpperation: OperationDescriptor<ImportModelParams> = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const flattenJSON = (obj = {}, res = {}, extraKey = '') => {
|
const flattenJSON = (obj = {}, res = {}, extraKey = '') => {
|
||||||
for (key in obj) {
|
for (let key of Object.keys(obj)) {
|
||||||
if (typeof obj[key] !== 'object') {
|
if (typeof obj[key] !== 'object') {
|
||||||
res[extraKey + key] = obj[key];
|
res[extraKey + key] = obj[key];
|
||||||
} else {
|
} else {
|
||||||
flattenJSON(obj[key], res, `${extraKey}${key}.`);
|
flattenJSON(obj[key], res, `${extraKey}${key}.`);
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
14
package-lock.json
generated
14
package-lock.json
generated
|
|
@ -14,7 +14,7 @@
|
||||||
"earcut": "2.1.1",
|
"earcut": "2.1.1",
|
||||||
"font-awesome": "4.7.0",
|
"font-awesome": "4.7.0",
|
||||||
"immer": "^9.0.12",
|
"immer": "^9.0.12",
|
||||||
"jsketcher-occ-engine": "1.0.1-055e9551d187d751bf4850255121de8971c1c7bc",
|
"jsketcher-occ-engine": "1.0.1-9e267e3f1d283ebaa7cb1d5d11b529823e00b360",
|
||||||
"jszip": "^3.10.0",
|
"jszip": "^3.10.0",
|
||||||
"less": "^3.11.1",
|
"less": "^3.11.1",
|
||||||
"libtess": "1.2.2",
|
"libtess": "1.2.2",
|
||||||
|
|
@ -9164,9 +9164,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/jsketcher-occ-engine": {
|
"node_modules/jsketcher-occ-engine": {
|
||||||
"version": "1.0.1-055e9551d187d751bf4850255121de8971c1c7bc",
|
"version": "1.0.1-9e267e3f1d283ebaa7cb1d5d11b529823e00b360",
|
||||||
"resolved": "https://registry.npmjs.org/jsketcher-occ-engine/-/jsketcher-occ-engine-1.0.1-055e9551d187d751bf4850255121de8971c1c7bc.tgz",
|
"resolved": "https://registry.npmjs.org/jsketcher-occ-engine/-/jsketcher-occ-engine-1.0.1-9e267e3f1d283ebaa7cb1d5d11b529823e00b360.tgz",
|
||||||
"integrity": "sha512-Uqf5cJovjdBXfoKuL+hquiWQAr7OP4AeVWeIdHYVMXkMpuZW01BjTkhKucyrwV7odWpDrzZsJrDtoYCjS6X2yw=="
|
"integrity": "sha512-Eyj1ooaO+BqWLtM9GHHJ7GP18r23p9pCcHc437L8XmCBSEEVXgvLG7Hwr0FZUYSaszdevmHmQVEkuYlTPXYLmg=="
|
||||||
},
|
},
|
||||||
"node_modules/json-parse-better-errors": {
|
"node_modules/json-parse-better-errors": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
|
|
@ -23437,9 +23437,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"jsketcher-occ-engine": {
|
"jsketcher-occ-engine": {
|
||||||
"version": "1.0.1-055e9551d187d751bf4850255121de8971c1c7bc",
|
"version": "1.0.1-9e267e3f1d283ebaa7cb1d5d11b529823e00b360",
|
||||||
"resolved": "https://registry.npmjs.org/jsketcher-occ-engine/-/jsketcher-occ-engine-1.0.1-055e9551d187d751bf4850255121de8971c1c7bc.tgz",
|
"resolved": "https://registry.npmjs.org/jsketcher-occ-engine/-/jsketcher-occ-engine-1.0.1-9e267e3f1d283ebaa7cb1d5d11b529823e00b360.tgz",
|
||||||
"integrity": "sha512-Uqf5cJovjdBXfoKuL+hquiWQAr7OP4AeVWeIdHYVMXkMpuZW01BjTkhKucyrwV7odWpDrzZsJrDtoYCjS6X2yw=="
|
"integrity": "sha512-Eyj1ooaO+BqWLtM9GHHJ7GP18r23p9pCcHc437L8XmCBSEEVXgvLG7Hwr0FZUYSaszdevmHmQVEkuYlTPXYLmg=="
|
||||||
},
|
},
|
||||||
"json-parse-better-errors": {
|
"json-parse-better-errors": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@
|
||||||
"earcut": "2.1.1",
|
"earcut": "2.1.1",
|
||||||
"font-awesome": "4.7.0",
|
"font-awesome": "4.7.0",
|
||||||
"immer": "^9.0.12",
|
"immer": "^9.0.12",
|
||||||
"jsketcher-occ-engine": "1.0.1-055e9551d187d751bf4850255121de8971c1c7bc",
|
"jsketcher-occ-engine": "1.0.1-9e267e3f1d283ebaa7cb1d5d11b529823e00b360",
|
||||||
"jszip": "^3.10.0",
|
"jszip": "^3.10.0",
|
||||||
"less": "^3.11.1",
|
"less": "^3.11.1",
|
||||||
"libtess": "1.2.2",
|
"libtess": "1.2.2",
|
||||||
|
|
|
||||||
2
web/app/cad/craft/e0/OCI.d.ts
vendored
2
web/app/cad/craft/e0/OCI.d.ts
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
interface OCCCommands {
|
export interface OCCCommands {
|
||||||
/*
|
/*
|
||||||
2dbeziercurve name nbpole pole, [weight]
|
2dbeziercurve name nbpole pole, [weight]
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
3
web/app/cad/craft/e0/interact.d.ts
vendored
3
web/app/cad/craft/e0/interact.d.ts
vendored
|
|
@ -19,3 +19,6 @@ export function UpdateTessellation(shapePtr: number, deflection: number): number
|
||||||
export function SetLocation(shapeName: string, matrixArray: number[]);
|
export function SetLocation(shapeName: string, matrixArray: number[]);
|
||||||
|
|
||||||
export function AddLocation(shapeName: string, matrixArray: number[]);
|
export function AddLocation(shapeName: string, matrixArray: number[]);
|
||||||
|
|
||||||
|
export function importStepFile(shapeName: string, fileName: string, oneOnly: boolean): number;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -128,3 +128,11 @@ export function AddLocation(shapeName, matrixArray) {
|
||||||
);
|
);
|
||||||
_free(shapeNamePtr);
|
_free(shapeNamePtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function importStepFile(shapeName, fileName, oneOnly) {
|
||||||
|
const shapeNamePtr = toCString(shapeName);
|
||||||
|
const fileNamePtr = toCString(fileName);
|
||||||
|
Module._ImportStepFile(shapeNamePtr, fileNamePtr, oneOnly);
|
||||||
|
_free(shapeNamePtr);
|
||||||
|
_free(fileName);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import {CallCommand} from "cad/craft/e0/interact";
|
import {CallCommand} from "cad/craft/e0/interact";
|
||||||
import {MObject} from "cad/model/mobject";
|
import {MObject} from "cad/model/mobject";
|
||||||
|
import {OCCCommands} from "cad/craft/e0/OCI";
|
||||||
|
|
||||||
export type OCCCommandInterface = OCCCommands;
|
export type OCCCommandInterface = OCCCommands;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ import {FileField} from "cad/craft/wizard/components/form/Fields";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {FieldBasicProps, fieldToSchemaGeneric} from "cad/mdf/ui/field";
|
import {FieldBasicProps, fieldToSchemaGeneric} from "cad/mdf/ui/field";
|
||||||
import {Types} from "cad/craft/schema/types";
|
import {Types} from "cad/craft/schema/types";
|
||||||
|
import {LocalFile, LocalFileAdapter} from "ui/components/controls/FileControl";
|
||||||
|
import {ValueResolver} from "cad/craft/schema/schema";
|
||||||
|
|
||||||
export interface FileWidgetProps extends FieldBasicProps {
|
export interface FileWidgetProps extends FieldBasicProps {
|
||||||
|
|
||||||
|
|
@ -14,18 +16,35 @@ export function FileWidget(props: FileWidgetProps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
FileWidget.propsToSchema = (props: FileWidgetProps) => {
|
FileWidget.propsToSchema = (props: FileWidgetProps) => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: Types.object,
|
type: Types.object,
|
||||||
schema: {
|
schema: {
|
||||||
fileName: {
|
fileName: {
|
||||||
type: 'string'
|
type: 'string'
|
||||||
},
|
},
|
||||||
content: {
|
dataUrl: {
|
||||||
type: 'string'
|
type: 'string'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
...fieldToSchemaGeneric(props),
|
...fieldToSchemaGeneric(props),
|
||||||
|
|
||||||
|
resolve: chainResolver(
|
||||||
|
(ctx, localFile: LocalFile) => new LocalFileAdapter(localFile),
|
||||||
|
props.resolve
|
||||||
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function chainResolver(...resolvers: ValueResolver<any, any>[]): ValueResolver<any, any> {
|
||||||
|
|
||||||
|
return (ctx, value, md, reportH) => {
|
||||||
|
let updatedValue = value;
|
||||||
|
resolvers.forEach(resolver => {
|
||||||
|
if (resolver) {
|
||||||
|
updatedValue = resolver(ctx, updatedValue, md, reportH);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return updatedValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue