question

Mike Mayer avatar image
0 Likes"
Mike Mayer asked Mike Mayer commented

Green triangles in Parameters Value column cells?

What are the little green triangles in the upper left corner of each cell of the Value column in a standard Parameter table? The only thing I found in the documentation was in Global Tables:

"Tracked Variable cells will display with a small green triangle in the upper right corner." However, the green triangles I'm referring to are in the upper LEFT corner. Do these triangle indicate that this (or these) particular Parameter table value(s) are being references somewhere? In my model, they are all being referenced, so maybe that's it?

1696959970898.png

FlexSim 23.2.1
green triangles
1696959970898.png (19.1 KiB)
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

1 Answer

Matthew Gillespie avatar image
0 Likes"
Matthew Gillespie answered Mike Mayer commented

I don't know why the documentation says upper right instead of upper left, looks like a mistake to me.

There are a few different triangles that are drawn in table cells that indicate they're not a normal cell:

1696971107806.png

Green: Tracked Variables and other SimpleDataType objects

Red: A node with no data

Grey: A table of data


Parameters get the green triangle because they are a special SimpleDataType node that stores a bunch of different bits of data about the type of parameter, its constraints, and value.


1696971107806.png (1.7 KiB)
· 5
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Mike Mayer avatar image Mike Mayer commented ·
Thank you Matthew. Got it.


By the way, it's worth noting that the "Refresh Conv Names" you see in my Parameter table is in all my 3D models, which are typically conveyor-heavy. It is a toggle to enable or disable the calculation refresh of the location of the conveyor names on their surfaces (floating on top of, and centered, on the rollers or belt surface).


You may recall you helped me a few years ago by coming up with some clever text code that puts the conveyor's name on its own surface in blue 3D text. Your code does some slick vector math to calculate the text's position, centering, angle, elevation, inclination, etc. so that it always "sticks" to the surface of the conveyor (on top of rollers or belt), in the same place on the conveyor, no matter where the conveyor is placed or sized or angled.


I discovered once the conveyor name text is in-place, and the code is commented out, the text conveniently freezes there and does not move, which is nice (as long as I don't move the conveyor around). By toggling this code off with an "if" statement and the "Refresh Conv Names" flag (instead of commenting the code out manually) when no conveyors are being moved around, it greatly enhances the performance and refresh rate of the 3D model since it doesn't have to do all those heavy-ish calculations, on every conveyor, for every frame of refresh.


I've been using this conveyor naming "feature" in all of my models. As a suggestion box item, it would be great if FlexSim would consider making this a permanent feature, since currently conveyors do not show their names at all (2D nor 3D). Other objects (processors, queues, etc.) can show their names in black monotype font, and some basic stats in the floating 2D plane text, but I'd put forth that those objects too could benefit with the optional ability to "stick" their names to their surfaces, in true 3D just like your clever conveyor naming text code.


The existing floating black 2D object names are nice, however depending on 3D angle, zoom factor, and how close they are clustered, it's sometimes difficult to see what object the floating text is associated with, and, in many instance the text will "auto-disappear", likely done via an algorithm to reduce visual clutter.

Thanks again for this green triangle answer, as well as the conveyor text code from way back.

0 Likes 0 ·
Jason Lightfoot avatar image Jason Lightfoot ♦♦ Mike Mayer commented ·

I'm not sure why you think the performance is better than calculating for every frame since that's exactly what it's doing. (update: I was only looking at Matt's code - I see now)

However it seems that it should be possible to draw the names by referring to the entries in the conveyor system from a single draw object/event rather than have a container of visual tools, each processing their own draw event (which it does currently), and that might actually speed up the draw slightly. If I find time I might put this together and post it, such that you don't need reset code or a user command.

0 Likes 0 ·
Mike Mayer avatar image Mike Mayer Jason Lightfoot ♦♦ commented ·

Hi Jason,

Thanks for the reply.

Here's what the home-brewed 3D conveyor text looks like:

1697033901817.png

In FlexSim, that conveyor's actual name is "C716_718" which is a valid FlexSim object name (whereas "716-718" is not).

Indeed, that 3D text is from the Visual Tools library, the "Text" one at the top of the library section. What makes it work as a sticky piece of text is that the text itself is "connected" logically to the conveyor by way of a label on the text object called "conveyor". That label is a FlexSim pointer to the actual conveyor.

1697035200562.pngThe rest of the code inside the text executes over and over again (however often visual tools are refreshed, i.e., each frame).

Therefore if I have dozens or even hundreds of conveyors, each with their own executing FlexScript text-positioning code (see below), it can really slow things down because all instances of the code are executing all the time (well, as often as the text object refresh is happening). That's what drags things down. As such, I put the flag check at the top so that I can easily prevent all the needless calculation when the conveyors are in-place.

Here's the code in its entirety, for each 3D text object connected to a conveyor. I have modified it a bit over the years (to allow special characters, like dashes, and for the text item to self-name itself for clarity), but Matt Gillespie was the original author, as credited in the code. Clever stuff:

/**Use conveyor name text, geometry, position*/


// Only update this text when "Refresh Conv Names" in Parameters is set to 1.

// Note when set to 1, the conveyor name text will refresh at every video buffer

// frame, which results in noticeable degradation of graphical rendering performance.

// We only set "Refresh Conv Names" when a conveyor is moved, resized, or its

// name is changed. When "Refresh Conv Names" is set back to 0, the text will simply

// display in-place, with no redraw overhead.


if (Model.parameters["Refresh Conv Names"].value == 1) {

Object current = ownerobject(c); // This text object.

treenode textnode = param(1); // Treenode for this text string name.


// Original code by Matthew Gillespie, FlexSim Inc.

// M. Mayer modified it to be used locally for each text string.


// Get conveyor object named in "conveyor" label (a model pointer).

// This label must be specified manually for each text string attached

// to a particular conveyor (use the eyedropper to pick the conveyor).

Object conveyor = current.conveyor; // Conveyor this text should sit on.

// Rename this text object to be similar to actual name of conveyor.

// Note this is the NAME of the text object, not the text object string itself.

// This "self naming" feature makes it easier to identify the text object.

string text = conveyor.name; // Get string name of conveyor.

current.name = text + "_NameText"; // Rename text object.

// Am I a curved conveyor?

int isCurved = isclasstype(conveyor, "Conveyor::CurvedConveyor") ||

isclasstype(conveyor, "Conveyor::CurvedMassFlowConveyor");

// Object names only allow spaces and underscores. It is possible to optionally

// use other characters in the visible text name on the conveyor. For example,

// we might like a decimal point (instead of an underscore) in the text

// on the conveyor, by replacing the underscore with a period.

// The object's actual name remains unaltered. If so, uncomment this line:

text = text.replace("_", "-", 1); // This is optional.

text = text.replace("C", "", 1); // This is optional.

//text = text.replace("Conv ", "", 1); // This is optional.


// This code helps center the text on the conveyor surface.

// Get font size as defined in "Text Size" dialog in the Properties panel.

double fontsize = getvarnum(current, "textsize");

// Original code by Matt Gillespie:

current.size.x = getdrawtextmetric(text, 1, 1) * 0.9; //This is an approximation of the current width of the text


// M. Mayer - multipliers are by trial and error; they work for most cases.

//double currentSizeX = getdrawtextmetric(text, fontsize, 1) * 0.75; // For horizontal centering.

//double currentSizeY = getdrawtextmetric(text, fontsize, 2) * 0.8; // For vertical centering.

//current.size.x = currentSizeX;

//current.size.y = currentSizeY;

//double max_fitting_len = getdrawtextmetric(text, fontsize, 3, current.size.x);

//print(current.name, " Xsize=", current.size.x, " Ysize=", current.size.y, " MaxFitLen=", max_fitting_len);


Vec3 start = conveyor.getProperty("StartLocation").as(Vec3);

Vec3 end = conveyor.getProperty("EndLocation").as(Vec3);

Vec3 midPoint = (start + end) / 2.0;

Vec3 rescueMidPoint = midPoint; // Used to rescue text location if it goes into the weeds.


// For curved conveyors.

double radius = conveyor.getProperty("Radius");

Vec3 bisector;

if (isCurved) {

bisector = (midPoint - conveyor.location);

// Vec3 bisector = midPoint - conveyor.location;

midPoint = (bisector.normalized * radius + conveyor.location);

/* print ("START", start,

"| END", end,

"| midPoint", midPoint,

"| rescueMidPoint", rescueMidPoint,

"| conveyor loc", conveyor.location,

"| bisector", bisector);

*/

}

// Per FlexSim manual:

// "Takes the vector in from coordinate space, translates this vector

// onto to coordinate space, and returns the projected vector."

Vec3 projectedPos = midPoint.project(conveyor.up, current.up); // Math woojie-woojie.


// Text location, centering.

Vec3 center = Vec3(0.25, 0.7, 4); // Had to fiddle with these values.

current.setLocation(projectedPos, center); // Set position of text.

// Something in FlexSim occasionally sets location values to "-nan(ind)"

// therefore sending this conveyor name text location out into the weeds.

// The following code is an error trap workaround to set current.location.[xyz]

// values to 0 whenever an X, Y, or Z coordinate becomes "-nan(ind)".

// This effectively rescues the text location so you can at least see it.

string xloc_str = string.fromNum(current.location.x);

string yloc_str = string.fromNum(current.location.y);

string zloc_str = string.fromNum(current.location.z);

//print(current.name, "| rescueMidPoint", rescueMidPoint, "| current.size.x", current.size.x, "| fontsize", fontsize);

if (xloc_str == "-nan(ind)") {

print("XlocStr=", xloc_str);

current.location.x = rescueMidPoint.x;

}

if (yloc_str == "-nan(ind)") {

print("YlocStr=", yloc_str);

current.location.y = rescueMidPoint.y;

}

if (zloc_str == "-nan(ind)") {

print("ZlocStr=", zloc_str);

current.location.z = rescueMidPoint.z;

}

// Floats text just above conveyor surface so as not to hit tops of side skirts.

current.location.z += 0.05; // Tweak as needed.

Vec3 convVec = end - start;


double length = isCurved ? fabs(2 * Math.pi * radius * conveyor.getProperty("SweepAngle") / 360) : conveyor.getProperty("HorizontalLength");

double theAngle = Math.degrees(Math.atan2(convVec.z, length));

current.rotation.y = -theAngle; // Sets angle to match conveyor incline.

// Set orientation (rotation) of text.

current.rotation.z = isCurved ? Math.degrees(Math.atan2(convVec.y, convVec.x)) : conveyor.rotation.z;

//current.rotation.z = 0.0; // Set at fixed angle if desired (0-360).


// Set text of text object to be conveyor name. Includes any name.replace done above.

textnode.value = text;


return 1;


}

-------------------------

So as you can see, I put the flag at top to disable having to run through this code every single frame refresh of every text object in a model, which again could number in the hundreds of identical code blocks being executed many times per second of simulation run.

There's probably a more elegant, efficient way for me to have done this, but I have kind of settled into a reasonably easy method of copying these conveyors as needed (like I say, sometimes hundreds, each with their own 3D name), and once all are in place, I un-set the "Refresh Conv Names" for the whole model, and it runs fast again because it's not needlessly and constantly recalculating each text position.

If I need to add more conveyors, or move the current ones, I enable "Refresh Conv Names" again, then, disable it when I'm done fiddling around with conveyors.

Thanks,

Mike

0 Likes 0 ·
1697033901817.png (166.2 KiB)
1697035200562.png (5.2 KiB)
Show more comments