# Would this be a good exercise for marionette?

## Recommended Posts

I posted this on the general forum but it occurred to me that surely this is the sort of thing that one should be able to do with marionette?

I haven’t really tried marionette before but thought this is something that could be useful and a good challenge to get me going.

Could be interesting.

I think this will be a challenge in any programming language. And maybe harder in Marionette than in others.

IF this was an easy thing to program, there would already be programs and algorithms out there doing it.

It looks like this is just barely starting to come out of academia.

Do a Google search for "algorithm to convert orthogonal views to 3D model" to see some of the info about what it takes.

Hmm ok. Yes I understand that this would be extremely difficult to do if you wanted it to work for a wide variety of types of objects and if you wanted precise 3d objects, I'm definitely not up to that task!

I was thinking just supply a marionette with 3x simple polygon orthogonal views - "plan", "front", and "side". The marionette would do the process of extruding the polys then adding/subtracting the extrudes to create a simple solid that bears a bit more resemblance to the actual object than a single extrusion of a plan would.

If I can do one manually in a few minutes surely a marionette can be created that can do multiple ones for me in a few seconds?

Believe it or not, but I think this would be VERY complicated in Marionette.  Marionette is not all that flexible and can be a bit of a nightmare to work with, though I suppose it might be possible as long as the nodes exist.

But I think I was able to make this happen using Vectorscript.  After running the command, it will ask you to select a Plan object, a Front object, and a Side object, in that order.  These objects can be anything that can be extruded (circles, rectangles, polygons, polylines, etc).  The script will extrude these along a path as well as a solid rectangle a little larger than the bounding box of the profile, then subtract these objects to create a "cutting" object for the front and side.  It then subtracts these from an extrude created by the plan object.

I haven't tested this with a wide variety of objects, so it might still break with something complicated, but it is worth trying out.  Video of me testing it is below as well as the source code.  Feel free to save it in a script palette or make it a full blown menu command.

Video of me testing the tool.  Windows won't capture floating palettes in screen cap video, so imagine me selecting the script from a script palette.

Vectorscript code.  It's probably a little rough in terms of variable naming and such, but it certainly works.  I also only tested it in Freedom Units, so let me know if it breaks when exposed to the logic of the Metric System.

```PROCEDURE Ortho2Dto3D;

{*	Polls for plan, front, and side objects and produces simple 3D object
Developed by: Jesse Cogswell
Date: 4/11/2021
VW Version: 2019
Revisions:
*}

CONST

BUFF = 6;

VAR

frontA,frontB,sideA,sideB:POINT;
origin,trackLoc:POINT3D;
width,height,depth,centerZ:REAL;
plan,frontProfile,sideProfile,planObj,frontObj,sideObj:HANDLE;
result:INTEGER;

FUNCTION CheckObjCallback(h:HANDLE) : BOOLEAN;

{Provides Callback for selecting extrude objects}

VAR

objType:INTEGER;

BEGIN
objType:=GetTypeN(h);
IF((objType=3)|(objType=4)|(objType=5)|(objType=6)|(objType=13)|(objType=21)) THEN CheckObjCallback:=TRUE;
END;

FUNCTION CreatePlanObj(h:HANDLE; rBase,rDepth:REAL) : HANDLE;

{Creates 3D object representing plan geometry}

VAR

tempHd:HANDLE;

BEGIN
tempHd:=CreateDuplicateObject(h,NIL);
CreatePlanObj:=HExtrude(tempHd,rBase,rDepth);
END;

FUNCTION CreateFrontObj(h:HANDLE; pOrigin:POINT3D; pA,pB:POINT; rHeight,rDepth:REAL) : HANDLE;

{Accepts profile information and returns Handle to 3D geometry of front subtract object}

VAR

pathHd,rectHd,cutHd,solidHd,objHd:HANDLE;
objCtr:POINT3D;
subResult:INTEGER;

BEGIN
{Create Path}
MoveTo(pOrigin.x,pOrigin.y-(rHeight*0.5)-BUFF);
LineTo(pOrigin.x,pOrigin.y+(rHeight*0.5)+BUFF);
pathHd:=LNewObj;
Move3DObj(pathHd,0,0,(rDepth*0.5));

{Create Profile}
Rect(pA.x-BUFF,pA.y+BUFF,pB.x+BUFF,pB.y-BUFF);
rectHd:=LNewObj;

{Extrude Cut Profiles}
solidHd:=ExtrudeAlongPath(pathHd,rectHd);
cutHd:=ExtrudeAlongPath(pathHd,h);
DelObject(rectHd);
DelObject(pathHd);

subResult:=SubtractSolid(solidHd,cutHd,objHd);

{Move 3D Geometry to Plan object center}
Get3DCntr(objHd,objCtr.x,objCtr.y,objCtr.z);
Move3DObj(objHd,0-objCtr.x+pOrigin.x,0,0-objCtr.z+(rDepth*0.5));

IF(subResult=0) THEN CreateFrontObj:=objHd;
END;

FUNCTION CreateSideObj(h:HANDLE; pOrigin:POINT3D; pA,pB:POINT; rWidth,rDepth:REAL) : HANDLE;

{Accepts profile information and returns Handle to 3D geometry of side subtract object}

VAR

pathHd,rectHd,cutHd,solidHd,objHd:HANDLE;
objCtr:POINT3D;
subResult:INTEGER;

BEGIN
{Create Path}
MoveTo(pOrigin.x+(rWidth*0.5)+BUFF,pOrigin.y);
LineTo(pOrigin.x-(rWidth*0.5)-BUFF,pOrigin.y);
pathHd:=LNewObj;
Move3DObj(pathHd,0,0,(rDepth*0.5));

{Create Profile}
Rect(pA.x-BUFF,pA.y+BUFF,pB.x+BUFF,pB.y-BUFF);
rectHd:=LNewObj;

{Extrude Cut Profile}
solidHd:=ExtrudeAlongPath(pathHd,rectHd);
cutHd:=ExtrudeAlongPath(pathHd,h);
DelObject(rectHd);
DelObject(pathHd);

subResult:=SubtractSolid(solidHd,cutHd,objHd);

{Move 3D Geometry to Plan object center}
Get3DCntr(objHd,objCtr.x,objCtr.y,objCtr.z);
Move3DObj(objHd,0,0-objCtr.y+pOrigin.y,0-objCtr.z+(rDepth*0.5));

IF(subResult=0) THEN CreateSideObj:=objHd;
END;

BEGIN
{Poll Plan object}
SetTempToolHelpStr('Select Plan Object');
TrackObject(CheckObjCallback,plan,trackLoc.x,trackLoc.y,trackLoc.z);
HCenter(plan,origin.x,origin.y);
origin.z:=0;

{Poll Front object}
SetTempToolHelpStr('Select Front Object');
TrackObject(CheckObjCallback,frontProfile,trackLoc.x,trackLoc.y,trackLoc.z);

{Poll Side object}
SetTempToolHelpStr('Select Side Object');
TrackObject(CheckObjCallback,sideProfile,trackLoc.x,trackLoc.y,trackLoc.z);

{Get bounding boxes for Front and Side}
GetBBox(frontProfile,frontA.x,frontA.y,frontB.x,frontB.y);
GetBBox(sideProfile,sideA.x,sideA.y,sideB.x,sideB.y);

{Determine overall dimensions}
width:=frontB.x-frontA.x;
height:=sideB.x-sideA.x;
depth:=frontA.y-frontB.y;

{Create 3D Geometry}
planObj:=CreatePlanObj(plan,origin.z,depth);
frontObj:=CreateFrontObj(frontProfile,origin,frontA,frontB,height,depth);
sideObj:=CreateSideObj(sideProfile,origin,sideA,sideB,width,depth);

{Cut Objects}
result:=SubtractSolid(planObj,frontObj,planObj);
result:=SubtractSolid(planObj,sideObj,planObj);
END;

Run(Ortho2Dto3D);```

Wow Jesse that is pretty cool! For a script illiterate player like myself I find this sort of thing pretty amazing. So it looks like I need another idea to start my marionette journey...!

I've played around with it a little and once I realised that you need to be in top/plan view to make it work it was fun knocking out a few basic 3d solids. I did manage to get it all going in vw2019 but vw2021 doesn't seem to want to play ball:

I meant to warn you about it only working in Top/Plan (bounding box gets distorted in 3D views).

Found the problem.  VW2019 lets you extrude along a line, but VW2021 only extrudes along a NURBS curve.  So I added a couple of lines to convert the line to a NURBS curve before extruding.  This should also work in VW2019.

```PROCEDURE Ortho2Dto3D;

{*	Polls for plan, front, and side objects and produces simple 3D object
Developed by: Jesse Cogswell
Date: 4/11/2021
VW Version: 2019
Revisions:
*}

CONST

BUFF = 6;

VAR

frontA,frontB,sideA,sideB:POINT;
origin,trackLoc:POINT3D;
width,height,depth,centerZ:REAL;
plan,frontProfile,sideProfile,planObj,frontObj,sideObj:HANDLE;
result:INTEGER;

FUNCTION CheckObjCallback(h:HANDLE) : BOOLEAN;

{Provides Callback for selecting extrude objects}

VAR

objType:INTEGER;

BEGIN
objType:=GetTypeN(h);
IF((objType=3)|(objType=4)|(objType=5)|(objType=6)|(objType=13)|(objType=21)) THEN CheckObjCallback:=TRUE;
END;

FUNCTION CreatePlanObj(h:HANDLE; rBase,rDepth:REAL) : HANDLE;

{Creates 3D object representing plan geometry}

VAR

tempHd:HANDLE;

BEGIN
tempHd:=CreateDuplicateObject(h,NIL);
CreatePlanObj:=HExtrude(tempHd,rBase,rDepth);
END;

FUNCTION CreateFrontObj(h:HANDLE; pOrigin:POINT3D; pA,pB:POINT; rHeight,rDepth:REAL) : HANDLE;

{Accepts profile information and returns Handle to 3D geometry of front subtract object}

VAR

pathHd,rectHd,cutHd,solidHd,objHd:HANDLE;
objCtr:POINT3D;
subResult:INTEGER;

BEGIN
{Create Path}
MoveTo(pOrigin.x,pOrigin.y-(rHeight*0.5)-BUFF);
LineTo(pOrigin.x,pOrigin.y+(rHeight*0.5)+BUFF);
pathHd:=ConvertToNURBS(LNewObj,FALSE);
Move3DObj(pathHd,0,0,(rDepth*0.5));

{Create Profile}
Rect(pA.x-BUFF,pA.y+BUFF,pB.x+BUFF,pB.y-BUFF);
rectHd:=LNewObj;

{Extrude Cut Profiles}
solidHd:=ExtrudeAlongPath(pathHd,rectHd);
cutHd:=ExtrudeAlongPath(pathHd,h);
DelObject(rectHd);
DelObject(pathHd);

subResult:=SubtractSolid(solidHd,cutHd,objHd);

{Move 3D Geometry to Plan object center}
Get3DCntr(objHd,objCtr.x,objCtr.y,objCtr.z);
Move3DObj(objHd,0-objCtr.x+pOrigin.x,0,0-objCtr.z+(rDepth*0.5));

IF(subResult=0) THEN CreateFrontObj:=objHd;
END;

FUNCTION CreateSideObj(h:HANDLE; pOrigin:POINT3D; pA,pB:POINT; rWidth,rDepth:REAL) : HANDLE;

{Accepts profile information and returns Handle to 3D geometry of side subtract object}

VAR

pathHd,rectHd,cutHd,solidHd,objHd:HANDLE;
objCtr:POINT3D;
subResult:INTEGER;

BEGIN
{Create Path}
MoveTo(pOrigin.x+(rWidth*0.5)+BUFF,pOrigin.y);
LineTo(pOrigin.x-(rWidth*0.5)-BUFF,pOrigin.y);
pathHd:=ConvertToNURBS(LNewObj,FALSE);
Move3DObj(pathHd,0,0,(rDepth*0.5));

{Create Profile}
Rect(pA.x-BUFF,pA.y+BUFF,pB.x+BUFF,pB.y-BUFF);
rectHd:=LNewObj;

{Extrude Cut Profile}
solidHd:=ExtrudeAlongPath(pathHd,rectHd);
cutHd:=ExtrudeAlongPath(pathHd,h);
DelObject(rectHd);
DelObject(pathHd);

subResult:=SubtractSolid(solidHd,cutHd,objHd);

{Move 3D Geometry to Plan object center}
Get3DCntr(objHd,objCtr.x,objCtr.y,objCtr.z);
Move3DObj(objHd,0,0-objCtr.y+pOrigin.y,0-objCtr.z+(rDepth*0.5));

IF(subResult=0) THEN CreateSideObj:=objHd;
END;

BEGIN
{Poll Plan object}
SetTempToolHelpStr('Select Plan Object');
TrackObject(CheckObjCallback,plan,trackLoc.x,trackLoc.y,trackLoc.z);
HCenter(plan,origin.x,origin.y);
origin.z:=0;

{Poll Front object}
SetTempToolHelpStr('Select Front Object');
TrackObject(CheckObjCallback,frontProfile,trackLoc.x,trackLoc.y,trackLoc.z);

{Poll Side object}
SetTempToolHelpStr('Select Side Object');
TrackObject(CheckObjCallback,sideProfile,trackLoc.x,trackLoc.y,trackLoc.z);

{Get bounding boxes for Front and Side}
GetBBox(frontProfile,frontA.x,frontA.y,frontB.x,frontB.y);
GetBBox(sideProfile,sideA.x,sideA.y,sideB.x,sideB.y);

{Determine overall dimensions}
width:=frontB.x-frontA.x;
height:=sideB.x-sideA.x;
depth:=frontA.y-frontB.y;

{Create 3D Geometry}
planObj:=CreatePlanObj(plan,origin.z,depth);
frontObj:=CreateFrontObj(frontProfile,origin,frontA,frontB,height,depth);
sideObj:=CreateSideObj(sideProfile,origin,sideA,sideB,width,depth);

{Cut Objects}
result:=SubtractSolid(planObj,frontObj,planObj);
result:=SubtractSolid(planObj,sideObj,planObj);
END;

Run(Ortho2Dto3D);```

Thanks Jesse.

Im starting to see more possible applications for this beyond modelling up basic kitchen equipment. We often get 2d cad bldg drawings from which we need to create a 3D model. Chimneys, extract flues, roof plant are a few of the things We regularly have to model from solids.

I’m looking forward to having a play with tmrw!
cheers

Posted (edited)

Loving this script! So far seems to be working well. Haven't yet found the limit of complexity it can handle but will keep trying...

4 clicks to make these is pretty cool:

Edited by Boh

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

×   Pasted as rich text.   Restore formatting

Only 75 emoji are allowed.

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×