{"id":175,"date":"2016-03-29T16:33:12","date_gmt":"2016-03-29T23:33:12","guid":{"rendered":"http:\/\/www.howardklein.net\/?p=175"},"modified":"2016-03-29T16:33:12","modified_gmt":"2016-03-29T23:33:12","slug":"through-the-animated-looking-glass","status":"publish","type":"post","link":"https:\/\/www.howardklein.net\/?p=175","title":{"rendered":"Through the (Animated) Looking Glass\u2026"},"content":{"rendered":"<p style=\"padding-left: 30px;\"><em>\u2026in which I post yet again on a topic about which I know relatively little\u2026 which arguably is not a recipe for a long and happy professional life<\/em><\/p>\n<p>It seems like every self-respecting simulation package has at least a modicum of animation capability \u2013 and many are, in fact, designed around pretty impressive animators.\u00a0 I figured I would have to supply at least bare-bones 2-D animation sooner or later\u2026 but I hoped it would be later.\u00a0 While I felt like I had a pretty good handle on what a core simulation engine looks like, I didn\u2019t really have a clue when it came to animation. Animation struck me as a large, amorphous black box that would suck up copious amounts of my time while still resulting in an amateurish solution.\u00a0 I just didn\u2019t want to deal with it.<\/p>\n<p>So I built the rudiments of a simulation engine, created some models using that engine, and started running them.\u00a0 And, of course, I almost immediately ran into the problem of verifying those models, even at the most basic level.\u00a0 How am I supposed to make sure these models are behaving as I intend?\u00a0 Sure, I can model an M\/M\/1 queue and see if queue size and time conform to the standard analytically-derived results.\u00a0 But if they don\u2019t, how do I figure out what\u2019s going wrong?\u00a0 What about other models, with no analytic solutions?<\/p>\n<p>Yes, I could manually trace the simulation, event-by-event, but I quickly tired of that approach. Like (probably) most software developers, I\u2019m easily bored by repetition, and inherently lazy \u2013 isn\u2019t that why we like to automate stuff? Spending hours tracing and debugging the simplest of models was just not going to cut it.<\/p>\n<p>Animation seemed to be the most straightforward solution. In theory, at least, animation should quickly make the most obvious bugs, well, obvious. I really did not want to go there yet, but if the only alternative was carefully pouring through reams of trace output, then perhaps it was, in fact, time to go there. So I waded my way into the Alice-in-Wonderland world of animation technology, and dove down the first rabbit hole that presented itself.<\/p>\n<p><!--more-->I should probably take some of that back. I did spend at least a <em>little<\/em> bit of time thinking about requirements.\u00a0 This is basically what I came up with:<\/p>\n<ul>\n<li>2-D animation should be just fine, particularly if my primary goal is to debug models. I realize that the commercial products are virtually all 3-D (and pretty impressive 3-D, for that matter) \u2013 but without knowing much about it, I decided that I wasn\u2019t ready to jump into that particular pool. I\u2019ll eventually see whether or not that was a mistake \u00a0\ud83d\ude42<\/li>\n<li>I do not want to create yet another full-featured drawing or graphic design tool. That\u2019s not my area of interest, and it\u2019s certainly not my area of expertise.\u00a0 If the modeler needs or wants to create sophisticated graphic elements, they should be able to do so using something off-the-shelf \u2013 and preferably, at least one of those somethings should be free.<\/li>\n<li>In addition to moving stuff around the screen, the simulation model code should be able modify graphic elements \u2013 e.g. changing the color of all or part of an element, or changing an element\u2019s text component.<\/li>\n<li>My overall target delivery platform is, at least initially, a traditional desktop operating system. I am therefore willing to live with an animation technology that is similarly constrained.\u00a0 That being said, it would be awfully <em>nice<\/em> if I chose a technology and architecture that ultimately lends itself to a solution that also runs on mobile or web-based platforms.<\/li>\n<li>Finally\u2026 while I do not want to overly dwell on performance up front, I do need to acknowledge that ultimately, I should expect to have to deal with models containing thousands of independent graphic elements, with many (if not most) of them moving about.<\/li>\n<\/ul>\n<p>After deciding to go 2-D, I almost immediately started looking at <a href=\"https:\/\/www.w3.org\/Graphics\/SVG\/\">SVG<\/a>.\u00a0 SVG was initially attractive for a several reasons:<\/p>\n<ul>\n<li>There are plenty of editors and tools that support it, including free ones.<\/li>\n<li>It provides a mechanism for addressing and modifying graphical subcomponents \u2013 i.e., modifying text elements or the color of some sub-element of the whole.<\/li>\n<li>My UI toolkit of choice (<a href=\"http:\/\/wiki.qt.io\/PySide\">Qt<\/a>) supports it.<\/li>\n<\/ul>\n<p>So I began fiddling with the use of SVG in traditional Qt desktop graphics\u2026 and didn\u2019t get very far. While I was able to load and render SVG from external files, I couldn\u2019t do much to modify it. After banging my head against that wall for a while, I ran across internet posts suggesting that for SVG support, <a href=\"http:\/\/wiki.qt.io\/QtWebKit\">QtWebKit <\/a>was the way to go. I promptly dove in.<\/p>\n<p>QtWebKit is a Qt wrapper around the open source <a href=\"https:\/\/webkit.org\/\">WebKit <\/a>web rendering and browser engine.\u00a0 One could, for example, use it to build a complete browser using Qt APIs.\u00a0 Of particular interest, QtWebKit provides mechanisms to integrate outside code (Python, in my case) and Javascript code running within a WebKit-rendered page. In particular, it:<\/p>\n<ul>\n<li>Allows Python code to invoke Javascript functions via the Qt signal\/slot mechanism; Javascript functions may be treated as Qt slots and connected to Qt signals emitted by the Python code.<\/li>\n<li>Allows a proxy for a Python object to be created in the (DOM) window, which is thereby accessible to the Javascript code (which can then in turn invoke methods on that Python object)<\/li>\n<\/ul>\n<p>Have I mentioned the fact that up until this point, I had never written a line of Javascript in my life? And that I was (and still am) at best barely conversant when it comes to the web development tool stack?\u00a0 (There go all those job offers!)\u00a0 Time for this mostly desktop guy to begin getting a clue. So I began reading, which is, of course, \u00a0an inherently dangerous activity.<\/p>\n<p>I started reading about animation and game development in HTML5, and quickly came across warnings about the scalability (pun only partially intended) of SVG.\u00a0 When running an animated simulation, you are likely to find yourself creating and destroying lots of objects (think simulation entities); if all of these transient objects are added to\/removed from the DOM, this reading suggested that things were not going to end well.\u00a0 In other words, if I did my animation using SVG, performance was going to suck.<\/p>\n<p>Most of this initial research seemed to suggest that for performant animation, HTML Canvas is the way to go. The built-in functionality is rudimentary as compared to SVG, but it should allow for animation of a large number of objects with reasonable performance.\u00a0 So I started poking around Canvas-based toolkits, settling on <a href=\"https:\/\/github.com\/ericdrowell\/KineticJS\/\">KineticJS<\/a>, which seemed to provide both reasonable support for the kind of animation I wanted and enough documentation and code samples for a Javascript neophyte such as myself.<\/p>\n<p>At this point, one might say I no longer knew which end was up. I had started thinking in terms of SVG, was led to a partially web page\/Javascript solution precisely because it had better SVG support, and then found myself looking at a Javascript solution without SVG at all! Nonetheless, I was able to build a rudimentary simulation model editor and animator without a horrendous amount of pain. The model editor\u2019s graphical palette was limited to a small, hardwired collection of basic simulation objects, each represented by a simple graphic (think squares and triangles, along with a T-shaped object representing a queue). Using this, I was able to build and animate an M\/M\/1 queue model, and it all more or less worked. It was very basic \u2013 just a bunch of small green rectangle-shaped entities flying across the screen, queueing up in front of the server (a triangle, of course!), and then flying into my rectangular sink object to die once they were done \u2013 but it did allow me to verify my model.<\/p>\n<p>But there were also clearly going to be some issues moving forward, even given my pretty simple and basic requirements:<\/p>\n<ul>\n<li>The KineticJS library allowed me to define arbitrarily complex graphical objects \u2013 in (Javascript) code. To make this accessible to a user, I\u2019d need a graphical object editor. This didn\u2019t appear to exist for KineticJS, and I was in no mood to roll my own. Other Canvas libraries might have provided some editing tools, but I was not excited by the prospect of a library switch, particularly if it meant tying myself to a so-so graphics editor that defined graphics persisted in a non-standard (and probably homegrown) format.<\/li>\n<li>I could have incorporated PNG-based graphics, which seemed to be reasonably well supported by KineticJS. I\u2019d then be stuck with the scalability ugliness of bit-mapped graphics, and I\u2019d lose the ability to access and modify sub-elements of the graphic (to modify text or color on the fly, for example).<\/li>\n<\/ul>\n<p>I should mention that before starting this little adventure, I had not given much thought to how I would persist models to disk, and what that might mean in terms of basic modeling library design. My initial (pre-animation) simulations were just programs \u2013 import the simulation modules, define a few model-specific Process (and maybe Resource) subclasses, instantiate the objects in the model, and run the simulation.<\/p>\n<p>Now the graphical representations for most of these objects would have to be specified and saved ahead of time. Sources, sinks, resources, queues, locations of various types &#8211; all of these would be created, saved, and reloaded via an editor, plopped on to the screen as graphics, and then tied to simulation objects at run time. Some objects \u2013 entities, essentially \u2013 could be ignored; they would be created and destroyed during the simulation run, and their location on the screen would be determined based on code and the location of the other objects they interacted with.<\/p>\n<p>So essentially I had two types of objects:<\/p>\n<ul>\n<li>Static objects, which are enumerated by the model (and by extension the modeler) ahead of time and exist in a more or less fixed location (both graphically and logically) for the entire simulation. (The \u201cmore or less\u201d should probably be the subject of a future post.)<\/li>\n<li>Transient objects, which are created at various points during a simulation run, typically are destroyed during the run, and move about based on the simulation logic and the location of model\u2019s static objects.<\/li>\n<\/ul>\n<p>I can be a bit slow and dense, but I like to think that I eventually acquire at least a modicum of clue. So at this point, it slowly dawned on me that there\u2019s nothing to prevent me from using both SVG and Canvas in the same animation. I could put both an SVG and Canvas container onto my model editing and animation (HTML) page, one over the other. The transient objects \u2013 just entities, at least for now \u2013 could be rendered as simple shapes or PNGs on the Canvas container, taking advantage of Canvas\u2019s strengths \u2013 the ability to create, destroy and animate lots of simple objects in a reasonably performant way. The static objects \u2013 everything else \u2013 could be rendered by the SVG container.\u00a0 All of these objects could be defined and added to the SVG container at the start of a simulation and exist for the entire life of the run, thereby avoiding overhead associated with large scale creation and destruction of elements in SVG. And I\u2019d get the goodies that come along with SVG \u2013 compatibility with other tools\/editors, vector graphics and the transformation functionality that comes with SVG.<\/p>\n<p>All in all, this sounded much more appealing, particularly since it seemed that the static objects were likely to be the ones represented by more complex graphics. The next version of my model editor incorporated a palette of simulation objects defined by SVG graphics, and was soon followed by enhancements allowing those graphics to be customized by (Python) class \u2013 if you want a customized resource graphic, define a SimResource subclass, and attach a Python decorator that specifies it\u2019s graphical representation \u2013 typically an SVG file and the id of an element within that file. (In other words, an SVG file can be used to specify graphics for any number of different simulation object types.) This decorator also integrates with the model editor \u2013 once your SimResource subclass is sucked into your model, the new resource type appears in the editor tool palette.\u00a0 If the decorator does not specify a graphic, your subclass will inherit the graphical representation from its base class. A similar decorator may be used to define entity subclasses and graphics, though in this case, the graphical representation must be a PNG or comparable bit-mapped file.<\/p>\n<p>(As an aside, I\u2019ll note that the phrase \u201conce your subclass is sucked into your model\u201d glosses over a number of sins and pitfalls that I have not fully addressed or solved \u2013 namely the potential problems that occur when a Python-based tool dynamically and potentially repeatedly reads and uses other Python source code \u2013 any of which could have theoretically been modified by the user between uses. At some point I\u2019ll try to post something about this, but if you\u2019re dying for a sneak preview, Google \u201cPython reimport\u201d.)<\/p>\n<p>At this point, I think I\u2019ve found myself with a usable, if basic, animation framework. The 2-D graphics are simple and very cartoonish (dare I say \u201camateurish\u201d) when compared to the pretty sophisticated stuff you see in high-end commercial solutions.\u00a0 And even in the context of my simple framework, there\u2019s a lot of work left to do (and problems that have yet to show themselves!). But I\u2019m hopeful that it\u2019s enough to communicate what\u2019s happening during a simulation, which at the end of the day, is really all I need.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u2026in which I post yet again on a topic about which I know relatively little\u2026 which arguably is not a recipe for a long and happy professional life It seems like every self-respecting simulation package has at least a modicum of animation capability \u2013 and many are, in fact, designed around pretty impressive animators.\u00a0 I&#8230;&nbsp;(<a href=\"https:\/\/www.howardklein.net\/?p=175\">read more<\/a>)<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[7,4,2],"tags":[],"class_list":["post-175","post","type-post","status-publish","format-standard","hentry","category-animation","category-goals-requirements","category-simulation"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/www.howardklein.net\/index.php?rest_route=\/wp\/v2\/posts\/175","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.howardklein.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.howardklein.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.howardklein.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.howardklein.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=175"}],"version-history":[{"count":4,"href":"https:\/\/www.howardklein.net\/index.php?rest_route=\/wp\/v2\/posts\/175\/revisions"}],"predecessor-version":[{"id":179,"href":"https:\/\/www.howardklein.net\/index.php?rest_route=\/wp\/v2\/posts\/175\/revisions\/179"}],"wp:attachment":[{"href":"https:\/\/www.howardklein.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=175"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.howardklein.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=175"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.howardklein.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=175"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}