Code Monkey home page Code Monkey logo

Comments (12)

guidovanhilst avatar guidovanhilst commented on May 22, 2024 2

https://zalo.github.io/CascadeStudio/

Hey guys, Really cool, nice work!

from opencascade.js.

donalffons avatar donalffons commented on May 22, 2024 1

I found a super silly workaround for the problem with webidl2ts (will file an issue over there) and just added the type definition files in v0.1.16 this library. I tested it and it seems to work well. If you find any issues with it, let me know.

@guidovanhilst, I looked at your code. Unfortunately, one of the current limitations is that not all C++ methods can be exposed if they are overloaded by type of arguments only (vs by number of arguments). I randomly picked the following methods

	void BRepBuilderAPI_MakeEdge([Const, Ref] Handle_Geom_Curve C);
	void BRepBuilderAPI_MakeEdge(
		[Const, Ref] Handle_Geom2d_Curve L,
		[Const, Ref] Handle_Geom_Surface S
	);

If you think, those methods should be changed to something else, let's start a new issue. I hope I will find a solution for this limitation soon.

@zalo, I agree - let's keep this thread from getting bigger and bigger.

Hope you don't mind if I will close this now.

from opencascade.js.

donalffons avatar donalffons commented on May 22, 2024

That sounds super cool! I will have a shot at using this tool and if it works well, I will add it to the project.

Long-term, I think it might be better to go with Emscripten's "Embind" workflow, instead of the "IDL" workflow (for reasons... But I'm just guessing, haven't used Embind before). But for the moment, this will be super helpful to have in this library.

from opencascade.js.

zalo avatar zalo commented on May 22, 2024

Here's the use-case:
https://zalo.github.io/CascadeStudio/
I was inspired by your port and made a simple web-frontend to play with the API.

These typescript definitions are profoundly useful for discovering OCC functionality while playing around and mousing over types.
(though it probably also makes sense to have a simplified "Standard Library" for more OpenSCAD like workflows...)

(By the way, could I trouble you to include STEPControl_Writer in the main API as well? ๐Ÿ™ƒ )

from opencascade.js.

donalffons avatar donalffons commented on May 22, 2024

Wow, that just made my day. Yes sir, I'll get you the STEPControl_Writer stuff into the IDL + builds.
This tool looks super useful. I have also been thinking about publishing some examples using CodeSandbox but didn't have a chance yet to work that yet. I like the super fast response you get when making changes with your tool though and might actually use this for prototyping, myself.

And yes, auto-completion and type checking is super useful when prototyping with the library and speeds up the development process a lot. I have only started using typescript a few months ago and don't want to miss it anymore.

How do you integrate the VS code editor into your website? That's such a helpful tool for building web applications...

from opencascade.js.

zalo avatar zalo commented on May 22, 2024

Thank you! The VS Code editor is integrated via monaco-editor (Microsoft's browser-friendly version of VS Code).

I'm hoping to expand the tool's features a lot (particularly save/load/import functionality) so that the BRep workflow can be a viable competitor to OpenSCAD (and OpenJSCAD). :D

Also, not to be too much of a burden, but could you also consider including the other Make Primitive Functions and PolygonOnTriangulation? I had to do some unspeakable things to make a box earlier. ๐Ÿ™ƒ (and it would be nice to read edge triangulations into three.js for picking and whatnot).

from opencascade.js.

donalffons avatar donalffons commented on May 22, 2024

Also, not to be too much of a burden, but could you also consider including the other Make Primitive Functions and PolygonOnTriangulation? I had to do some unspeakable things to make a box earlier.

The build is running right now. Will let you know as soon as its done. I think I captured the most important parts of those interfaces. If something important is missing, let me know.

and it would be nice to read edge triangulations into three.js for picking and whatnot

If I understand you correctly, that should already be possible. You can use the TopExp_Explorer to iterate through different classes of geometry. Here is some example code that I used in some project recently:

  getEdgesFromShape() {
    const shape = this.shape;
    const ExpEdge = new this.openCascade.TopExp_Explorer();
    const edges = [];
    for(ExpEdge.Init(shape, this.openCascade.TopAbs_EDGE); ExpEdge.More(); ExpEdge.Next()) {
      const myEdge = this.openCascade.TopoDS.prototype.Edge(ExpEdge.Current());

      const adaptorCurve = new this.openCascade.BRepAdaptor_Curve(myEdge);
      const tangDef = new this.openCascade.GCPnts_TangentialDeflection(adaptorCurve, 0.1, 0.1);
      const thisEdge = [];
      for(let i = 0; i < tangDef.NbPoints(); i++) {
        thisEdge.push({
          x: tangDef.Value(i+1).X(),
          y: tangDef.Value(i+1).Y(),
          z: tangDef.Value(i+1).Z(),
        })
      }
      edges.push(thisEdge);
    }
    return edges;
  }

from opencascade.js.

donalffons avatar donalffons commented on May 22, 2024

New builds are up!

from opencascade.js.

donalffons avatar donalffons commented on May 22, 2024

@zalo, I also tried to run the webidl2ts script against the idl file with no success. I used this command

$ yarn webidl2ts -i ./opencascade.idl -n opencascade -ed -o ./dist/opencascade.d.ts
yarn run v1.22.4
$ /home/sebastian/Projects/opencascade.js/node_modules/.bin/webidl2ts -i ./opencascade.idl -n opencascade -ed -o ./dist/opencascade.d.ts
(node:173512) UnhandledPromiseRejectionWarning: WebIDLParseError: Syntax error at line 107, since `interface BRepPrimAPI_MakeCylinder`:
BRepPrimAPI_MakeCylinder implements BRepPrimAPI_MakeOneAxis;
^ Unrecognised tokens
    at tokeniser_Tokeniser.error (/home/sebastian/Projects/opencascade.js/node_modules/webidl2/dist/webidl2.js:1:20350)
    at r (/home/sebastian/Projects/opencascade.js/node_modules/webidl2/dist/webidl2.js:1:33487)
    at L (/home/sebastian/Projects/opencascade.js/node_modules/webidl2/dist/webidl2.js:1:34464)
    at Module.q (/home/sebastian/Projects/opencascade.js/node_modules/webidl2/dist/webidl2.js:1:34604)
    at Object.<anonymous> (/home/sebastian/Projects/opencascade.js/node_modules/webidl2ts/dist/parse-idl.js:47:43)
    at step (/home/sebastian/Projects/opencascade.js/node_modules/webidl2ts/dist/parse-idl.js:33:23)
    at Object.next (/home/sebastian/Projects/opencascade.js/node_modules/webidl2ts/dist/parse-idl.js:14:53)
    at /home/sebastian/Projects/opencascade.js/node_modules/webidl2ts/dist/parse-idl.js:8:71
    at new Promise (<anonymous>)
    at __awaiter (/home/sebastian/Projects/opencascade.js/node_modules/webidl2ts/dist/parse-idl.js:4:12)
(node:173512) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:173512) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Done in 0.87s.

It seems like the IDL parser has an issue with BRepPrimAPI_MakeCylinder implements BRepPrimAPI_MakeOneAxis; or any other statement of A implements B;. Did you have the same error? How did you manage to resolve that?

from opencascade.js.

zalo avatar zalo commented on May 22, 2024

Thank you for the example code and exposing all the extra functions! I was busy today, but Iโ€™m excited to get back into it and add it to CascadeStudio :)

I originally used a slightly different library for the typings and manually converted all of the โ€œimplementโ€s to the colon inheritance syntax; however later in the readme for this idl parser, I noticed it explicitly mentions the -e parameter as enabling a preprocess that does that conversion... maybe itโ€™s not activating for some reason?

from opencascade.js.

guidovanhilst avatar guidovanhilst commented on May 22, 2024

I tried to make the "make bottle". (see code below)
But goes wrong due to override of oc.BRepBuilderAPI_MakeEdge.
Would it be nice if the make bottle worked?

I have made a C# script app to run OCC C# from the browser(backend) See also: MakeBottle


function MakeBottle( myWidth,  myHeight,  myThickness)
        {
			var myNeckRadius = myThickness / 4;
            var myNeckHeight = myHeight / 10;
        
        
            let aPnt1 = new oc.gp_Pnt(-myWidth / 2, 0, 0);
            let aPnt2 = new oc.gp_Pnt(-myWidth / 2, -myThickness / 4, 0);
            let aPnt3 = new oc.gp_Pnt(0, -myThickness / 2, 0);
            let aPnt4 = new oc.gp_Pnt(myWidth / 2, -myThickness / 4, 0);
            let aPnt5 = new oc.gp_Pnt(myWidth / 2, 0, 0);


            //Profile : Define the Geometry
            let aArcOfCircle = new oc.GC_MakeArcOfCircle(aPnt2, aPnt3, aPnt4).Value();

            //Profile : Define the Topology
            let aEdge1 = new oc.BRepBuilderAPI_MakeEdge(aPnt1, aPnt2).Edge();
            let aEdge2 = new oc.BRepBuilderAPI_MakeEdge(aArcOfCircle).Edge();
            let aEdge3 = new oc.BRepBuilderAPI_MakeEdge(aPnt4, aPnt5).Edge();
            let aWire = new oc.BRepBuilderAPI_MakeWire(aEdge1, aEdge2, aEdge3).Wire();

            //Complete Profile
            let xAxis = oc.gp.OX();
            let aTrsf = new oc.gp_Trsf();

            aTrsf.SetMirror(xAxis);

            let aBRepTrsf = new oc.BRepBuilderAPI_Transform(aWire, aTrsf, false);
            let aMirroredShape = aBRepTrsf.Shape();
            let aMirroredWire = oc.TopoDS.Wire(aMirroredShape);

            let mkWire = new oc.BRepBuilderAPI_MakeWire();

            mkWire.Add(aWire);
            mkWire.Add(aMirroredWire);

            let myWireProfile = mkWire.Wire();

            //Body : Prism the Profile
            let myFaceProfile = new oc.BRepBuilderAPI_MakeFace(myWireProfile, true).Face();
            let aPrismVec = new oc.gp_Vec(0, 0, myHeight);

            let myBody = new oc.BRepPrimAPI_MakePrism(myFaceProfile, aPrismVec, true, false).Shape();

            //Body : Apply Fillets
            let mkFillet = new oc.BRepFilletAPI_MakeFillet(myBody, oc.ChFi3d_FilletShape.ChFi3d_Rational);
            let aEdgeExplorer = new oc.TopExp_Explorer(myBody, oc.TopAbs_ShapeEnum.TopAbs_EDGE, oc.TopAbs_ShapeEnum.TopAbs_SHAPE);

            while (aEdgeExplorer.More())
            {
                let aEdge = oc.TopoDS.Edge(aEdgeExplorer.Current());
                //Add edge to fillet algorithm
                mkFillet.Add(myThickness / 12, aEdge);
                aEdgeExplorer.Next();
            }

            myBody = mkFillet.Shape();

            //Body : Add the Neck	
            let neckLoc = new oc.gp_Pnt(0, 0, myHeight);
            let neckNormal = oc.gp.DZ();
            let neckAx2 = new oc.gp_Ax2(neckLoc.ation, neckNormal);

            

            let MKCylinder = new oc.BRepPrimAPI_MakeCylinder(neckAx2, myNeckRadius, myNeckHeight);
            let myNeck = MKCylinder.Shape();

            myBody = new oc.BRepAlgoAPI_Fuse(myBody, myNeck).Shape();

           

            //Body : Create a Hollowed Solid
            let faceToRemove = null;
            zMax = -1;

            let aFaceExplorer = new oc.TopExp_Explorer(myBody, oc.TopAbs_ShapeEnum.TopAbs_FACE, oc.TopAbs_ShapeEnum.TopAbs_SHAPE);

            while (aFaceExplorer.More())
            {

                let aFace = oc.TopoDS.Face(aFaceExplorer.Current());

                //Check if <aFace> is the top face of the bottle's neck
                let aSurface = oc.BRep_Tool.Surface(aFace);
                //if (aSurface is oc.Geom_Plane)
                if(aSurface.DynamicType().Name() == "Geom_Plane")
                {

                    let aPlane = Handle_Geom_Plane.DownCast(aSurface);
                    //oc.Geom_Plane aPlane = aSurface as oc.Geom_Plane;

                    let aPnt = aPlane.Location();
                    var aZ = aPnt.Z();
                    if (aZ > zMax)
                    {
                        zMax = aZ;
                        faceToRemove = aFace;
                    }
                }

                aFaceExplorer.Next();
            }

            let facesToRemove = new oc.TopTools_ListOfShape();
            
            facesToRemove.Append(faceToRemove);
            

            myBody = new oc.BRepOffsetAPI_MakeThickSolid(
              myBody, 
              facesToRemove, 
              -myThickness / 50, 
              1 / 1000, 
              oc.BRepOffset_Mode.BRepOffset_Pipe, 
              false, false, 
              oc.GeomAbs_JoinType.GeomAbs_Intersection).Shape();

            //return myBody;
            //Threading : Create Surfaces
            let neckAx3 = new oc.gp_Ax3(neckAx2);

            let aCyl1 = new oc.Geom_CylindricalSurface(neckAx3, myNeckRadius * 0.99);
            let aCyl2 = new oc.Geom_CylindricalSurface(neckAx3, myNeckRadius * 1.05);

            //Threading : Define 2D Curves
            let aPntc = new oc.gp_Pnt2d(2.0 * Math.PI, myNeckHeight / 2);
            let aDir = new oc.gp_Dir2d(2.0 * Math.PI, myNeckHeight / 4);
            let aAx2d = new oc.gp_Ax2d(aPntc, aDir);
            let aAx22d = new oc.gp_Ax22d(aPntc, aDir, true);

            var aMajor = 2.0 * Math.PI;
            var aMinor = myNeckHeight / 10;

            let anEllipse1 = new oc.Geom2d_Ellipse(aAx22d, aMajor, aMinor);
            let anEllipse2 = new oc.Geom2d_Ellipse(aAx22d, aMajor, aMinor / 4);

            let aArc1 = new oc.Geom2d_TrimmedCurve(anEllipse1, 0, Math.PI, true);
            let aArc2 = new oc.Geom2d_TrimmedCurve(anEllipse2, 0, Math.PI, true);

            let anEllipsePnt1 = anEllipse1.Value(0);
            let anEllipsePnt2 = anEllipse1.Value(Math.PI);

            let aSegment = new oc.GCE2d_MakeSegment(anEllipsePnt1, anEllipsePnt2).Value();

            //Threading : Build Edges and Wires
            let aEdge1OnSurf1 = new oc.BRepBuilderAPI_MakeEdge(aArc1, aCyl1).Edge();
            let aEdge2OnSurf1 = new oc.BRepBuilderAPI_MakeEdge(aSegment, aCyl1).Edge();
            let aEdge1OnSurf2 = new oc.BRepBuilderAPI_MakeEdge(aArc2, aCyl2).Edge();
            let aEdge2OnSurf2 = new oc.BRepBuilderAPI_MakeEdge(aSegment, aCyl2).Edge();

            let threadingWire1 = new oc.BRepBuilderAPI_MakeWire(aEdge1OnSurf1, aEdge2OnSurf1).Wire();
            let threadingWire2 = new oc.BRepBuilderAPI_MakeWire(aEdge1OnSurf2, aEdge2OnSurf2).Wire();

            oc.BRepLib.BuildCurves3d(threadingWire1);
            oc.BRepLib.BuildCurves3d(threadingWire2);

            //Create Threading
            let aTool = new oc.BRepOffsetAPI_ThruSections(true, true, 0.001);

            aTool.AddWire(threadingWire1);
            aTool.AddWire(threadingWire2);
            aTool.CheckCompatibility(false);

            let myThreading = aTool.Shape();

            //Building the resulting compound
            let aRes = new oc.TopoDS_Compound();
            let aBuilder= new oc.BRep_Builder();

            aBuilder.MakeCompound(aRes);

            aBuilder.Add(aRes, myBody);
            aBuilder.Add(aRes, myThreading);


            return aRes;


        }


function CompileModel() {

    console.log("Model Compiling...");

    // Create a Sphere
    let spherePlane    = new oc.gp_Ax2(new oc.gp_Pnt(0, 0, 50.), oc.gp.prototype.DZ());
    let sphere         = new oc.BRepPrimAPI_MakeSphere(spherePlane, 50.0).Shape();

    // Create Cylinders to Subtract
    let xCylinderPlane = new oc.gp_Ax2(new oc.gp_Pnt(-100, 0, 50), new oc.gp_Dir(1, 0, 0));
    let yCylinderPlane = new oc.gp_Ax2(new oc.gp_Pnt(0, -100, 50), new oc.gp_Dir(0, 1, 0));
    let zCylinderPlane = new oc.gp_Ax2(new oc.gp_Pnt(0,    0,-50), new oc.gp_Dir(0, 0, 1));
    let xCylinder      = new oc.BRepPrimAPI_MakeCylinder(xCylinderPlane, GUIState['Radius'], 200.0).Shape();
    let yCylinder      = new oc.BRepPrimAPI_MakeCylinder(yCylinderPlane, GUIState['Radius'], 200.0).Shape();
    let zCylinder      = new oc.BRepPrimAPI_MakeCylinder(zCylinderPlane, GUIState['Radius'], 200.0).Shape();

    // Cut the Cylinders from the Sphere
    sphere             = new oc.BRepAlgoAPI_Cut(sphere, xCylinder).Shape();
    sphere             = new oc.BRepAlgoAPI_Cut(sphere, yCylinder).Shape();
    sphere             = new oc.BRepAlgoAPI_Cut(sphere, zCylinder).Shape();


    // Convert to a mesh
    console.log("Compilation Complete! Converting to Mesh...");
    //cascadeViewport.updateShape(sphere, GUIState["Res"]);
    //cascadeViewport.updateShape(externalShapes['Pipe cut profile test Rhino step AP203.stp'], GUIState["Res"]);
	
	//Make bottle
    var Width=30.0;
    var Height=30.0;
    var  Thicknes=15.0;

    let bottle = MakeBottle(Width, Height, Thicknes);
    cascadeViewport.updateShape(bottle, GUIState["Res"]);
   
    console.log("Generation Complete!");
}

// Define GUI State Variables here
Object.assign(GUIState, {
    "Res"    : 0.1,  "ResRange"    : [0.01, 1.00],
    "Radius" : 30.0, "RadiusRange" : [27.0, 35.0] });

// GUI uses https://github.com/automat/controlkit.js
gui.addPanel({label: 'Cascade Control Panel'})
   .addButton     ('Generate Model' ,                             () => { CompileModel(); }  )
   .addSlider     (GUIState, 'Res',       'ResRange', { onFinish: () => { CompileModel(); }} )
   .addSlider     (GUIState, 'Radius', 'RadiusRange', { onFinish: () => { CompileModel(); }} );

from opencascade.js.

zalo avatar zalo commented on May 22, 2024

@guidovanhilst Perhaps better for another issue? (I feel bad about overloading this one so much already...)

MakeBottle (or a version of it) does appear to work, however; did you try the version from the example repo?
https://github.com/donalffons/opencascade.js-examples/blob/master/src/main.js#L46-L182

One of my goals with CascadeStudio is to expose better error handling inside the text editor... hopefully that extends to detecting type mismatches...

from opencascade.js.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.