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
00040 return (TColor)(c.r+(c.g<<8)+(c.b<<16));
00041 }
00042
00043
00044
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
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
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
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
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) {
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
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
00198 c->Pixels[x][y] = _start.TC;
00199 if (dy==0) {
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) {
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) {
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
00226
00227
00228
00229
00230 c->Pixels[x][y] = RGBA2TColor(interpolate((float)(x-xs)/
00231 (float)dx));
00232 }
00233 } else {
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
00246
00247
00248
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
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
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;
00316
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
00418 int i=0;
00419
00420
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
00467
00468
00469
00470
00471
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
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
00512 _areaNames->Add(n->Text);
00513 }
00514
00515
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
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
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
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
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)