Welcome to the Onshape forum! Ask questions and join in the discussions about everything Onshape.
First time visiting? Here are some places to start:- Looking for a certain topic? Check out the categories filter or use Search (upper right).
- Need support? Ask a question to our Community Support category.
- Please submit support tickets for bugs but you can request improvements in the Product Feedback category.
- Be respectful, on topic and if you see a problem, Flag it.
If you would like to contact our Community Manager personally, feel free to send a private message or an email.
Centred Text in FeatureScript
alan_budden
Member Posts: 7 ✭✭
I'm trying to create a simple featurescript thing that will take a numeric value (from a variable, but that's incidental), convert it to a string with a prefix and write it as text centred on the origin of a face of a body. Most of that is quite straightforward, but I've been completely beaten by the (seemingly simple) task of centring the text. I can set the height easily enough (so could work out how far to move it vertically), but I have no idea what the width will be (as it depends on the actual text) so I don't know how far to move it horizontally.
This is what I've got so far that works:
This is what I've got so far that works:
FeatureScript 1431; import(path : "onshape/std/geometry.fs", version : "1431.0"); annotation { "Feature Type Name" : "RatioText" } export const ratioText = defineFeature(function(context is Context, id is Id, definition is map) precondition { // Number to include in the (e.g.) "1:9" text annotation { "Name" : "Ratio" } isInteger(definition.ratio, POSITIVE_COUNT_BOUNDS); // Height of the text (font size) annotation { "Name" : "Text Height" } isLength(definition.textHeight, { (millimeter) : [0.5, 6, 20] } as LengthBoundSpec); // How deep to extrude the text into the object annotation { "Name" : "Depth of Text" } isLength(definition.depth, { (millimeter) : [0.01, 0.5, 5] } as LengthBoundSpec); // On which face should the text be shown? annotation { "Name" : "Face for Text", "Filter" : EntityType.FACE, "MaxNumberOfPicks" : 1 } definition.faceForText is Query; } { // Create a sketch on the given plane var sketch1 = newSketch(context, id + "sketch1", { "sketchPlane" : definition.faceForText }); // Create the text, with the bottom-left corner at 0, 0 and of the correct height. // Ideally this would centre the text, but for now we'll put it there and then figure // out how to work out the text width and then move it by // (-textWidth/2.0, -definition.textHeight/2.0) afterwards var text = skText(sketch1, "textId", { "text" : "1:" ~ toString(definition.ratio), "fontName" : "NoboSans-Regular.ttf", "firstCorner" : vector(0, 0) * millimeter, "secondCorner" : vector(100 * millimeter, definition.textHeight) }); // Now need to figure out how to move text such that it's centred in X & Y on 0, 0 // not set with the bottom left on 0, 0. First problem is I have no idea what the // width of the text is... skSolve(sketch1); });
I've spent ages playing around with evBox3D and suchlike but I either get lots of errors (if trying to use it on the text object) or the results don't seem to make any sense (if trying to use it on the resulting sketch).
Can anyone suggest what I'm doing wrong? This feels like it should be a fairly simple thing to do.
Can anyone suggest what I'm doing wrong? This feels like it should be a fairly simple thing to do.
Tagged:
0
Comments
Things to keep in mind:
1) Sketch geometry is not created until skSolve() is called, so you'll need to do the evBox3d(... qCreatedBy(id + "sketch1", EntityType.BODY)) after skSolve()
2) evBox3d will also need a coordinate system input to make sure it's measuring the text bounds along the right axes. To pull this data out of your current code I'd recommend some changes small changes:
3) That cSys then becomes useful – you'll need it as an input to your evBox3d so you can figure out the extents of your text in a particular direction
4) The final opTransform will also need to depend on your cSys. i.e. opTransform(... "transform" : transform( -cSys.xAxis * (bounds[0].maxCorner - bounds[0].minCorner) / 2)) should be the right direction and magnitude of a x-centering transform
Finally, your current feature decides the x-axis of the sketch (i.e. the rotation) arbitrarily in newSketchOnPlane (and my changes decide it arbitrarily in evPlane()). It could easily be 90º off from what the user expects. If this is an issue you can give more control by adding an x-axis input, or (my preference), changing the input query to BodyType.MATE_CONNECTOR to let the user input the cSys directly. This way the user can click on the selected mate connector and change the rotation (or anything else) if they desire. With that adjustment, evPlane would need to be replaced by evMateConnector (which gives a cSys), and cSys = cSys(sketchPlane) would need to be replaced by sketchPlane = plane(cSys).
Let us know if you have more questions!
- For practice
- To allow me to use the value of a variable in the text (which doesn't seem to be possible with the built-in text tools).
With your help, it's very nearly working now. The only thing I can't figure out is why the extrude isn't working. I've used opExtrude and extrude before with no real issues, but I'm drawing a blank here. There are no error messages - it just says "Regeneration complete", but the sketch is still visible and hasn't been "cut" into the object. Can you see what I'm missing?The code seems reasonable at first glance. Is it possible the extrude remove is simply pointing the wrong way? That would be fixed with "oppositeDirection" : true in the extrude. Note that "direction" is not a real parameter of extrude, so it's being ignored. It is a parameter of opExtrude, the more flexible underlying operation that extrude is based on, but that's not the function you're calling.
If that's not it, sharing a link to a public document would make things easiest to debug.
Oh dear, that's embarrassing! Changing the direction sorted it out. Thank you!
Final version in case other people come hunting for centred text and want to see it for some reason...
I find that generally using `extrude` rather than `opExtrude` is also a good way to go to add sheet metal compatibility, since `opBoolean` can't cut sheet metal, and you also get the cutting in `extrude` easier, like you have done.
IR for AS/NZS 1100