bezier.h

Go to the documentation of this file.
00001 /*
00002  * bezier.h
00003  *
00004  * Copyright (c) 2003 Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Bezier utilities
00032  */
00033 
00034 #ifndef WAVEPACKET_BEZIER_H__
00035 #define WAVEPACKET_BEZIER_H__
00036 
00037 
00038 // includes --------------------------------------------------------------------
00039 #include "common/common.h"
00040 #include "threadsafe/smart_ptr.h"
00041 
00042 #include "geometry/geometry_2d.h"
00043 
00044 /// \ingroup geometric
00045 /*@{*/
00046 
00047 ////////////////////////////////////////////////////////////////////////////////
00048 ///
00049 /// \defgroup bezier Bezier Curves
00050 ///
00051 /// Collection of objects and APIs intended to be helpful with bezier curves.
00052 ///
00053 ////////////////////////////////////////////////////////////////////////////////
00054 
00055 /*@{*/
00056 
00057 
00058 // bezier namespace
00059 namespace bezier {
00060 
00061 
00062 typedef point2d_t<float> point_t;
00063 typedef rect2d_t<float> rect_t;
00064 
00065 /**
00066  * paramaterized bezier curve
00067  *
00068  * A (3rd-order) bezier curve is parameterized on t, 0 <= t <= 1, satisfying:
00069  *
00070  *      x(t) = ax * t^3 + bx * t^2 + cx * t + x0
00071  *      y(t) = ay * t^3 + by * t^2 + cy * t + y0
00072  */
00073 struct curve_t {
00074         // manipulators
00075         void clear(void) throw() {
00076                 ax = ay = bx = by = cx = cy = x0 = y0 = 0.0;
00077         }
00078         void getPointAtT(IN float t, OUT point_t& pt) const throw() {
00079                 ASSERT((t + 1.0e-8) >= 0.0 && (t - 1.0e-8) <= 1.0,
00080                     "Bad parameter value: t=%f", t);
00081                 pt.x = ax * t * t * t + bx * t * t + cx * t + x0;
00082                 pt.y = ay * t * t * t + by * t * t + cy * t + y0;
00083         }
00084 
00085         // data fields
00086         float   ax, ay;         // 3rd-order coefficient
00087         float   bx, by;         // 2nd-order coefficient
00088         float   cx, cy;         // 1st-order coefficient
00089         float   x0, y0;         // constant
00090 };
00091 
00092 
00093 
00094 /**
00095  * bezier curve specified by control points
00096  *
00097  * a = (1 - t)
00098  *
00099  * p(t) = a^3 p0 + 3 a^2 t p1 + 3 a t^2 p2 + t^3 p3
00100  */
00101 struct control_points_t {
00102         void clear(void) throw() {
00103                         p0 = p1 = p2 = p3 = point_t(0.0, 0.0);
00104                 }
00105 
00106         void setFromPointsAndTangents(IN const point_t& q0,     // initial point
00107                                 IN const point_t& t0,   // tangent at q0
00108                                 IN const point_t& q1,   // final point
00109                                 IN const point_t& t1) throw() {
00110                         p0 = q0;        // initial point
00111                         p3 = q1;        // final point
00112                         float inv3 = 1.0 / 3.0;
00113                         p1.x = p0.x + inv3 * t0.x;
00114                         p1.y = p0.y + inv3 * t0.y;
00115                         p2.x = p3.x - inv3 * t1.x;
00116                         p2.y = p3.y - inv3 * t1.y;
00117                 }
00118 
00119         void dump(IN const char * title) const throw() {
00120                         DPRINTF("%s (bezier control points): ", title);
00121                         p0.dump("p0");
00122                         p1.dump("p1");
00123                         p2.dump("p2");
00124                         p3.dump("p3");
00125                 }
00126 
00127         // data fields
00128         point_t         p0;
00129         point_t         p1;
00130         point_t         p2;
00131         point_t         p3;
00132 };
00133 
00134 
00135 
00136 ////////////////////////////////////////////////////////////////////////////////
00137 //
00138 //      Bezier APIs
00139 //
00140 ////////////////////////////////////////////////////////////////////////////////
00141 
00142 void getCurveFromControlPoints(IN const control_points_t& cp,
00143                                 OUT curve_t& b) throw();
00144 
00145 void getControlPointsFromCurve(IN const curve_t& b,
00146                                 OUT control_points_t& cp) throw();
00147 
00148 void getRect(IN const curve_t& curve, OUT rect_t& rect) throw();
00149 
00150 void scale(IO curve_t& curve, IN float factor) throw();
00151 
00152 void write(IN const curve_t& curve, OUT std::string& value,
00153                         IN float eps) throw();
00154 
00155 void read(IN const char * value, OUT curve_t& curve);
00156 
00157 
00158 };      // bezier namespace
00159 
00160 #endif  // WAVEPACKET_BEZIER_H__
00161