Author Topic: Creating 3D Text and Wrap it Around a Pipe (Cylinder)  (Read 3040 times)

0 Members and 1 Guest are viewing this topic.

flyte

  • Newt
  • Posts: 26
Creating 3D Text and Wrap it Around a Pipe (Cylinder)
« on: April 15, 2020, 01:38:37 AM »
I am looking to create a routine that will create 3D Text and then place this on the side of a Plant3D pipe. For creating text geometry, I stumbled upon the excellent TxtExp Alternative by SEANT https://www.theswamp.org/index.php?topic=31435.0. While this approach creates the text geometry just fine, I am wondering:

a) How would I make the generated geometry solid and extrude it to make it 3D?
b) Given that 3D geometry, how could I "wrap" it around a curved shape / the side of a cylinder, (in my case, a Plant3D pipe).

Any help would be greatly appreciated.

(note, I was about to post this question in the aforementioned thread above, but the site suggested that I create a new post because that one is quite old and inactive. I can move it / re-post there if necessary).
« Last Edit: April 15, 2020, 02:03:54 AM by flyte »

MickD

  • Gator
  • Posts: 3435
  • (x-in)->[process]->(y-out)
Re: Creating 3D Text and Wrap it Around a Pipe (Cylinder)
« Reply #1 on: April 15, 2020, 01:56:29 AM »
I'm not exactly sure what SEANT's app produces but it looks like splines so you should be able to create a region from each character then extrude them. To get them to wrap around the pipe, make sure the solid totally intersects with the pipe and extrude another 'cylinder' that is just undersized to the pipe (the depth) you want the lettering on and subtract it from the letters that should give you a solid with a flat face and a curved face in the letters' normal directions.
Then subtract this result from the pipe to leave the imprint.

Hope that made sense :)

Just be careful with this as if you do a lot of this in a drawing it can bog it down (so many new faces and edges to deal with!), cheers.
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: “To attain knowledge, add things
every day; to obtain wisdom, remove things every day.”

flyte

  • Newt
  • Posts: 26
Re: Creating 3D Text and Wrap it Around a Pipe (Cylinder)
« Reply #2 on: April 19, 2020, 08:16:59 PM »
Thanks so much for the reply MickD!

So I managed to leverage that routine by SEANT to add text as a region and then extrude it. I currently have the extruded text appear at the Pipe's coordinates by getting it's Position X/Y/Z properties. So it's a start.

But I don't quite follow the rest of what you wrote. I am not sure how to properly place and wrap that around the pipe. Do you happen to have an example?


MickD

  • Gator
  • Posts: 3435
  • (x-in)->[process]->(y-out)
Re: Creating 3D Text and Wrap it Around a Pipe (Cylinder)
« Reply #3 on: April 19, 2020, 11:38:17 PM »
I don't have any code to hand and you can do this manually in the editor but basically, create the text 3D solid and position it along the centre line of the pipe making sure that the text solid has the outside face outside of the pipe. That is, the text solid height needs to be bigger than the pipe radius.

Make a copy of the pipe solid (probably better to create a cylinder with no wall like a pipe) and use that solid to cut the curve into the text solid using Subtract.

Move the text solid a fraction towards the centre of the pipe (depth of text 'etching' cut) then use the text solid and Subtract it from the pipe (make a copy if needed before doing the subtraction as you will lose it).

Like I said, depending on the height of the text compared to the pipe size, the text will be deformed a bit due to the cut and wrap but this can be tweaked by 'squashing' the text before creating the text solid or by working out how to scale the height more correctly with math.

here's some pics of the steps, the yellow box represents your text solid.
1 = create the pipe and text solids
2 = create cylinder just under the diameter of the pipe along the pipe centre line and use it to subtract from text solid
3 = subtract text solid leaves etching into pipe wall
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: “To attain knowledge, add things
every day; to obtain wisdom, remove things every day.”

flyte

  • Newt
  • Posts: 26
Re: Creating 3D Text and Wrap it Around a Pipe (Cylinder)
« Reply #4 on: April 27, 2020, 06:42:56 PM »
Thanks once again MickD - your guidance got me very close to what I need.

I have successfully been able to create a cylinder and subtract that from my extruded text. But now my problem is aligning the text to the orientation of the pipe. right now my text blindly gets written on the XY Plane, but obviously I need the text to be in the same orientation as the (Plant3D) pipe.

How would I go about finding that? I do have the start point of the pipe, and I can get the "center of gravity" point of the pipe.. would that allow me to create a vector and somehow translate my text solid such that it would be on top of the pipe properly?

Also how can I have my text solid "straddle" the center point of the pipe, so the text is more horizontally center justified, instead of the text starting at the center point? If i could somehow set the solid's center point to be the same as the pipe's, I think that would be great.

Here is a sample of what I have:

MickD

  • Gator
  • Posts: 3435
  • (x-in)->[process]->(y-out)
Re: Creating 3D Text and Wrap it Around a Pipe (Cylinder)
« Reply #5 on: April 27, 2020, 07:31:03 PM »
Getting there! :)

It's basically an exercise in vector and matrix math from here on to move things into place.
You need to either transform and/or translate the text to the pipe or the pipe to the text. If you move the pipe you need to 'invert' it back.
Have a look into the Geometry.Matrix3d class and its methods. There are plenty of examples here as well.

I see in the Plant3d doc's that the pipe object has an ECS (entity coordinate system) which you can use to move it 'to world' and back, you then just need to adjust your text into position to suit.
You can use it to move the text to the pipe as well, just set the text up in WCS as if it was aligned to the pipe then transform it with the pipe ECS ;)

hth
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: “To attain knowledge, add things
every day; to obtain wisdom, remove things every day.”

MP

  • Seagull
  • Posts: 17731
  • Have thousands of dwgs to process? Contact me.
Re: Creating 3D Text and Wrap it Around a Pipe (Cylinder)
« Reply #6 on: April 27, 2020, 08:05:45 PM »
* cool thread to follow *
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.com • http://cadanalyst.slack.com • http://linkedin.com/in/cadanalyst

MickD

  • Gator
  • Posts: 3435
  • (x-in)->[process]->(y-out)
Re: Creating 3D Text and Wrap it Around a Pipe (Cylinder)
« Reply #7 on: April 28, 2020, 03:22:15 AM »
* cool thread to follow *

It's been a while but you don't forget it :)


Here's some code with some added comments I use to rotate and move an object from its own ucs (ECS in your case) to world to get its length, you could get the ECS from the pipe and use PlaneToWorld on the text object once you have it arranged (as if it were along the pipe say). You should be able to get some ideas from this.

Code - C#: [Select]
  1. Matrix3d mat = new Matrix3d();
  2. Plane plane = new Plane(new Point3d(0,0,0), mySolidVector); // a vector pointing away/perp to the pipe centre line vector
  3. mat = Matrix3d.WorldToPlane(plane); // create the matrix using a simple plane created by a point and a vector
  4. pipe.TransformBy(mat); // transform it
  5. double length = mySolid.GeometricExtents.MaxPoint.Z - mySolid.GeometricExtents.MinPoint.Z; // get the length
  6. mySolid.TransformBy(mat.Inverse()); //transform it back
  7. return length;
  8.  

You could use PlaneToWorld using the pipe ECS to move the text to the pipe. Something to experiment with anyway.
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: “To attain knowledge, add things
every day; to obtain wisdom, remove things every day.”

wizman

  • Bull Frog
  • Posts: 270
Re: Creating 3D Text and Wrap it Around a Pipe (Cylinder)
« Reply #8 on: May 07, 2020, 02:08:34 AM »
Gents, To add to the manual method - imprint > explode > thicken

flyte

  • Newt
  • Posts: 26
Re: Creating 3D Text and Wrap it Around a Pipe (Cylinder)
« Reply #9 on: May 07, 2020, 11:48:26 PM »
Thanks everyone for the help and guidance thus far. I have been a bit frustrated with this and had to step away for a bit, :tickedoff: but I've got enough motivation now to drive this to completion,(with assistance of course). I make an honest attempt to follow the guidance I am given (see rest of thread), but I just can't get how to translate/rotate/orientate my text solid and cylinder (used to subtract the text) to that of the original pipe. My dilemma is that I am not well versed in the matrix3d / vector math needed to understand how to nail the positioning down. I am well comfortable in software engineering - not so much in CAD'n.

Having said that, I tried taking MickD's guidance, and also researched a number of other approaches to get some hints:
https://stackoverflow.com/questions/31952750/insert-a-block-at-an-angle-in-autocad-c
https://forums.autodesk.com/t5/net/align-entity-3d/m-p/9398486#M65184
https://forums.autodesk.com/t5/net/rotating-a-block-into-a-new-orientation-in-3d/m-p/3877703#M34708

But I am not sure how to apply those strategies with what I have. I was delighted to see @gile's response in https://forums.autodesk.com/t5/net/align-entity-3d/m-p/9398486#M65184 but I wasn't sure how to to define / select the
Quote
"3 (non colinear) source points and 3 (non colinear) destination points to be able to define the source plane and destination plane."

MickD - I tried to experiment with what you provided, but no joy. As per my previous screenshots, I can get the text/cylinder positioned OK (center point of pipe), but still not sure how the plane transformation using the different coordinate systems align my solids.

wizman - I'm intrigued by what you suggested as a manual approach. Is there a way to do this programatically? When I explode the pipe, reduces the pipe down to its primitives, but I want to retain the pipe.. not sure how to proceed manually, or implement via the API...

Again, thanks for all of the assistance thus far.. I feel I am missing some fundamentals here.. but this is proving to be a challenge!

wizman

  • Bull Frog
  • Posts: 270
Re: Creating 3D Text and Wrap it Around a Pipe (Cylinder)
« Reply #10 on: May 08, 2020, 01:06:31 AM »
Quote
wizman - I'm intrigued by what you suggested as a manual approach. Is there a way to do this programatically? When I explode the pipe, reduces the pipe down to its primitives, but I want to retain the pipe.. not sure how to proceed manually, or implement via the API...

Hello Flyte, i'm unable to help with the programming part.  I'm sure MickD can guide you all the way into this.  You are correct, the manual way i did does not retain the pipes.  Imprinting and exploding is just a quick way to have the text as a surface which can be thickened.  But then the imprinted text is just a crude way of doing it and i assume you would want to maintain the text proportions exactly as it drape along the curved solid.  All the best!

MickD

  • Gator
  • Posts: 3435
  • (x-in)->[process]->(y-out)
Re: Creating 3D Text and Wrap it Around a Pipe (Cylinder)
« Reply #11 on: May 08, 2020, 05:44:14 PM »
Hi Wizman, instead of doing imprint and extrude you can do double cut on text then union text to pipe :)

Flyte, what code do you have so far? I'd be happy to take a look if you can provide it and a sample drawing with the text and pipe set up in a typical scenario.
cheers.
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: “To attain knowledge, add things
every day; to obtain wisdom, remove things every day.”

flyte

  • Newt
  • Posts: 26
Re: Creating 3D Text and Wrap it Around a Pipe (Cylinder)
« Reply #12 on: May 08, 2020, 08:28:35 PM »
Thanks MickD.

So.. for creating the text as an entity, (i.e.: not text/mtext), i heavily rely on SEANT's solution described here (and in the OP): https://www.theswamp.org/index.php?topic=31435.0 and it works perfectly, (I may have grabbed a newer version of that code somewhere else.. but the premise is the same.). So I have the text... and I have the pipe.. which leads me to this code that accepts the block reference entity which is the text converted into a Region), where I want to:

1. Extrude the text region
2. Create the cylinder to be used to subtract from the text region to get the "wrap around" effect
3. Properly orientate the cylinder and text region (help needed here!)

Here is the code:

Code: [Select]
// FYI - the following are as held as member variables
//        List<KeyValuePair<string, string>> pipeProperties;
//        private Point3d position;
//        private Point3d centerOfPipe;
//        private double extrudeHeight;
//        private double outsideDiameter;
//        private double wallThickness;
//        private double pipeLength;
//        private Vector3d pipeVector;

private void CreateEnt(Entity ent)
{
// Scale the text height...
Extents3d geometricExtents = ent.GeometricExtents;
Point3d point3d = new Point3d();
double mHeight = this.m_height;
Vector3d vectorTo = point3d.GetVectorTo(geometricExtents.MaxPoint);
double y = mHeight / vectorTo.Y;
ent.TransformBy(Matrix3d.Scaling(y, point3d));

using (Transaction tr = this.m_db.TransactionManager.StartTransaction())
{
try
{
BlockTableRecord btr = tr.GetObject(this.m_db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
ent.SetDatabaseDefaults();

// Extrude this region just beyond the thickness of the pipe...
var pSolid = new Solid3d { RecordHistory = true };
pSolid.Extrude(ent as Region, extrudeHeight, 0.0);

// Move this region to the center point of the pipe, and move it down so it is vertically center justified...
var centerJustPoint = new Point3d(centerOfPipe.X, centerOfPipe.Y, centerOfPipe.Z - (extrudeHeight / 4.0));
pSolid.TransformBy(Matrix3d.Displacement(centerJustPoint - Point3d.Origin));

// Now the text region is by default oriented so that the text is laying down flat. Hard code transform to be "vertical" so the
// text region is up.
// ** how do I figure out the proper orientation of the text region to match the orientation of the pipe...??
Matrix3d matrix = Matrix3d.Rotation(Math.PI / 2, Vector3d.XAxis, centerJustPoint);
pSolid.TransformBy(matrix);


// Add this solid to the model...
btr.AppendEntity(pSolid);
tr.AddNewlyCreatedDBObject(pSolid, true);                   

// Create the cylinder that will be subtracted from the text regoin, and move it to the center point of the pipe..
var cyl = new Solid3d { RecordHistory = true };
var radius = (outsideDiameter / 2.0);
cyl.CreateFrustum(pipeLength, radius, radius, radius);
cyl.TransformBy(Matrix3d.Displacement(centerOfPipe - Point3d.Origin));

// Now this cylinder and text region is simply using the default orientation. Manually hard code to orientate it, just like above,
// so that it matches the text orientation..
// ** obviouslly this is wrong and won't handle, for example, vertical pipes.. how do I align this and the text to the orientation
//    of the pipe.

Matrix3d matrix2 = Matrix3d.Rotation(Math.PI / 2, Vector3d.YAxis, centerOfPipe);
cyl.TransformBy(matrix2);

// Lots of test code here to try to orientate / align the cylinder and text to the pipe... see previous post that describes the approaches
                        // that I attempted, but couldn't figure out...

btr.AppendEntity(cyl);
tr.AddNewlyCreatedDBObject(cyl, true);

// Subtract the cylinder from the text region..
pSolid.BooleanOperation(BooleanOperationType.BoolSubtract, cyl);
}

catch
{
this.m_isValid = false;
}

finally
{
tr.Commit();
}
}
}

Now this code got me as far as my previous screenshots show.. so if the pipe is completely horizontal.. everything looks good and it got me as far as implementing the strategy that you outlined for me in your initial reply. So I feel like the heavy lifting is done.. it is just this alignment issue that is blocking me..

I have attached a test DWG showing the pipes, (it is a Plant3D dwg...hopefully you are able to open it.. )

MickD

  • Gator
  • Posts: 3435
  • (x-in)->[process]->(y-out)
Re: Creating 3D Text and Wrap it Around a Pipe (Cylinder)
« Reply #13 on: May 09, 2020, 07:08:28 PM »
Quote
// ** how do I figure out the proper orientation of the text region to match the orientation of the pipe...??

that's where you use WorldToPlane, you are changing the texts's and new 'cutting' pipe's world coordinates to those of the plane by multiplying the WCS vectors by the pipe's ECS vectors which will transform and rotate the text in one go.
Create a plane from your pipe in space from say its start point, its ECS x and y vectors and use that in the transformation. The ECS is a Matrix3d so you need to access its CoordinateSystem3d properties for X and Y.

Code - C#: [Select]
  1. Plane plane = new Plane(pipe.StartPoint /*or pipeEcs.CoordinateSystem3d.Origin*/, pipeEcs.CoordinateSystem3d.Xaxis, pipeEcs.CoordinateSystem3d.Yaxis);
  2. mat = Matrix3d.WorldToPlane(plane); // set the matrix up to use for text and cutting pipe to move (TransformBy) them 'to' the pipe ECS
  3.  

You could also play with PostMultiplyBy or PreMultiplyBy where you just use the ECS directly. It depends on if the ECS origin aligns with the pipe start point (which it probably does).
Code - C#: [Select]
  1. textCuttingSolid.PostMultiplyBy(pipe.getEcs());
  2. textSolid.PostMultiplyBy(pipe.getEcs());
  3. // do subtraction of cutting solid from text and then subtraction of cut text on existing pipe solid...
  4.  
You're almost there :)

p.s.
I couldn't open the drawing but thinking on it a bit more just use PostMultiplyBy example as it saves a lot of setup. Standard Solid3d's do not have a meaningful ECS like a 'pipe' does so I had to do more work by creating a plane from my own custom ECS.
All you need now is a simple method that takes the plant3d pipe to be etched and some text, create the cutting text and etch the pipe using the pipe's ECS to line the text to the pipe.
« Last Edit: May 09, 2020, 07:36:33 PM by MickD »
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: “To attain knowledge, add things
every day; to obtain wisdom, remove things every day.”

flyte

  • Newt
  • Posts: 26
Re: Creating 3D Text and Wrap it Around a Pipe (Cylinder)
« Reply #14 on: May 11, 2020, 12:33:02 PM »
Thanks again MickD.

So using the Pipe's ECS still doesn't seem to position, or orientate, the text solid or the cylinder. Given this code:

Code: [Select]
using (Transaction tr = this.m_db.TransactionManager.StartTransaction())
{
    try
    {
        BlockTableRecord btr = tr.GetObject(this.m_db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
        ent.SetDatabaseDefaults();

        // Extrude this region just beyond the thickness of the pipe...
        var textSolid = new Solid3d { RecordHistory = true };
        textSolid.Extrude(ent as Region, extrudeHeight, 0.0);

        // Using ECS
        Plane plane = new Plane(pipeEcs.CoordinateSystem3d.Origin, pipeEcs.CoordinateSystem3d.Xaxis, pipeEcs.CoordinateSystem3d.Yaxis);
        Matrix3d matrix = Matrix3d.WorldToPlane(plane);
        textSolid.TransformBy(matrix);

        // Add this solid to the model...
        btr.AppendEntity(textSolid);
        tr.AddNewlyCreatedDBObject(textSolid, true);

        // Create the cylinder that will be subtracted from the text regoin, and move it to the center point of the pipe..
        var cyl = new Solid3d { RecordHistory = true };
        var radius = (outsideDiameter / 2.0);
        cyl.CreateFrustum(pipeLength, radius, radius, radius);
        cyl.TransformBy(matrix);
     
        btr.AppendEntity(cyl);
        tr.AddNewlyCreatedDBObject(cyl, true);       
    }

    catch
    {
        this.m_isValid = false;
    }

    finally
    {
        tr.Commit();
    }
}

See screenshot - the pipe I clicked on is marked with the red arrow, and I put a box around where the text and cylinder ended up being positioned and oriented. Not sure what's going on here? Also note that I also tried creating the plane using the pipe's StartPoint as the first parameter as in your example, but that positioned the text solid and cylinder in a slightly different position as in the screenshot..

Is there something I missed when using this approach?

« Last Edit: May 11, 2020, 05:32:28 PM by flyte »