Archive
Rotate A Point Collection About Another Point
Well, this will probably be the last, or nearly last post of a busy year that involved a lot of work on gigs and little focus on this blog. Sorry, maybe next year will be better
In the previous example, I showed how to rotate a box (rectangle) around an arbitrary point, but the algorithm and code never presumed anything about the geometric nature of the object. It’s possible to extend the exact same algorithm to a collection of points and that is the subject of the current post.
Instead of maintaining variables for the four vertices of a rectangle, the code was modified to work with an arbitrary point collection. A RotatablePoint class was used to hold data points and offload some of the computations. This greatly simplifies the actual demo and provides you with ample means for experimentation.
The online example starts with a small collection of points as shown below.
These points are rotated about the fixed point, drawn as a red dot. The drawing may be cleared after each rotation increment or continually updated from the prior drawing as shown below.
Have a Merry Christmas and I’ll try to post more next year!
Trig Plus Algebra Plus Geometry Plus Vectors Equals Fun
Math teachers hear the most often-uttered student phrase in history a lot more than I do, but my ears have twitched to the infamous, “I’ll never use that” or its many variants over the years. Funny how people know right now what will and will not be needed or used for the rest of their lives
Now, taken in strict isolation, a single trig or algebra formula might appear to have limited or no use in the myriad of life situations in someone’s future. It is, however, quite interesting how often problems can be solved by strategic use of a single formula from multiple areas of study. The problem discussed in this post is one such example.
In the prior post, I illustrated how some basic trig concepts could be used to solve a rotation and bounding-box problem without any presumptions or special considerations of the programming environment. This example is similar in that it illustrates how to rotate a box around an arbitrary point in its interior. The box is represented by a sequence of four coordinate pairs. It is not a Flash symbol or anything other than a sequence of coordinates. The drawing environment is simple; it can move the pen, draw lines, and draw filled circles. The programming environment contains the typical set of math functions.
Our math background includes a semester of trig, analytic geometry, and algebra. We know the very basics of vectors, but have not been introduced to matrices or matrix/coordinate transforms. As it happens, all we need to know to solve the stated problem is
1 – Polar coordinates, i.e. x = r cos(a) , y = r sin(a)
2 – Parametric equation of a straight line, i.e. P = (1-t)P0 + tP1
3 – How to add and subtract vectors
4 – How to compute the distance between two points
Refer to the diagram below.
The four points of the box are A (x1,y1), B (x2,y2), C (x3,y3), and D (x4,y4). The rotation point is R (rx,ry). The example code was written in Flex and the coordinate system in the Flash player is y-down. We are not given the coordinates of R. In fact, the box may be at an angle to the horizontal as shown in the lower, right part of the diagram. The only thing we know about R is that the component parallel to each side of the box is a fraction of that side’s length. This is where vector math can be useful.
The coordinates of R can be computed by adding the vectors V1 and V2. The percentage inputs can be converted into numbers t1 and t2 in [0,1]. The exact coordinates of the terminal points of these vectors are obtained from the parametric equation of a line. Let the non-bolded notation V1 and V2 refer to vectors from the origin representing these terminal points. Then, V1 = (1-t1)A + t1B and V2 = (1-t2)A + t2D. Since the initial point of both V1 and V2 is A, the vector constituents (Δx and Δy) are immediately available. Add the vectors and add the result to A to obtain the coordinates for R. So, we can adjust sliders that change the percentage along each side and quickly compute R regardless of any prior rotation since we should always recompute the correct coordinates for A, B, C, and D.
When R is set, imagine lines drawn from R to each of the vectors A, B, C, and D. Let the distances be r1, r2, r3, and r4, respectively. Also compute the angle each line segment makes with the horizontal using the atan2() function. Since this returns a value in [-Π, Π], a small adjustment is made to always record the angles in [0, 2Π]. This makes studying the angle computations a bit easier if you want to trace out the results as part of deconstructing the code.
Also record the initial rotation angle when R is assigned. Subsequent changes to this value rotate the box around R by some delta. If the initial angle of the box is θ, and the delta is δ, then the four points are rotated around R by an angle θ+δ. Compute the coordinates of each new vector, A, B, C, and D by using the formula for polar coordinates and add the center, R.
These concepts are illustrated in an online demo.
The percentage along each side used to compute R is adjusted by sliders as well as the rotation angle. The red dot visually identifies the rotation point, R. You may optionally display the circle traced by each of the four corner points as the box is rotated. There is a _clear (Boolean) variable in the code that you may adjust to either clear the drawing each rotation update or choose to draw over each update of the box. If the value is false, you can produce some spirograph-style drawings.
The UI was created in Flex, but the actual code is very straightforward and does not rely on anything unique to Actionscript. It could be ported to many other environment quite easily. There is also some internal documentation on how to use trig identities to reduce the number of trig computations at each rotation update.
Even more importantly, there is nothing in the code or the algorithm that relies on a box being rotated other than computing R. The actual rotation is applied to a sequence of points using the simplest of concepts from a few math disciplines. I hope this provides some sense of appreciation of problems that can be solved using only the most fundamental techniques from a few branches of applied math.
Trig 101
In the previous post, I promised to discuss the math behind rotating a rectangular sprite about its upper, left-hand registration point; that is, the origin of the sprite in its local coordinate space is the upper, left-hand corner. This is actually a segue into a more general discussion of rotation about an arbitrary point.
While some programming environments offer more direct capability than others, low-level math serves as a common denominator between them. If you understand the math, then it’s easy and efficient to port capability from one environment to another. There are also times where inlining direct computations offers opportunities for performance optimization in mobile apps or games. So, let’s start with that age-old question of what will I ever use trig for?
The programming example in the prior post dealt with computing the axis-aligned bounding box of a rectangular sprite after rotation about its origin. Refer to the diagram below.
The original sprite in light blue is rotated through an angle, a, to the orientation shown in light red. The origin (upper, left-hand corner) remains the same while the points A, B, and C are rotated to new positions A’, B’, and C’. Once the coordinates of these new points are known, it is trivial to compute the AABB (axis-aligned bounding box) shown in red.
From the outset drawing to the lower, right, let the width and height of the sprite be represented by w and h, respectively. The distance, r, is simply sqrt(w2 + h2) and the angle, b, may be precomputed using the atan2 function available in most any programming language. Using the base definitions of sine and cosine, the coordinates of point A’ are ( w*cos(a), w*sin(a) ). The coordinates of B’ are ( r*cos(a+b), r*sin(a+b) ). If a+b = c, then the coordinates of C’ are computed as ( h*cos(c+Π/2), h*sin(c+Π/2) ) .
There is no need for an additional trig computation for C’ since we can use the well-known identity, sin(x+y) = sin(x)*cos(y) + sin(y)*cos(x). cos(x+y) = cos(x)*cos(y) – sin(x)*sin(y). cos(Π/2) = 1 and sin(Π/2) = 0. Plug these into the identities and you should see that we can re-use the computation of cos(c) and sin(c). Refer to the code (the rotation() mutator function) in the prior post to check your computations. It should be easy to follow whether Actionscript, Javascript, C++, or Obj C is your language of choice.
Once we have the coordinates, the AABB is trivially computed and the computations can be easily ported to any programming environment or further optimized inside the application. All with some very basic trig and your friendly, neighborhood pythagorean theorem
The operations could be optimized beyond what is illustrated in the code and that is left as an exercise.
Notice that we computed the rotated points in the sprite’s local coordinate space. The AABB is often computed in parent space, so it’s necessary to translate to the origin of that space. This is illustrated in the boundingBox() accessor function.
There is, of course, nothing special about rotation about the upper, left-hand corner. The next example will cover rotation about the centroid of the sprite, which is a special case of rotation about an arbitrary point in the sprite’s coordinate space. No matter what application you are working on or language you are working with, understanding what is happening ‘under the hood’ can go a long way. I hope you found something useful in this post.
Typescript and Jangaroo
I think I’m about to set a new personal record for lowest number of posts in a given year. Is it really October already?
Well, at least I’m working and on a pretty interesting project from both a mathematical and programming perspective, so I should be thankful for that.
I am, however, still interested in doing something new and interesting this year and I think it will be along the lines of a computational geometry library and/or version of the Freehand Drawing Library in Javascript. The CG library is likely to be released through a series of posts in an open-source context similar to the TechNotes series I did in Actionscript for Flash/Flex programmers. The JS FDL is intended for clients doing mobile development in an HTML/JS environment. Okay, it’s mostly for me to have fun – I confess! However, an extra license or two never hurt anyone
To this end, I’m currently looking into both Typescript and Jangaroo. Coffeescript is on the list as well, but I’m really looking to get back into Visual Studio and C++/C# development, so Typescript has some natural appeal. Perhaps sufficient time will arise to deep-dive into all three?
I guess we’ll have to wait and see. Sorry again for the waiting part. This has been a strange (but fortunately very profitable) year.
Privatizing Freehand Drawing Library
I’m into an extension of my prior gig, so time is still very limited. In addition to family issues, what little time remains is dedicated to supporting existing beta users of the Freehand Drawing Library. And, these users just scored big time. I’ve decided to keep the library private and license it only to customers, providing requested customization at an hourly rate.
Existing beta users will continue to receive free updates of the core library and the current beta period is now permanently closed. I will blog about development of the library as a segue into discussing some of the math behind the programming. I also hope to start a series on computational geometry in Javascript some time this fall.
Thanks for bearing with the extreme lack of posts this year
Geometric Shapes in Freehand Drawing Library
Well, here’s another example that I would not have though appropriate for the Freehand Drawing Library. Regular geometric shapes might be drawable as strokes (i.e. press-move-release) with some sort of external control to force straight or constant-angle line segments. That concept, however, does not seem to fit in a freehand or freeform drawing library.
After some thought, many geometric shapes can be defined (even if somewhat arbitrarily) by a bounding rectangle. The current TwoPoint stroke class could easily be extended to define such a bounding rectangle. By injecting different drawing engines, it is possible to draw a nearly unlimited number of shapes inside that bounding rectangle.
To illustrate the idea, a GeometricShape class was created that extends TwoPoint. I developed three sample drawing engines for this stroke, Ellipse, Triangle, and BasicArrow. Each engine draws the bounding rectangle while the mouse is down and clears it on release. Pre-draw parameters may be assigned to each engine to further control the shape (i.e. select an isosceles or equilateral triangle or alter arrow shape).
While these engines may seem trivial, they open the door to creating a wide variety of such drawings in the FDL, and, all line decorators are available for each shape. So, if you want a dashed ellipse or dotted arrow, it’s simply a matter of injecting the desired line decorator.
An astute reader (aka existing beta users) may ask, “what about editing?” It’s easy to modify or extend these shape drawing engines to return the vertex information for the shape. This information can be edited and then stored in a value object. That VO may be sent as auxData in the stroke dataProvider. If present, the stroke could simply redraw the shape directly from the edited vertex information instead of a bounding rectangle. It’s all supported in the FDL architecture.
An update is going out to all beta users this morning.
Editing A Cubic Bezier Spline
A couple months ago, this was something I believed I would never say about the Freehand Drawing Library. Now, the library is and always will be a drawing library. Editing is not part of the core library architecture, however, it is something that requires a level of support inside the library. In the past, this was accomplished by caching the sequence of mouse motions used to define a stroke. The points could be edited and manually assigned to a stroke, either all at once or in an ENTER_FRAME event to animate the stroke.
This works cleanly with a simple interface for typical strokes, i.e. touch-move-release motions. Now that the FDL supports splines and possibly other constructs that stretch the definition of a stroke, what about editing more complex drawings? I want to maintain a light interface and not make editing operations an integral part of the library. That inevitably leads to interface and code bloat in an attempt to satisfy every possible combination of customer-created editor.
I think it was the movie ‘War Games’ that popularized the phrase, ‘always leave yourself a back door.’ The back door to stroke manipulation outside normal FDL methods is to use arbitrary name-value parameters. Every stroke has the ability to access or mutate arbitrary data objects. It’s only two methods in the API, but they provide a wide variety of capability to custom strokes.
I added a simple spline editor to the PolyLine demo as an illustration. After creating a spline (by clicking the end button), the knot/tangent display is overlaid on top of the stroke as shown below.
The spline knots are already available since they were manually assigned to the stroke. The tangent information is entirely encapsulated inside the drawing engine, inside the stroke. That information is obtained by the demo via a parameter request,
__stroke.getParam( “tangent” + i.toString() );
It is the responsibility of each stroke class to document all custom parameter queries and settings. The above query returns in- and out-tangent values in an Object and that information is passed to the editor. Knots may be dragged, which cause a parallel shift in the tangent. The new knot and tangent information is conveyed back to the stroke with a sequence of parameter settings,
__stroke.params = { “changeKnot”:{vertex:index, x:editor.knotX, y:editor.knotY} };
or
__stroke.params = { “changeInTangent”:{vertex:index, x:editor.inTangentX, y:editor.inTangentY} };
__stroke.params = { “changeOutTangent”:{vertex:index, x:editor.outTangentX, y:editor.outTangentY} };
If a spline drawing engine is assigned to the PolyLine, it passes this information onto the internal FDLIntepolatingSpline instance. A non-spline engine (line segments) ignores the parameters.
The screenshot below shows the result of a knot drag.
After dragging the middle vertex, the following screenshot shows the result of editing the first-vertex out-tangent.
This is all supported by the existing architecture, but there is one wrinkle. If the edited spline is to be saved and then redrawn at a future time, we must have the facility to record the tangent edits *and* bypass the tangent Command when the spline is reconstructed.
I added an auxData parameter to the StrokeDataVO, which allows arbitrary auxiliary data to be recorded for a stroke. It’s easy to deep-copy an Object with a ByteArray, so preserving immutability was no problem. Now, by adding support for a ‘redraw’ parameter in the PolyLine stroke, the spline can be redrawn with arbitrary tangents supplied by external data instead of the tangents computed by the injected tangent Command.
Progress on Freehand Drawing Library Splines
Splines in the Freehand Drawing Library have been a challenge in two areas. First, the concept of freehand drawing is centered around strokes. Strokes are defined by sequence of mouse/touch points that begin with a press, continue with a sequence of moves (while pressing), and end with a release. An interpolative spline is defined with a series of interpolation points or vertices and continuity conditions at the join points. There is no concept of press-move-release. Fortunately, the FDL architecture is sufficiently general to allow points to be artificially added to strokes. The UI issue with splines is creating a user-friendly mechanism for identifying the last interpolation point.
The second issue is editing, both vertex and in/out tangents at each vertex. Since all strokes allow their input points to be either manually defined or cached and returned via user input, editing is not part of the core library. It’s impossible to create an editing system that is general, maintainable, and equally satisfies all prospective users. When it comes to splines, I don’t want to add more methods to the IFreehandDrawable interface simply to accommodate new features. New methods should be added only with careful thought and because it makes good, long-term sense for the library. Fortunately, ample back-doors exist to arbitrarily set and retrieve properties for various stroke engines through parameter access and mutation methods. I plan to use that existing scheme to expose parameters that facilitate spline editing.
Tangent construction is handled by a Command pattern that is applied across the engine spline or at individual vertices. The tangent command is injectable and its fully qualified class name is part of the stroke engine parameter set.
There is currently one spline-based stroke engine for the PolyLine stroke. The CubicBezierSpline engine is based on the cubic bezier spline in this TechNote. The tangent construction is handled by a NormalBisector Command that is injected into the stroke engine. I also plan to add another tangent command that uses the same approach as Catmull-Rom splines. This provides two different cubic bezier splines with a single code base. I also plan to provide a corner tangent command that allows sharp corners to be inserted into otherwise continuous splines.
One final feature of the architecture is the decoupling of the spline computations from the drawing facilities in the FDL. This is similar to how I decoupled spline computations from the drawing architecture in Degrafa. There are no actual spline computations performed in the CubicBezierSpline drawing engine. It contains a FDLCubicBezierSpline, which is a concrete implementation of the IFDLInterpolatingSpline interface. FDLCubicBezierSpline is completely independent of the FDL.
The final implementation issue is on-the-fly arc-length parameterization. In order to draw the spline with line decorators, all requests for x-y coordinates along the spline are based on normalized arc length, not the spline’s natural parameter. In other words, getX(0.5) returns an x-coordinate of a point that is approximately one-half the length along the entire spline. The arc-length parameterization is optimized for monotonically increasing or decreasing normalized arc-length queries. It presumes constant redraws of the spline, so there is no pre-computation/lookup applied in the parameterization.
A screenshot of work in progress is provided below.
During debugging, the outer edge of the convex hull of the bezier control points is drawn (in black). The red dots are points on the cubic bezier spline at (approximate) uniform normalized arc length. The next step is to apply a line decorator to actually draw the spline. Another advantage of automatic arc-length parameterization is relatively easy computation of the Δs to use in point-to-point drawing of the spline. This mimics a freehand curve like all the other engines, which allows automatic application of the existing line decorators in drawing the spline.
Quadratic Arc Decorators for Freehand Drawing Library
I just finished the first cut at the quadratic arc decorators for the Freehand Drawing Library. Previously, only solid arcs could be drawn. The example below shows dashed- and dotted-line decoration applied to arrowed arcs.
The decorators all share a fast, on-the-fly arc-length parameterization utility. I still have a few tweaks to make to one of the decorators before full production release, but the new library is going out to all beta users this morning.
Based on feedback, I’m going to add one more stroke (Polygonal) and two spline-based drawing engines to the full release. Because of this new addition, I’m seeking a couple more beta users. If your drawing requirements could benefit from a variety of splines, including splines that auto-convert to shapes (i.e. lines and quads) for creating dynamic outlines/fills, please e-mail me for more information on entering the beta program.
The beta includes full source code and there is a small, 3-figure license fee. All beta users get FREE upgrades for life. Email is theAlgorithmist [at] gmail [dot] com. Thanks!
Graphing Non-Functions
My current gig is winding down, so this will probably be the last update on the function graphing engine for a while. Although the function graphing engine is architected to graph cartesian or parameteric functions, only cartesian functions were supported in the initial release. All functions defined in XML must implement an IPlottable interface, which means that evaluation and derivative methods are interpreted with y as a strict function of x. All functions must be marked as cartesian, since a parametric function will not plot in the initial implementation.
What about non-functions, that is cases where y is not strictly a function of x? As the saying goes, there is always a back door. Functions may identify themselves as self-plotting. In this case, the engine does not sample the function. Instead, it provides the function with all the relevant information regarding the current graph window and calls the function’s plot() method. A self-plotting function is welcome to draw anything it pleases, including Bezier curves, conic sections, spirals, or even smiley faces
Problems may arise with derived functions, however, i.e. other functions that derive their visual display from the definition of another function. A graphical Marker function is a perfect example. The Marker is an artist-generated, interactive graphic asset that is constrained to the path of another function. If domain values exist for which there is not a unique range value, then Marker movement is unpredictable.
This example shows how to work around the non-function issue to a degree. It plots parabolas that open upward, downward, and to the left or right. More specifically, the parabola directrix is either parallel to the x or y axis. Parallel to the x-axis is good. Parallel to the y-axis causes problems.
Suppose we want a Marker constrained to the parabola along with a display of the tangent and normal, as well as the directrix. The fixed distance from the point on the parabola to the directrix and axis of symmetry is also drawn.
Of the four use cases, the Marker follows y as a function of x in two and x as a function of y in the other two. We can’t use the function graphing engine to manage the Marker display as it always calls the base function (parabola) eval() method with an input x-coordinate. The derivative and normal displays won’t work in two cases because dy/dx is not uniquely defined.
In general, the equation of a parabola with vertex (h,k), focus (h,k+p), and directrix y=k-p is given by
(x-h)2 = 4p(y-k)
which allows y to be defined as a function of x, or x as a function of y. There are really only two use cases requiring consideration, directrix parallel to the y-axis and directrix parallel to the x-axis. In one case, horizontal mouse movement is used to position the Marker. Vertical mouse movements control the Marker in the other case.
The custom Marker is composed directly into the custom Parabola function, which is marked as self-plotting. This function is responsible for creating the Marker and controlling its placement as well as drawing all supporting graphics.
The Parabola function is defined in XML as
<function id=”Parabola” class=”graph.tests.Parabola” params=”h:0,k:0,p:-1,parallelTo:y”>
<lineMetrics thickness=”2″ color=”0xff0000″ />
<data markerParams=”marker:graph.symbols.CustomMarkerSymbol,rolloverColor:0x9ACD32,digits:2″
markerCoord=”1″ >
<directrix thickness=”3″ color=”0x9933CC” alpha=”1″ lineStyle=”line_dashed” dashWidth=”6″ dashSpacing=”4″ />
<lineSet1 thickness=”2″ color=”0x0000ff” />
<lineSet2 thickness=”1″ color=”0x00ff00″ alpha=”0.5″/>
</data>
</function>
and the display is shown below.
The aspect ratio of this graph is not ideal for the example, but it’s adequate for illustrating the example. Note that the custom Parabola function is welcome to plot not only the parabola, but as many supporting graphics as it likes. The custom Marker may be dragged along the boundaries of the parabola and rollover displays the current y-coordinate by default.
A simple parameter change, h:0,k:0,p:1,parallelTo:y, causes the parabola to open to the right.
Parametric function graphing should be supported in the future, providing for a more clean and general-purpose means to plot any general parabola and supporting visuals. I thought this was an interesting example of how a decent architecture and simple concepts like Composition open up possibilities that do not seem possible based on the defined constraints of an engine.
Next post will be an update on new capability in the Freehand Drawing Library.













