step file import support

This commit is contained in:
Val Erastov 2022-07-30 23:40:27 -07:00
parent ac6e8dc567
commit 9c82d662b0
9 changed files with 96 additions and 50 deletions

View file

@ -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);

View 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
View file

@ -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",

View file

@ -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",

View file

@ -1,4 +1,4 @@
interface OCCCommands { export interface OCCCommands {
/* /*
2dbeziercurve name nbpole pole, [weight] 2dbeziercurve name nbpole pole, [weight]
*/ */

View file

@ -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;

View file

@ -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);
}

View file

@ -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;

View file

@ -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;
}
}