00001 #include "DualCoding/ShapeEllipse.h"
00002 #include "DualCoding/EllipseData.h"
00003 #include "Graphics.h"
00004 #include "FilterBankGenerator.h"
00005
00006 using namespace std;
00007
00008
00009
00010
00011
00012 #define CHKBOUNDS(p,ERR_F) { \
00013 unsigned int rowoffset=(p-img1)-(p-img1)/yInc*yInc; \
00014 if(p<img1 || p>=img1+h*yInc || rowoffset>=w*xInc || rowoffset/xInc*xInc!=rowoffset) { \
00015 cout << "Graphics Bad draw! line:" << __LINE__ << " frame=" << (gen!=NULL?gen->getFrameNumber():0) << ' ' << (int)(p-img1) << " w=" << w << " xInc=" << xInc << " h=" << h << " yInc=" << yInc << endl; \
00016 ERR_F; \
00017 } \
00018 }
00019
00020 Graphics::Graphics(FilterBankGenerator& fbg, unsigned int layer, unsigned int channel)
00021 : gen(&fbg), genLayer(layer), genChan1(channel), genChan2(channel), genChan3(channel),
00022 img1(NULL), img2(NULL), img3(NULL), w(0), h(0), xInc(0), yInc(0), color(0, 0, 0) {
00023 updateFBG();
00024 }
00025
00026 Graphics::Graphics(FilterBankGenerator& fbg, unsigned int layer, unsigned int chan1, unsigned int chan2, unsigned int chan3)
00027 : gen(&fbg), genLayer(layer), genChan1(chan1), genChan2(chan2), genChan3(chan3),
00028 img1(NULL), img2(NULL), img3(NULL), w(0), h(0), xInc(0), yInc(0), color(0, 0, 0) {
00029 updateFBG();
00030 }
00031
00032 Graphics::Graphics(unsigned char* base, unsigned int width, unsigned int height, unsigned int interval, unsigned int stride)
00033 : gen(NULL), genLayer(), genChan1(), genChan2(), genChan3(),
00034 img1(base), img2(base), img3(base), w(width), h(height), xInc(interval), yInc(stride), color(0, 0, 0) {}
00035
00036 void Graphics::updateFBG() {
00037 if(gen==NULL)
00038 return;
00039 img1=gen->getImage(genLayer,genChan1);
00040 img2=gen->getImage(genLayer,genChan2);
00041 img3=gen->getImage(genLayer,genChan3);
00042 w=gen->getWidth(genLayer);
00043 h=gen->getHeight(genLayer);
00044 xInc=gen->getIncrement(genLayer);
00045 yInc=gen->getStride(genLayer);
00046 }
00047
00048 void Graphics::drawRect(int x, int y, int width, int height) {
00049 if(width<0) {
00050 x+=width;
00051 width=-width;
00052 }
00053 if(height<0) {
00054 y+=height;
00055 height=-height;
00056 }
00057 if(x>=(int)w || y>=(int)h || x+width<0 || y+height<0)
00058 return;
00059 if(x<0 && y<0 && x+width>=(int)w && y+height>=(int)h)
00060 return;
00061 unsigned int left=x>0?x:0;
00062 unsigned int top=y>0?y:0;
00063 unsigned int right=( (x+width>=(int)w) ? w : (unsigned int)(x+width));
00064 unsigned int bot=( (y+height>=(int)h) ? h : (unsigned int)(y+height));
00065
00066 if(x>=0) {
00067 unsigned int result = top*yInc+left*xInc;
00068 unsigned char* p1=img1+result;
00069 unsigned char* p2=img2+result;
00070 unsigned char* p3=img3+result;
00071 unsigned char* end1=img1+result;
00072 while (p1!=end1) {
00073 CHKBOUNDS(p1,return);
00074 *p1=color.y;
00075 *p2=color.u;
00076 *p3=color.v;
00077 p1+=yInc;
00078 p2+=yInc;
00079 p3+=yInc;
00080 }
00081 }
00082
00083 if(y>=0) {
00084 unsigned int result1 = top*yInc+left*xInc;
00085 unsigned int result2 = top*yInc+right*xInc;
00086 unsigned char* p1=img1+result1;
00087 unsigned char* p2=img2+result1;
00088 unsigned char* p3=img3+result1;
00089 unsigned char* end1=img1+result2;
00090 while (p1!=end1) {
00091 CHKBOUNDS(p1,return);
00092 *p1=color.y;
00093 *p2=color.u;
00094 *p3=color.v;
00095 p1+=xInc;
00096 p2+=xInc;
00097 p3+=xInc;
00098 }
00099 }
00100
00101 if(right<w && left!=right) {
00102 unsigned int result1 = top*yInc+right*xInc;
00103 unsigned int result2 = bot*yInc+right*xInc;
00104 unsigned char* p1=img1+result1;
00105 unsigned char* p2=img2+result1;
00106 unsigned char* p3=img3+result1;
00107 unsigned char* end1=img1+result2;
00108 while (p1!=end1) {
00109 CHKBOUNDS(p1,return);
00110 *p1=color.y;
00111 *p2=color.u;
00112 *p3=color.v;
00113 p1+=yInc;
00114 p2+=yInc;
00115 p3+=yInc;
00116 }
00117 }
00118
00119 if(bot<h && top!=bot) {
00120 unsigned int result1 = bot*yInc+left*xInc;
00121 unsigned int result2 = bot*yInc+right*xInc;
00122 unsigned char* p1=img1+result1;
00123 unsigned char* p2=img2+result1;
00124 unsigned char* p3=img3+result1;
00125 unsigned char* end1=img1+result2;
00126 unsigned char* end2=img2+result2;
00127 unsigned char* end3=img3+result2;
00128 while(p1!=end1 && p2!=end2 && p3!=end3) {
00129 CHKBOUNDS(p1,return);
00130 *p1=color.y;
00131 *p2=color.u;
00132 *p3=color.v;
00133 p1+=xInc;
00134 p2+=xInc;
00135 p3+=xInc;
00136 }
00137 }
00138
00139 if(right<w && bot<h) {
00140 unsigned int result = bot*yInc+right*xInc;
00141 unsigned char* p1=img1+result;
00142 unsigned char* p2=img2+result;
00143 unsigned char* p3=img3+result;
00144 CHKBOUNDS(p1,return);
00145 *p1=color.y;
00146 *p2=color.u;
00147 *p3=color.v;
00148 return;
00149 }
00150 }
00151 void Graphics::drawRect(float x, float y, float width, float height) {
00152 unsigned int left,top,right,bot;
00153 getPixelCoordinates(left,top,x,y);
00154 getPixelCoordinates(right,bot,x+width,y+height);
00155 drawRect((int)left,(int)top,(int)(right-left),(int)(bot-top));
00156 }
00157
00158
00159
00160
00161
00162
00163 void Graphics::drawLine(int ix1, int iy1, int ix2, int iy2) {
00164
00165
00166
00167
00168
00169 if( (ix1<0 && ix2<0) || (iy1<0 && iy2<0) || (ix1>=(int)w && ix2>=(int)w) || (iy1>=(int)h && iy2>=(int)h) )
00170 return;
00171
00172 float x1=ix1, y1=iy1, x2=ix2, y2=iy2;
00173 float width=x2-x1;
00174 float height=y2-y1;
00175 bool clipped=false;
00176 if(width!=0) {
00177 float slope=height/width;
00178 if(x1<x2) {
00179 if(x1<0) {
00180 y1-=x1*slope;
00181 x1=0;
00182 clipped=true;
00183 }
00184 if(x2>=w) {
00185 y2-=(x2-(w-1))*slope;
00186 x2=w-1;
00187 clipped=true;
00188 }
00189 } else {
00190 if(x2<0) {
00191 y2-=x2*slope;
00192 x2=0;
00193 clipped=true;
00194 }
00195 if(x1>=w) {
00196 y1-=(x1-(w-1))*slope;
00197 x1=w-1;
00198 clipped=true;
00199 }
00200 }
00201 }
00202 if(clipped) {
00203 if( (x1<0 && x2<0) || (y1<0 && y2<0) || (x1>=w && x2>=w) || (y1>=h && y2>=h) )
00204 return;
00205 clipped=false;
00206 }
00207 if(height!=0) {
00208 float invslope=width/height;
00209 if(y1<y2) {
00210 if(y1<0) {
00211 x1-=y1*invslope;
00212 y1=0;
00213 clipped=true;
00214 }
00215 if(y2>=h) {
00216 x2-=(y2-(h-1))*invslope;
00217 y2=h-1;
00218 clipped=true;
00219 }
00220 } else {
00221 if(y2<0) {
00222 x2-=y2*invslope;
00223 y2=0;
00224 clipped=true;
00225 }
00226 if(y1>=h) {
00227 x1-=(y1-(h-1))*invslope;
00228 y1=h-1;
00229 clipped=true;
00230 }
00231 }
00232 }
00233 if(clipped) {
00234 if((x1<0 && x2<0) || (y1<0 && y2<0) || (x1>=w && x2>=w) || (y1>=h && y2>=h) )
00235 return;
00236 clipped=false;
00237 }
00238 width=x2-x1;
00239 height=y2-y1;
00240 int aw=abs((int)width);
00241 int ah=abs((int)height);
00242 int d=aw>ah?aw:ah;
00243 float dx=width/d;
00244 float dy=height/d;
00245 for(float x=x1,y=y1;d>0;d--,x+=dx,y+=dy) {
00246 unsigned int result = ((int)y)*yInc+((int)x)*xInc;
00247 unsigned char* p1=img1+result;
00248 unsigned char* p2=img2+result;
00249 unsigned char* p3=img3+result;
00250 CHKBOUNDS(p1,continue);
00251 *p1=color.y;
00252 *p2=color.u;
00253 *p3=color.v;
00254 }
00255 unsigned int result = ((int)y2)*yInc+((int)x2)*xInc;
00256 unsigned char* p1=img1+result;
00257 unsigned char* p2=img2+result;
00258 unsigned char* p3=img3+result;
00259 CHKBOUNDS(p1,return);
00260 *p1=color.y;
00261 *p2=color.u;
00262 *p3=color.v;
00263 }
00264 void Graphics::drawLine(float x1, float y1, float x2, float y2) {
00265 unsigned int px1,py1,px2,py2;
00266 getPixelCoordinates(px1,py1,x1,y1);
00267 getPixelCoordinates(px2,py2,x2,y2);
00268 drawLine((int)px1,(int)py1,(int)px2,(int)py2);
00269 }
00270
00271 void Graphics::drawEllipse(int x, int y, float semimajor, float semiminor, AngPi orientation) {
00272 const float cosT = cos(orientation);
00273 const float sinT = sin(orientation);
00274 const float xRange = semimajor;
00275 const float majorSq = xRange * xRange;
00276 const float aspectRatio = semiminor / semimajor;
00277
00278 for(float xDist = -xRange; xDist <= xRange; xDist += 0.2f) {
00279 const float yRange = sqrt(max(0.f, majorSq - xDist*xDist)) * aspectRatio;
00280 int px = round(x + xDist*cosT + yRange*sinT);
00281 int py = round(y - yRange*cosT + xDist*sinT);
00282 drawPoint(px, py);
00283 px = round(x + xDist*cosT - yRange*sinT);
00284 py = round(y + yRange*cosT + xDist*sinT);
00285 drawPoint(px, py);
00286 }
00287 }
00288
00289 void Graphics::drawEllipse(float x, float y, float semimajor, float semiminor, AngPi orientation ) {
00290 unsigned int px, py;
00291 getPixelCoordinates(px,py,x,y);
00292 drawEllipse((int)px,(int)py,semimajor,semiminor,orientation);
00293 }
00294
00295 void Graphics::drawQuarterEllipse(int x, int y, float semimajor, float semiminor, AngPi orientation) {
00296 const float cosT = cos(orientation);
00297 const float sinT = sin(orientation);
00298 const float xmax = abs(semimajor);
00299 const float majorSq = semimajor * semimajor;
00300 const float xsign = semimajor > 0 ? 1 : -1;
00301 const float ysign = semiminor > 0 ? 1 : -1;
00302 const float aspectRatio = abs(semiminor / semimajor);
00303 for (float xval=0; xval <= xmax; xval += 0.1f) {
00304 const float yval = sqrt(max(0.f, majorSq-xval*xval)) * aspectRatio;
00305 int px = round(x + xval*cosT*xsign - yval*sinT*ysign);
00306 int py = round(y + yval*cosT*ysign + xval*sinT*xsign);
00307 drawPoint(px, py);
00308 }
00309 }
00310
00311 void Graphics::getPixelCoordinates(unsigned int& px, unsigned int& py, float x, float y) const {
00312 if(gen!=NULL) {
00313 gen->getPixelCoordinates(px,py,x,y,genLayer);
00314 } else {
00315
00316 px=(unsigned int)((w-1)*(x+1)/2+.5f);
00317 float aspect=h/(float)w;
00318 py=(unsigned int)((h-1)*(y+aspect)/(aspect*2)+.5f);
00319 }
00320 }
00321
00322 void Graphics::getRealCoordinates(float& x, float& y, unsigned int px, unsigned int py) const {
00323 if(gen!=NULL) {
00324 gen->getRealCoordinates(x,y,px,py,genLayer);
00325 } else {
00326
00327 x=px/(float)(w-1)*2-1;
00328 float aspect=h/(float)w;
00329 y=py/(float)(h-1)*aspect*2-aspect;
00330 }
00331 }
00332
00333
00334
00335
00336