00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "mmsgui/ft/mmsftcontour.h"
00034 #include <math.h>
00035
00036 static const unsigned int BEZIER_STEPS = 5;
00037
00038 MMSFTContour::MMSFTContour(FT_Vector *outlineVertexList, char *outlineVertexTags, unsigned int outlineNumVertices) {
00039
00040 MMSFTVertex prev, cur(outlineVertexList[(outlineNumVertices - 1) % outlineNumVertices]), next(outlineVertexList[0]);
00041 MMSFTVertex a;
00042 double olddir, dir = atan2((next - cur).Y(), (next - cur).X());
00043 double angle = 0.0;
00044
00045
00046
00047 for(unsigned int i = 0; i < outlineNumVertices; i++) {
00048 prev = cur;
00049 cur = next;
00050 next = MMSFTVertex(outlineVertexList[(i + 1) % outlineNumVertices]);
00051 olddir = dir;
00052 dir = atan2((next - cur).Y(), (next - cur).X());
00053
00054
00055 double t = dir - olddir;
00056 if(t < -M_PI) t += 2 * M_PI;
00057 if(t > M_PI) t -= 2 * M_PI;
00058 angle += t;
00059
00060
00061 if (outlineNumVertices < 2 || FT_CURVE_TAG(outlineVertexTags[i]) == FT_Curve_Tag_On) {
00062 AddVertex(cur);
00063 }
00064 else
00065 if (FT_CURVE_TAG(outlineVertexTags[i]) == FT_Curve_Tag_Conic) {
00066 MMSFTVertex prev2 = prev, next2 = next;
00067
00068
00069
00070
00071 if (FT_CURVE_TAG(outlineVertexTags[(i - 1 + outlineNumVertices) % outlineNumVertices]) == FT_Curve_Tag_Conic) {
00072 prev2 = (cur + prev) * 0.5;
00073 AddVertex(prev2);
00074 }
00075
00076
00077 if(FT_CURVE_TAG(outlineVertexTags[(i + 1) % outlineNumVertices]) == FT_Curve_Tag_Conic) {
00078 next2 = (cur + next) * 0.5;
00079 }
00080
00081 evaluateQuadraticCurve(prev2, cur, next2);
00082 }
00083 else
00084 if (FT_CURVE_TAG(outlineVertexTags[i]) == FT_Curve_Tag_Cubic
00085 &&FT_CURVE_TAG(outlineVertexTags[(i + 1) % outlineNumVertices]) == FT_Curve_Tag_Cubic) {
00086
00087 evaluateCubicCurve(prev, cur, next, MMSFTVertex(outlineVertexList[(i + 2) % outlineNumVertices]));
00088 }
00089 }
00090
00091
00092
00093 clockwise = (angle < 0.0);
00094 }
00095
00096
00097 MMSFTContour::~MMSFTContour() {
00098 this->vertexList.clear();
00099 this->outsetVertexList.clear();
00100 this->frontVertexList.clear();
00101 this->backVertexList.clear();
00102 }
00103
00104
00105 void MMSFTContour::AddVertex(MMSFTVertex vertex) {
00106 if(vertexList.empty() || (vertex != vertexList[vertexList.size() - 1] && vertex != vertexList[0])) {
00107 vertexList.push_back(vertex);
00108 }
00109 }
00110
00111
00112 void MMSFTContour::AddOutsetVertex(MMSFTVertex vertex) {
00113 outsetVertexList.push_back(vertex);
00114 }
00115
00116
00117 void MMSFTContour::AddFrontVertex(MMSFTVertex vertex) {
00118 frontVertexList.push_back(vertex);
00119 }
00120
00121
00122 void MMSFTContour::AddBackVertex(MMSFTVertex vertex) {
00123 backVertexList.push_back(vertex);
00124 }
00125
00126
00127 void MMSFTContour::evaluateQuadraticCurve(MMSFTVertex A, MMSFTVertex B, MMSFTVertex C) {
00128 for(unsigned int i = 1; i < BEZIER_STEPS; i++)
00129 {
00130 double t = static_cast<double>(i) / BEZIER_STEPS;
00131
00132 MMSFTVertex U = (1.0f - t) * A + t * B;
00133 MMSFTVertex V = (1.0f - t) * B + t * C;
00134
00135 AddVertex((1.0f - t) * U + t * V);
00136 }
00137 }
00138
00139
00140 void MMSFTContour::evaluateCubicCurve(MMSFTVertex A, MMSFTVertex B, MMSFTVertex C, MMSFTVertex D) {
00141 for(unsigned int i = 0; i < BEZIER_STEPS; i++)
00142 {
00143 double t = static_cast<double>(i) / BEZIER_STEPS;
00144
00145 MMSFTVertex U = (1.0f - t) * A + t * B;
00146 MMSFTVertex V = (1.0f - t) * B + t * C;
00147 MMSFTVertex W = (1.0f - t) * C + t * D;
00148
00149 MMSFTVertex M = (1.0f - t) * U + t * V;
00150 MMSFTVertex N = (1.0f - t) * V + t * W;
00151
00152 AddVertex((1.0f - t) * M + t * N);
00153 }
00154 }
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 MMSFTVertex MMSFTContour::ComputeOutsetVertex(MMSFTVertex A, MMSFTVertex B, MMSFTVertex C) {
00172
00173 MMSFTVertex ba = (A - B).Normalise();
00174 MMSFTVertex bc = C - B;
00175
00176
00177 MMSFTVertex tmp(bc.X() * -ba.X() + bc.Y() * -ba.Y(),
00178 bc.X() * ba.Y() + bc.Y() * -ba.X());
00179
00180
00181 double norm = sqrt(tmp.X() * tmp.X() + tmp.Y() * tmp.Y());
00182 double dist = 64.0 * sqrt((norm - tmp.X()) / (norm + tmp.X()));
00183 tmp.X(tmp.Y() < 0.0 ? dist : -dist);
00184 tmp.Y(64.0);
00185
00186
00187 return MMSFTVertex(tmp.X() * -ba.X() + tmp.Y() * ba.Y(),
00188 tmp.X() * -ba.Y() + tmp.Y() * -ba.X());
00189 }
00190
00191
00192 void MMSFTContour::setParity(int parity) {
00193 unsigned int size = getVertexCount();
00194 MMSFTVertex vOutset;
00195
00196 if(((parity & 1) && clockwise) || (!(parity & 1) && !clockwise)) {
00197
00198
00199 for(unsigned int i = 0; i < size / 2; i++) {
00200 MMSFTVertex tmp = vertexList[i];
00201 vertexList[i] = vertexList[size - 1 - i];
00202 vertexList[size - 1 -i] = tmp;
00203 }
00204
00205 clockwise = !clockwise;
00206 }
00207
00208 for(unsigned int i = 0; i < size; i++) {
00209 unsigned int prev, cur, next;
00210
00211 prev = (i + size - 1) % size;
00212 cur = i;
00213 next = (i + size + 1) % size;
00214
00215 vOutset = ComputeOutsetVertex(Vertex(prev), Vertex(cur), Vertex(next));
00216 AddOutsetVertex(vOutset);
00217 }
00218 }
00219
00220
00221 void MMSFTContour::buildFrontOutset(double outset) {
00222 for (unsigned int i = 0; i < getVertexCount(); i++) {
00223 AddFrontVertex(Vertex(i) + Outset(i) * outset);
00224 }
00225 }
00226
00227
00228 void MMSFTContour::buildBackOutset(double outset) {
00229 for (unsigned int i = 0; i < getVertexCount(); i++) {
00230 AddBackVertex(Vertex(i) + Outset(i) * outset);
00231 }
00232 }
00233