A Simple Discrete-Event Simulation: Part 81

This week and possibly much of next I’m concentrating on updating the fixed content of my website, which means I’m only going to be doing small increments on this project. I’ve decided that the next item to work on is panning a zooming because of something I want to demonstrate in the fixed content. To that end I installed the simplest possible commands to pan the 2D display around within certain limits. Mostly I wanted to verify that I’d added the base x- and y-origins for the viewable area of the screen were added to all of the drawing commands properly.

Here’s the relevant code from the DisplayElement object. It shows how the drawing locations now include the offsets I’ve defined (globalBaseX and globalBaseY):

Here’s the code that does the basic pan. It picks up keystrokes and changes the base x- and y-axis panning origins within limits. When the code is running in its own window there are times when higher priority events consume the messages for the up and down arrow keys, namely when the entire page wants to scroll. When I embed this in an iframe on the website it doesn’t seem to have this problem. However, when it’s in the iframe (like you see it here) you need to click on the canvas to give it the focus. The arrow keys move the display and the home key restore the origin point to its original value. There’s no provision for panning on a mobile device, either, but at least I know the offsets are in correctly.

You may also notice that these calls update the graphics when the simulation is not running, but don’t need to do so when the simulation is running, though the panning action will be much more slow and choppy.

Posted in Simulation | Tagged , | Leave a comment

Converting the Entire Site from HTTP to HTTPS

…was painful.

Instructions for making the change effective throughout WordPress were easy enough to find and follow, but updating references in 250-ish posts by hand took some time. I had two hassles. The first was my own doing in that I put all of the local images in a named directory rather than using the WordPress way of referring to local content. This means I know where everything is and can move the WordPress installation anywhere I want without having to worry about the directory tree that it would build. The downside is that I have to include a fully qualified path to each piece of content. Oh well. The other hassle is the general issue that linking to unsecure content on a secure page makes the browser report unsecure content (in most browsers this means showing a warning symbol over the lock symbol at the left end of the browser’s address bar. There are some ugly workarounds for this involving various browser- and server-side scripts but I found it easier to find replacement images in ten or so cases that were hosted on secure pages.

Changing over the non-WordPress pages was pretty straightforward. I’m in the middle of redoing a lot of those pages anyway.

I was moved to do this because the slides.com tool I used to build yesterday’s presentation doesn’t much like serving insecure content, either. It made the editing process harder because I couldn’t easily see what I was working with and when I gave the presentation I had to do so with my browser’s security purposefully turned off. It’s not a big deal in the short run but over time it’ll be easier to just do it “right.” I updated the slides to reflect the new information and, as I think about it, I should also check the references to the site I’ve placed on LinkedIn and elsewhere. I also updated the settings in the FTP access tool I’ve been using.

Posted in Software | Tagged , , | Leave a comment

Presentation for CharmCityJS Meetup Feb 1, 2017

Link.

Posted in Software | Tagged , , | Leave a comment

A Simple Discrete-Event Simulation: Part 80

I was working on other things today so the only thing I added to this project was the grid. It’s at a y-elevation of zero. More interestingly, it’s generation is automated, with the relevant code being shown below. Because floating-point numbers can be notoriously touchy after numerous operations I added in the smidge factor to ensure that end lines are always drawn and that the center lines can be found reliably. The center lines can be drawn in a different color if the number of divisions across the total width or length of the grid is even, meaning there will be an odd number of lines.

The grid fits to the layout so well because I make use of the fact that I had the boundary locations available since they’d been calculated to identify the center about which the camera flies and at which it looks. I extended the grid exactly one block in each direction. I wanted the blocks to be (roughly) square so I created more of them in the z-direction than in the x-direction. Last but not least the function can and should be parameterized instead of hard-coded like I’ve done here, but that’s a trivial matter.

I put the following scene together as part of preparations for a presentation. The code for generating the grid is a bit more primitive but this exercise drove me to learn how to modify the endpoints of existing lines as well as their color. In define3DLine we specify the endpoints as a pair of vector objects pushed into an array called vertices. If we want to modify those endpoints we simply dereference them in the other direction. The trick in this case is knowing you need to set the flag which lets the framework know the change needs to be processed internally. Some operation are straightforward — you just change and value and it takes effect (the line’s color works this way as we’ve already seen). In other cases you have to set the flag because the framework has to do something extra in response to the changes that wouldn’t happen naturally.

Always be on the lookout for such gotchas if the first thing you try doesn’t work the way you think it should. As it happens I found the verticesNeedUpdate property when I was using the Firefox debugger to inspect the line I was trying to change. A quick search in the documentation told me that my hunch was correct. You know what they say: RTFM.

You can see the results here, in the lines showing where the camera is located as it orbits the scene. The camera does the same thing in the simulation code demos up to this point as well.

Posted in Simulation | Tagged , , , | Leave a comment

A Simple Discrete-Event Simulation: Part 79

The direct link to the latest version is here. Open this in a new window and try resizing it.

While preparing to give a presentation at the CharmCityJS Meetup this Wednesday I spent quite a bit of time investigating the setup of the 3D display, particularly in full screen mode. The first thing I had to do was make the full screen 3D display work again, since I inadvertently broke it when I updated the base HTML last week. Once that was done I set about making it work the way I want even as the user resizes the browser window.

Here’s the base HTML. In full screen 3D mode the normal components are all set to not display and a renderer canvas element is assigned to fill the entire window. Therefore a single wrapper is used to enclose all of the other elements.

Here’s the code that sets up the 3D display. I originally controlled this with a single variable, virtual3DViewOnly, but realized that making the display 3D and making it stereo/VR could easily be controlled with a separate setting. The stereoVR setting is only used in three places, as it turns out.

If fullScreen3D is set to true the script hides the standard components and attaches a dedicated, full-screen canvas to the window as described. If it is set to false is creates a renderer canvas of a fixed size and attaches it to the target div element. If the stereoVR flag is set then the renderer’s output is piped through an additional transform to produce the stereo display. There are a few other mechanics in place to support changing the size of the window interactively. These are mostly not necessary when not in full screen 3D mode.

The other part of the setup involves adding a camera, which defines the viewing frustum. This is the transform that maps the internal 3D representation of objects to the 2D screen. It requires a field of view angle, an aspect ratio, and settings to clip near and far distances from the viewing point. There’s the relevant Three.js documentation. When the size of the window changes the aspect ratio and field of view angle have to change accordingly.

Here’s how changes to the window size are detected and how the camera parameters are updated. I included links to the pages where I found these methods.

Setting the aspect ratio as the window size changes is straightforward but recalculating the field of view angle was trickier, and that’s where the calcFovBaseX and calcFovAngle functions come in. The field of view angle is given an initial value (of 75 degrees) in the fovBase variable. This angle is applicable to the initial internal height of the window, in pixels. If the height of the window changes we have to back calculate the new field of view angle that keeps the display the same relative size. (Note that you might not want this behavior, but if you do you have to take steps like those I describe here.)

In order to keep the displayed scene a constant size we have to keep the viewing location the same distance from the scene. Consider the following figure:

We want to keep the distance (x) from the viewer to the scene constant as we change the height of the window (y), so we have to find the new angle (a2) to go along with a new window height (y2). In order to do that we need to find the constant distance (x) to use. Remembering that the tangent of an angle is the ratio of the height of a right triangle divided by the width of that triangle we know that:

tan( a1 / 2) = (0.5y1) / x

which means that

x = 0.5y1 / tan( a1 / 2).

We know the original values for y, and a1 so we can calculate x using the calcFovBaseX function. Given a new y2 when the screen size changes, and using our constant x, we can find the new fov angle like this:

a2 = 2 atan( 0.5y2 / x)

This calculation is done in the calcFovAngle function. Remember that we have to convert from degrees to radians and back again to do these calculations properly. A good check to make sure we get both functions right is to generate a base x value for a given field of view angle and window height, then feed that window height back into the second function to be sure it returns that same angle.

Once I got all this straightened out it worked like a charm, and it worked if we’re viewing one 3D image or doing so in stereo. Interestingly, the apparent size of the scene is determined based on the initial viewing frustum and the initial window size. The scene will appear to be different sizes based on the initial size of the window, and will not change even if the size of the window is changed. However, a scene initialized in a larger starting window will appear larger than one initialized in a smaller starting window. The apparent size of the scene is also a function of where the camera is located in the global 3D space, and we’ll experiment with that some tomorrow.

Until then, don’t let anyone tell you that trigonometry never comes up in your everyday life. đŸ™‚

Last but not least you may notice that the shape for the Combined component, (C21) is itself rotating about a y-axis drawn through its center. The locations of the components are all defined relative to their center points (on the x-z plane). If doing 3D transforms natively the procedure is to translate the object so the point you want to rotate around is at the origin of the global 3D space, perform the rotation (or scale or skew) operation, and then translate the object back to where you want it. The makers of Three.js know that’s kind of painful, so they hide all those mechanics from the user and allow the code to just say:

In this example this.component is a reference to one of the shape objects we created and rotation is the total angle of rotation from the original orientation. The y gives access to rotation about the y-axis individually.

Posted in Simulation | Tagged , , | Leave a comment

A Simple Discrete-Event Simulation: Part 78

Today I did a bunch of work behind the scenes, starting with automatically determining the exclusivity of components based on their defined capacities, where appropriate. Queue, Process, Bag, and Combined components are exclusive if their governing capacities are finite and not exclusive if they are infinite. All other component types are always non-exclusive. It could be argued that Process components should never be defined to have infinite capacities when modeling any real system, since the whole purpose is to examine its finite constraints. The same might also be true of bag components. I should probably have the system throw a warning if a user specifies an infinite capacity for a Process or Bag component. Components that can operationally handle an infinite capacity are as a practical matter limited in two ways. One is by the amount of memory that can be allocated to store entities in internal queues and the other is by the number of entities that can be individually displayed.

Next I streamlined a bunch of the initializers for the graphic display components by defining a lot of default parameter values and embedding an assignment into a constructor. This was especially germane to the graphic characteristics of Path components, whose endpoints are usually determined automatically by the non-Path components they are connected to. I also removed references to the internal DisplayGroup mechanisms in the initialization code, but the mechanics remain in place within the component objects.

Finally, in preparation for doing something a little cleaner with the specification of internal entity locations, I redefined the internal arrays that store those locations to be multidimensional. The code is otherwise unchanged, and all locations are saved in master array zero. The goal is to be able to specify locations for different internal entity queues (e.g., parking and exit queues in Bag components, waiting and process queues in Combined components) in their own arrays rather than having to figure out which of the latter locations apply to entities in the second queue. This should also allow for a process to represent multiple, parallel operations, possibly each with their own sub-queues, but that is an idea for later.

The only visible change in the model is that I lowered the queue capacity in the Combined component down to two so I could test to ensure it handles exclusivity properly, which it does. You may have to reset and rerun a couple of times to see enough entities back up in that component, but it happens.

Posted in Simulation | Tagged | Leave a comment

A Simple Discrete-Event Simulation: Part 77

Today I created a combined Queue-Process component I called a Combined component. You can see it in today’s version of the model as component 50, labeled C21, having replaced queue 21 and process 21. I suspect that this will become the default Process component once I have it cleaned up and a bit more bulletproof. I started with a Queue component and then added features until I had the behaviors I wanted. The main change is that the hand-off between the queue and process parts is handled internally and instantaneously. The mechanism for pulling from the previous component had to be adjust as well, as did the code to draw the 2D and 3D graphic displays.

Here’s the code for the new component:

I see numerous opportunities for compressing and streamlining things as I continue to work with this code. One of the insights is that any Queue or Process with a finite capacity is effectively exclusive, so I can probably automate the setting of that value for each component. That will be one of the things I work on tomorrow. I’m also thinking of modifying the way the entities are drawn in the various components. The current code works but is a bit twisty and opaque, so it could stand some clarification and regularizing.

I also fixed the 3D display mechanisms for the entities in the Bag and Combined components.

Posted in Simulation | Tagged | Leave a comment

A Simple Discrete-Event Simulation: Part 76

Today I added a series of Queue and Process components into the pathway traversed by the sub-entities leaving and returning to the Bag component. I found one change I had to make, which was adding the ability of the ReturnFromSubJourney component to return its parent component’s componentGroup value. This was necessary so entities could test to see whether they were leaving the component groups represented by the two new Queue-Process pairs.

I changed the routing to divert more entities over to the Bag component to exercise the added components. I then found that the number of entities in the system exceeded the maximum number of 3D entity objects I’d allocated (which halted the simulation), so I changed the maximum from 35 to 50.

Everything else worked perfectly, including the reporting. It added report sections for “Ped Primary” and “Ped Secondary” (short for Pedestrian Primary and Secondary, or Queue and Process 20 and Queue and Process 21, respectively). I was originally wondering if it would create new sections of reports for the spawned entities but the way I had it set up they retained the Process Speed and Residency properties of their parent entities and the Queue and Process components were set to use those properties.

It suddenly occurred to me how to make a combined Queue-Process component, and also a process component with multiple, parallel processing positions. Both of these ideas had been on my To Do list for a while, so that’s what I’ll work on tomorrow. Such a component will greatly compress and simplify the specification and layout of a simulation system.

Last but not least I seriously reworked the basic HTML and CSS configuration.

Posted in Simulation | Tagged | Leave a comment

A Simple Discrete-Event Simulation: Part 75

Today I expanded the capability of the Bag component to allow entities to reside there, spawn new sub-entities that undergo an external process of their own, and return to the “parked” entity. Delay times can be specified that control how long it takes the spawned sub-entity to start moving once the main entity parks, and how long it takes the before main entity transfers to the exit queue once the sub-entity returns. Think of the delays like this. You drive into a parking lot and park. Then you gather up your belongings, paperwork, and do whatever else you might have to before walking in to your next activity. The activity has its own duration, at which point you walk back to your parked car. Then you put all your stuff back in the car, get settled as you need to, and you finally drive out of the parking lot. The spawned entity is, in our example, colored orange. When it is waiting at the main entity within the Bag component is is displayed on top of the main entity that spawned it, a handful of pixels up and to the right.

The value for the Bag component’s process time has no meaning in this case, though perhaps it should double as one or both of the delay times.

Two new components were created to serve as the internal “entry” into the sub-process and “exit” back out of the sub-process. They have as little of the machinery common to the other component types as possible. When entities are forwarded to them they are immediately forwarded to their next component. The source component can only connect to a single, downstream component, but multiple upstream components can be connected to the destination component.

The external system can be made up of any types of components (except Entry or Exit components) but I’ve included only two paths so I didn’t have to think about reporting on top of everything else I did today. That will be tomorrow’s project. The process of traversing an external system is referred to as a “sub-journey” and the new components and processes are named accordingly.

Here’s the updated code for the Bag component:

Here are the new source and destination components:

Here’s the code that defines the entire system:

Some adjustments had to be made to the DisplayElement object as well, to handle drawing the 2D and 3D versions of the new components.

I also made the background transparent so it’ll look a bit nicer in an iframe and need to do something more explicit with the 3D versions of the sub-entities.

Posted in Simulation | Tagged | Leave a comment

A Simple Discrete-Event Simulation: Part 74

Following yesterday’s work I had three tasks to complete. The first task was to fix the reporting for cases where a Process or Bag component is not the last item in a component group. The fix was to only run the reporting process for exiting a group when the entity leaving a Process or Bag component is going to a different non-Path component that’s in a different group. This involved embedding the report function at the end of the forwardEntity function in the if statement shown below.

The getComponentGroup function in Path components had to be modified so it actually returns the component group of its next component, so it always returns the component group of the next non-Path component.

The second task was to experiment with different ways of specifying the process time for certain components in a modular way. I originally passed in an array of values and called a fixed, external function to determine the array index to use base on the relevant entity’s user-defined properties. Later I added an additional index to the process so different Process or Bag components could generate lookup indices based on different properties or combinations of properties. I then realized that I could simply pass a custom function in for each case. The code for one way of doing this is here:

If we want to retain some additional form of external modularity of parameters we could do something like this:

The possibilities are many.

The third and final task was to allow the simulation to run until it is empty if a specific flag is set. I defined a global variable called runToEmptyFlag and modified two tests that control when to stop the simulation and when to stop recording data. The logic says to run to at least the minimum time and then stop if runToEmptyFlag is false, or keep going until there are no entities left in the system if runToEmptyFlag is true. Today’s version of the model has the flag set to true, so it will run beyond 630 time units as long as there are entities still in the system. If the first run doesn’t run past that time because it clears out then reset and rerun it until you see the desired behavior. The runtimes can vary quite a bit depending on how the type and routing dice fall.

I noticed that the final time increment would not be reported properly if the systems runs to empty beyond its allotted time. The fix was to add in an extra reporting increment if the global clock is greater than the number of reporting cycles run times the number of time units per cycle.

Posted in Simulation | Tagged | Leave a comment