Main Page   Alphabetical List   Compound List   File List   Compound Members   Related Pages  

transfer.cpp

00001 //---------------------------------------------------------------------------
00002 
00003 
00004 #pragma hdrstop
00005 
00006 #include "transfer.h"
00007 
00008 //---------------------------------------------------------------------------
00009 
00013 rgba TColor2RGBA(TColor c)
00014 {
00015         rgba tmp;
00016         tmp.r = (unsigned char)(c&0xff);
00017         tmp.g = (unsigned char)((c&0xff00) >> 8);
00018         tmp.b = (unsigned char)((c&0xff0000) >> 16);
00019         return tmp;
00020 }
00021 
00025 rgb TColor2RGB(TColor c)
00026 {
00027         rgb tmp;
00028         tmp.r = (unsigned char)(c&0xff);
00029         tmp.g = (unsigned char)((c&0xff00) >> 8);
00030         tmp.b = (unsigned char)((c&0xff0000) >> 16);
00031         return tmp;
00032 }
00033 
00037 TColor RGBA2TColor(rgba c)
00038 {
00039         //return (TColor)(0x01000000+c.r+(c.g<<8)+(c.b<<16));
00040         return (TColor)(c.r+(c.g<<8)+(c.b<<16));
00041 }
00042 
00043 //---------------------------------------------------------------------------
00044 // TLinePoint:
00045 //---------------------------------------------------------------------------
00046 const TLinePoint &TLinePoint::operator=(const TLinePoint &p)
00047 {
00048         if (&p != this) {
00049                 _x = p._x;
00050                 _y = p._y;
00051                 _c = p._c;
00052         }
00053         return *this;
00054 }
00055 
00056 //---------------------------------------------------------------------------
00057 // TLine:
00058 //---------------------------------------------------------------------------
00059 void __fastcall TLine::_drawMarker(TCanvas *c, TColor col,
00060                                    int x, int y, int width)
00061 {
00062         c->Pen->Color = col;
00063         c->Pen->Width = width;
00064 
00065         // Cross:
00066         c->MoveTo(x-2*_distPoint, y);
00067         c->LineTo(x+2*_distPoint, y);
00068         c->MoveTo(x, y-2*_distPoint);
00069         c->LineTo(x, y+2*_distPoint);
00070 
00071         // Rect:
00072         c->MoveTo(x-_distPoint, y-_distPoint);
00073         c->LineTo(x+_distPoint, y-_distPoint);
00074         c->LineTo(x+_distPoint, y+_distPoint);
00075         c->LineTo(x-_distPoint, y+_distPoint);
00076         c->LineTo(x-_distPoint, y-_distPoint);
00077 
00078         c->Pen->Width = 1;
00079 }
00080 
00081 void __fastcall TLine::_drawCross(TCanvas *c, TColor col, int x, int y)
00082 {
00083         // Cross:
00084         c->MoveTo(x-(_distPoint>>1), y);
00085         c->LineTo(x+(_distPoint>>1), y);
00086         c->MoveTo(x, y-(_distPoint>>1));
00087         c->LineTo(x, y+(_distPoint>>1));
00088 }
00089 
00090 int __fastcall TLine::getStartX(TPaintBox *pb)
00091 {
00092         return (int)((float)_start.X/_histo->getHPP(pb));
00093 }
00094 
00095 int __fastcall TLine::getStartY(TPaintBox *pb)
00096 {
00097         return pb->Height-(int)((float)_start.Y/(float)0xff*pb->Height);
00098 }
00099 
00100 int __fastcall TLine::getEndX(TPaintBox *pb)
00101 {
00102         return (int)((float)_end.X/_histo->getHPP(pb));
00103 }
00104 
00105 int __fastcall TLine::getEndY(TPaintBox *pb)
00106 {
00107         return pb->Height-(int)((float)_end.Y/(float)0xff*pb->Height);
00108 }
00109 
00110 int __fastcall TLine::getY(TPaintBox *pb, int x)
00111 {
00112         return getStartY(pb)+(int)((float)(x-getStartX(pb))*getSlope(pb));
00113 }
00114 
00115 int __fastcall TLine::getX(TPaintBox *pb, int y)
00116 {
00117         return getStartX(pb)+(int)((float)(y-getStartY(pb))/getSlope(pb));
00118 }
00119 
00120 float __fastcall TLine::getSlope(TPaintBox *pb)
00121 {
00122         return (float)(getEndY(pb)-getStartY(pb))/
00123                (float)(getEndX(pb)-getStartX(pb));
00124 }
00125 
00126 bool __fastcall TLine::highSlope(TPaintBox *pb)
00127 {
00128         return (fabs(getSlope(pb)) > 1.0);
00129 }
00130 
00131 bool __fastcall TLine::isNear(TPaintBox *pb, int x, int y)
00132 {
00133         int sx = getStartX(pb);
00134         int sy = getStartY(pb);
00135         int ex = getEndX(pb);
00136         int ey = getEndY(pb);
00137         int dx = ex - sx;
00138         int dy = ey - sy;
00139         if (dx == 0) {  // vertical line
00140                 if ( ((ey>sy) && (y>ey || y<sy)) ||
00141                      ((ey<sy) && (y<ey || y>sy)) )
00142                         return false;
00143                 else
00144                         return (DEF_DIST_SQR >= (sx-x)*(sx-x));
00145         } else if (dy == 0) {
00146                 if (x<sx || x>ex)
00147                         return false;
00148                 else
00149                         return (DEF_DIST_SQR >= ((sy-y)*(sy-y)));
00150         } else {
00151                 float k = (float)dy/(float)dx;
00152                 float absk = FABS(k);
00153                 if ((absk < 1.0) && (x<sx || x>ex))
00154                         return false;
00155                 else if ( (k >= 1.0) &&
00156                           ( ((ey>sy) && (y>ey || y<sy)) ||
00157                             ((ey<sy) && (y<ey || y<sy)) ) )
00158                         return false;
00159                 else if (FABS(k) != 1.0) {
00160                         // TODO: Refine
00161                         float dg1 = (float)(sy - k*sx);
00162                         float dg2 = (float)y - (float)x/k;
00163                         float distx = ((k*dg2 - k*dg1)/(k*k - 1.0)) - (float)x;
00164                         float disty = ((k*k*dg2 - dg1) / ((k*k) - 1.0)) - (float)y;
00165                         return ((float)DEF_DIST_SQR >= (distx*distx+disty*disty));
00166                 }
00167         }
00168         return false;
00169 }
00170 
00171 rgba __fastcall TLine::interpolate(float d)
00172 {
00173         rgba tmp;
00174         tmp.r = _start.C.r + (int)((float)(_end.C.r-_start.C.r)*d);
00175         tmp.g = _start.C.g + (int)((float)(_end.C.g-_start.C.g)*d);
00176         tmp.b = _start.C.b + (int)((float)(_end.C.b-_start.C.b)*d);
00177         tmp.a = _start.C.a + (int)((float)(_end.C.a-_start.C.a)*d);
00178         return tmp;
00179 }
00180 
00181 void __fastcall TLine::drawTo(TPaintBox *pb)
00182 {
00183         TCanvas *c = pb->Canvas;
00184         c->Pen->Color = _start.TC;
00185         int xs = getStartX(pb);
00186         int ys = getStartY(pb);
00187         int xe = getEndX(pb);
00188         int ye = getEndY(pb);
00189         int x = xs, y = ys;
00190         int dx = xe - xs;
00191         int dy = ye - ys;
00192         int sign;
00193         if (dy >= 0)    sign = 1;
00194         else            sign = -1;
00195         dy *= sign;
00196         int p = 2*dy - dy;
00197         //c->Pen->Color = _start.TC;
00198         c->Pixels[x][y] = _start.TC;
00199         if (dy==0) {                                    // horizontal line
00200                 while(x < xe) {
00201                         x++;
00202                         c->Pixels[x][y] =
00203                                 RGBA2TColor(interpolate((float)(x-xs)/
00204                                                         (float)dx));
00205                 }
00206         } else if (dx==0) {                             // vertical line
00207                 while(y != ye) {
00208                         y += sign;
00209                         c->Pixels[x][y] =
00210                                 RGBA2TColor(interpolate((float)abs(y-ys)/
00211                                                         (float)abs(dy)));
00212                 }
00213         } else if (fabs((float)dy/(float)dx) < 1.0) {   // more than 45°
00214                 int twody = 2*dy;
00215                 int twodydx = 2*(dy-dx);
00216                 while(x < xe) {
00217                         x++;
00218                         if (p < 0) {
00219                                 p += twody;
00220                         } else {
00221                                 y += sign;
00222                                 p += twodydx;
00223                         }
00224                         /*
00225                         c->Pen->Color =
00226                                 RGBA2TColor(interpolate((float)(x-xs)/
00227                                                         (float)dx));
00228                         c->Pixels[x][y] = c->Pen->Color;
00229                         */
00230                         c->Pixels[x][y] = RGBA2TColor(interpolate((float)(x-xs)/
00231                                                       (float)dx));
00232                 }
00233         } else {                                        // less than 45°
00234                 int twody = 2*dx;
00235                 int twodydx = 2*(dx-dy);
00236                 while(y != ye) {
00237                         y += sign;
00238                         if (p < 0) {
00239                                 p += twody;
00240                         } else {
00241                                 x++;
00242                                 p += twodydx;
00243                         }
00244                         /*
00245                         c->Pen->Color =
00246                                 RGBA2TColor(interpolate((float)abs(y-ys)/
00247                                                            (float)abs(dy)));
00248                         c->Pixels[x][y] = c->Pen->Color;
00249                         */
00250                         c->Pixels[x][y] =
00251                                 RGBA2TColor(interpolate((float)abs(y-ys)/
00252                                                         (float)abs(dy)));
00253                 }
00254         }
00255         if (_selected) {
00256                 if (_start.Selected)
00257                         _drawMarker(c, _start.TC, xs, ys, 2);
00258                 else
00259                         _drawMarker(c, _start.TC, xs, ys, 1);
00260                 if (_end.Selected)
00261                         _drawMarker(c, _end.TC, xe, ye, 2);
00262                 else
00263                         _drawMarker(c, _end.TC, xe, ye, 1);
00264         } else {
00265                 _drawCross(c, _start.TC, xs, ys);
00266                 _drawCross(c, _end.TC, xe, ye);
00267         }
00268 }
00269 
00270 //---------------------------------------------------------------------------
00271 // TTransfer:
00272 //---------------------------------------------------------------------------
00273 void TTransfer::_resize(int s)
00274 {
00275         int newsize = _size+s;
00276         TLine **tmp = new TLine*[newsize];
00277         for(int i=0; i<newsize; ++i) tmp[i] = 0;
00278         if (_lines) {
00279                 for(int i=0; i<_size; ++i) tmp[i] = _lines[i];
00280                 delete [] _lines;
00281         }
00282         _lines = tmp;
00283         _size = newsize;
00284 }
00285 
00286 void TTransfer::_addLine(TLine *l)
00287 {
00288         if (_fill >= _size) _resize(10);
00289         _lines[_fill] = l;
00290         _fill++;
00291 }
00292 
00293 void TTransfer::_insertLine(TLine *l, int pos)
00294 {
00295         if (pos >= _fill) {
00296                 _addLine(l);
00297         } else {
00298                 if (_fill >= _size) _resize(10);
00299                 // move the rest one back:
00300                 for(int i=_fill; i>pos; --i)
00301                         _lines[i] = _lines[i-1];
00302                 _lines[pos] = l;
00303                 _fill++;
00304         }
00305 }
00306 
00307 int TTransfer::split(TPaintBox *pb, int x, int y)
00308 {
00309         int idx = lineNear(pb, x, y);
00310         if (idx == -1) return -1;
00311         if (nearStart(idx, pb, x, y)) return -1;
00312         if (nearEnd(idx, pb, x, y)) return -1;
00313         int thex = (int)((float)x*_histo->getHPP(pb));
00314         int they = (int)((float)(pb->Height-y)/(float)pb->Height*(float)0xff);
00315         if (thex > _lines[idx]->End.X) thex = _lines[idx]->End.X; // Startpoint
00316                 // x can not be bigger than endpoint x!
00317         TLinePoint n(thex, they, _lines[idx]->End.C);
00318         _insertLine(new TLine(n, _lines[idx]->End, _histo, _distPoint, _lines[idx]->Name), idx+1);
00319         _lines[idx]->End = n;
00320         select(idx);
00321         return idx;
00322 }
00323 
00324 void TTransfer::clear()
00325 {
00326         for(int i=0; i<_fill; ++i) {
00327                 delete _lines[i];
00328                 _lines[i] = 0;
00329         }
00330         _fill = 0;
00331 }
00332 
00333 bool TTransfer::select(TPaintBox *pb, int x, int y)
00334 {
00335         int idx = lineNear(pb, x, y);
00336         if (idx == -1) return false;
00337         else {
00338                 unselect();
00339                 _lines[idx]->Selected = true;
00340                 return true;
00341         }
00342 }
00343 
00344 void TTransfer::select(int idx)
00345 {
00346         unselect();
00347         if ((idx>-1) && (idx<_fill)) _lines[idx]->Selected = true;
00348 }
00349 
00350 void TTransfer::selectStart(int idx)
00351 {
00352         unselect();
00353         if ((idx>-1) && (idx<_fill)) {
00354                 _lines[idx]->Selected = true;
00355                 _lines[idx]->Start.Selected = true;
00356         }
00357 }
00358 
00359 void TTransfer::selectEnd(int idx)
00360 {
00361         unselect();
00362         if ((idx>-1) && (idx<_fill)) {
00363                 _lines[idx]->Selected = true;
00364                 _lines[idx]->End.Selected = true;
00365         }
00366 }
00367 
00368 void TTransfer::unselect()
00369 {
00370         for(int i=0; i<_fill; ++i) {
00371                 _lines[i]->Start.Selected = false;
00372                 _lines[i]->End.Selected = false;
00373                 _lines[i]->Selected = false;
00374         }
00375 }
00376 
00377 TLine *TTransfer::getSelected()
00378 {
00379         int i = 0;
00380         bool found = false;
00381         while(i<_fill && !found) {
00382                 found = _lines[i]->Selected;
00383                 i++;
00384         }
00385         if (found)      return _lines[i-1];
00386         else            return 0;
00387 }
00388 
00389 int TTransfer::getSelIdx()
00390 {
00391         int i = 0;
00392         bool found = false;
00393         while(i<_fill && !found) {
00394                 found = _lines[i]->Selected;
00395                 i++;
00396         }
00397         if (found) return i-1;
00398         else       return -1;
00399 }
00400 
00401 TLine *TTransfer::getLine(int idx)
00402 {
00403         if (idx<0 || idx>_fill) return 0;
00404         return _lines[idx];
00405 }
00406 
00407 void TTransfer::drawTo(TPaintBox *pb)
00408 {
00409         for(int i=0; i<_fill; ++i)
00410         {
00411                 _lines[i]->drawTo(pb);
00412         }
00413 }
00414 
00415 int __fastcall TTransfer::lineNear(TPaintBox *pb, int x, int y)
00416 {
00417         // TODO: Should find all lines!
00418         int i=0;
00419         //int xx = (int)((float)x * _histo->getHPP(pb));
00420         //int yy = (int)((pb->Height-y)/(float)pb->Height*(float)0xff);
00421         bool found = false;
00422         while (!found && i<_fill) {
00423                 found = _lines[i++]->isNear(pb, x, y);
00424         }
00425         return found ? (i-1) : -1;
00426 }
00427 
00428 bool __fastcall TTransfer::nearStart(int idx, TPaintBox *pb, int x, int y)
00429 {
00430         if (idx<0 ||idx>_fill) return false;
00431         int dx = abs(_lines[idx]->getStartX(pb) - x);
00432         int dy = abs(_lines[idx]->getStartY(pb) - y);
00433         return (dx<=_distPoint && dy<=_distPoint);
00434 }
00435 
00436 bool __fastcall TTransfer::nearEnd(int idx, TPaintBox *pb, int x, int y)
00437 {
00438         if (idx<0 ||idx>_fill) return false;
00439         int dx = abs(_lines[idx]->getEndX(pb) - x);
00440         int dy = abs(_lines[idx]->getEndY(pb) - y);
00441         return (dx<=_distPoint && dy<=_distPoint);
00442 }
00443 
00444 rgba white = { 0xff, 0xff, 0xff, 0xff };
00445 
00446 rgba __fastcall TTransfer::getColor(__int16 data)
00447 {
00448         if (_setupTDataCache(data)) {
00449                 return _TDataCache[data]->col;
00450         } else {
00451                 return white;
00452         }
00453 }
00454 
00455 int __fastcall TTransfer::getName(double data)
00456 {
00457     int i = 0;
00458     while(_lines[i]->End.X<=data && i<_fill) i++;
00459     if (i>_fill) return -1;
00460     return _lines[i]->Name;
00461 }
00462 
00463 TData TData_white = { { 0xff, 0xff, 0xff, 0xff }, 0 };
00464 
00465 /*
00466 TData __fastcall TTransfer::getData(__int16 data)
00467 {
00468         if (_setupTDataCache(data)) {
00469                 return *_TDataCache[data];
00470         } else {
00471                 return TData_white;
00472         }
00473 }
00474 */
00475 
00476 TData __fastcall TTransfer::getData(double data)
00477 {
00478     int i = 0;
00479     while(_lines[i]->End.X<=data && i<_fill) i++;
00480     if (i>_fill) return TData_white;
00481     int xs = _lines[i]->Start.X;
00482     int dx = _lines[i]->End.X - xs;
00483     int ys = _lines[i]->Start.Y;
00484     int dy = _lines[i]->End.Y - ys;
00485     double d = (double)dy/(double)dx;
00486     TData res;
00487     res.col = _lines[i]->interpolate((float)(data-xs)/(float)dx);
00488     res.alpha = ((double)ys+((double)(data-xs)*d))/255.0;
00489     res.name = _lines[i]->Name;
00490     return res;
00491 }
00492 
00493 bool TTransfer::loadFromXLM(_di_IXMLNode doc)
00494 {
00495         // Names:
00496         _di_IXMLNode names = doc->ChildNodes->Nodes[OleVariant(AnsiString(XML_NODE_NAMES))];
00497         _di_IXMLNodeList nlist = names->ChildNodes;
00498         WideString wsCount = names->Attributes[XML_ATTRIB_COUNT];
00499         if (wsCount.IsEmpty()) {
00500                 ShowMessage(AnsiString("No '")
00501                             + XML_ATTRIB_COUNT
00502                             + "' attribute in '"
00503                             + XML_NODE_NAMES
00504                             + "'!");
00505                 return false;
00506         }
00507         int count = AnsiString((BSTR)wsCount).ToInt();
00508         _areaNames->Clear();
00509         for(int i = 0; i<count; ++i) {
00510                 _di_IXMLNode n = nlist->GetNode(AnsiString(XML_NODE_NAME)+AnsiString(i));
00511                 // TODO: Make ist robust!
00512                 _areaNames->Add(n->Text);
00513         }
00514 
00515         // Lines:
00516         _di_IXMLNode lines = doc->ChildNodes->Nodes[OleVariant(AnsiString(XML_NODE_LINES))];
00517         _di_IXMLNodeList llist = lines->ChildNodes;
00518         WideString wsTmp = lines->Attributes[XML_ATTRIB_COUNT];
00519         if (wsTmp.IsEmpty()) {
00520                 ShowMessage(AnsiString("No '")
00521                             + XML_ATTRIB_COUNT
00522                             + "' attribute in the '"
00523                             + XML_NODE_LINES
00524                             + "'!");
00525                 return false;
00526         }
00527         count = AnsiString((BSTR)wsTmp).ToInt();
00528         clear();
00529         _cleanTDataCache();
00530         for(int i = 0; i<count; ++i) {
00531                 _di_IXMLNode l = llist->Nodes[OleVariant(AnsiString(XML_NODE_LINE)+AnsiString(i))];
00532                 int name = AnsiString(l->Attributes[XML_ATTRIB_LINE_NAME]).ToInt();
00533                 // Getting start point:
00534                 _di_IXMLNode ep = l->ChildNodes->Nodes[OleVariant(AnsiString(XML_NODE_LINE_START))];
00535                 int x = AnsiString(ep->Attributes[XML_ATTRIB_LINE_X]).ToInt();
00536                 int y = AnsiString(ep->Attributes[XML_ATTRIB_LINE_Y]).ToInt();
00537                 rgba col;
00538                 col.r = AnsiString(ep->Attributes[XML_ATTRIB_LINE_R]).ToInt();
00539                 col.g = AnsiString(ep->Attributes[XML_ATTRIB_LINE_G]).ToInt();
00540                 col.b = AnsiString(ep->Attributes[XML_ATTRIB_LINE_B]).ToInt();
00541                 col.a = AnsiString(ep->Attributes[XML_ATTRIB_LINE_A]).ToInt();
00542                 TLinePoint s(x, y, col);
00543                 // Getting end point:
00544                 ep = l->ChildNodes->Nodes[OleVariant(AnsiString(XML_NODE_LINE_END))];
00545                 x = AnsiString(ep->Attributes[XML_ATTRIB_LINE_X]).ToInt();
00546                 y = AnsiString(ep->Attributes[XML_ATTRIB_LINE_Y]).ToInt();
00547                 col.r = AnsiString(ep->Attributes[XML_ATTRIB_LINE_R]).ToInt();
00548                 col.g = AnsiString(ep->Attributes[XML_ATTRIB_LINE_G]).ToInt();
00549                 col.b = AnsiString(ep->Attributes[XML_ATTRIB_LINE_B]).ToInt();
00550                 col.a = AnsiString(ep->Attributes[XML_ATTRIB_LINE_A]).ToInt();
00551                 TLinePoint e(x, y, col);
00552                 _addLine(new TLine(s, e, _histo, DEF_POINT_DIST, name));
00553         }
00554         return true;
00555 }
00556 
00557 
00558 bool TTransfer::saveToXML(_di_IXMLNode doc)
00559 {
00560         _di_IXMLNode names = doc->AddChild("Names");
00561         names->SetAttribute("Count", AnsiString(_areaNames->Count));
00562         for(int i=0; i<_areaNames->Count; ++i) {
00563                 _di_IXMLNode n = names->AddChild("Name"+AnsiString(i));
00564                 n->Text = _areaNames->Strings[i];
00565         }
00566 
00567         _di_IXMLNode lines = doc->AddChild(XML_NODE_LINES);
00568         lines->SetAttribute(XML_ATTRIB_COUNT, AnsiString(_fill));
00569         for(int i=0; i<_fill; ++i) {
00570                 _di_IXMLNode node = lines->AddChild(XML_NODE_LINE+AnsiString(i));
00571                 // Start:
00572                 node->SetAttribute(XML_ATTRIB_LINE_NAME, AnsiString(_lines[i]->Name));
00573                 _di_IXMLNode ep = node->AddChild(XML_NODE_LINE_START);
00574                 ep->SetAttribute(XML_ATTRIB_LINE_X, AnsiString(_lines[i]->Start.X));
00575                 ep->SetAttribute(XML_ATTRIB_LINE_Y, AnsiString(_lines[i]->Start.Y));
00576                 ep->SetAttribute(XML_ATTRIB_LINE_R, AnsiString(_lines[i]->Start.C.r));
00577                 ep->SetAttribute(XML_ATTRIB_LINE_G, AnsiString(_lines[i]->Start.C.g));
00578                 ep->SetAttribute(XML_ATTRIB_LINE_B, AnsiString(_lines[i]->Start.C.b));
00579                 ep->SetAttribute(XML_ATTRIB_LINE_A, AnsiString(_lines[i]->Start.C.a));
00580                 // End:
00581                 ep = node->AddChild(XML_NODE_LINE_END);
00582                 ep->SetAttribute(XML_ATTRIB_LINE_X, AnsiString(_lines[i]->End.X));
00583                 ep->SetAttribute(XML_ATTRIB_LINE_Y, AnsiString(_lines[i]->End.Y));
00584                 ep->SetAttribute(XML_ATTRIB_LINE_R, AnsiString(_lines[i]->End.C.r));
00585                 ep->SetAttribute(XML_ATTRIB_LINE_G, AnsiString(_lines[i]->End.C.g));
00586                 ep->SetAttribute(XML_ATTRIB_LINE_B, AnsiString(_lines[i]->End.C.b));
00587                 ep->SetAttribute(XML_ATTRIB_LINE_A, AnsiString(_lines[i]->End.C.a));
00588         }
00589         return true;
00590 }
00591 
00592 
00593 int TTransfer::addName(AnsiString &name)
00594 {
00595         _areaNames->Add(name);
00596         return _areaNames->Count;
00597 }
00598 
00599 
00600 #pragma package(smart_init)

Generated on Thu Jan 23 06:17:39 2003 for Vol by doxygen1.2.18