00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "TrkReco/TTrack.h"
00014 #include "TrkReco/TSegment0.h"
00015 #include "TrkReco/TMDCUtil.h"
00016 #include "TrkReco/TMLink.h"
00017 #include "TrkReco/TMDCWire.h"
00018 #include "TrkReco/TMDCWireHit.h"
00019
00020 #include "TrkReco/Range.h"
00021
00022 TSegment0::TSegment0()
00023 : TTrackBase(),
00024 _innerWidth(0),
00025 _outerWidth(0),
00026 _nLayer(0),
00027 _clusterType(0),
00028 _duality(0.),
00029 _nDual(0),
00030 _angle(0.) {
00031 _fitted = false;
00032 }
00033
00034 TSegment0::TSegment0(const AList<TMLink> & a)
00035 : TTrackBase(a),
00036 _innerWidth(0),
00037 _outerWidth(0),
00038 _nLayer(0),
00039 _clusterType(0),
00040 _duality(0.),
00041 _nDual(0),
00042 _angle(0.) {
00043 _links.sort(SortByWireId);
00044 _fitted = false;
00045 }
00046
00047 TSegment0::~TSegment0() {
00048 }
00049
00050 void
00051 TSegment0::dump(const std::string & msg, const std::string & pre) const {
00052 if (! _fitted) update();
00053 bool def = false;
00054 if (msg == "") def = true;
00055
00056 if (def || msg.find("cluster") != std::string::npos || msg.find("detail") != std::string::npos) {
00057 std::cout << pre;
00058 std::cout << "#links=" << _links.length();
00059 std::cout << "(" << _innerWidth << "," << _outerWidth << ":";
00060 std::cout << clusterType() << ")," << _nDual << "," << _duality << ",";
00061 std::cout << _angle << std::endl;
00062 }
00063 if (def || msg.find("vector") != std::string::npos || msg.find("detail") != std::string::npos) {
00064 std::cout << pre;
00065 std::cout << "pos" << _position << "," << "dir" << _direction;
00066 std::cout << std::endl;
00067 }
00068 if (! def) TTrackBase::dump(msg, pre);
00069 }
00070
00071 void
00072 TSegment0::update(void) const {
00073 _clusterType = 0;
00074 _position = ORIGIN;
00075 _direction = ORIGIN;
00076 _inners.removeAll();
00077 _outers.removeAll();
00078
00079 if (_links.length() == 0) return;
00080
00081 _innerMostLayer = _links[0]->wire()->layerId();
00082 _outerMostLayer = _innerMostLayer;
00083 for (unsigned i = 1; i < _links.length(); i++) {
00084 unsigned id = _links[i]->wire()->layerId();
00085 if (id < _innerMostLayer) _innerMostLayer = id;
00086 else if (id > _outerMostLayer) _outerMostLayer = id;
00087 }
00088 _nLayer = _outerMostLayer - _innerMostLayer + 1;
00089
00090 double centerX = _links[0]->position().x();
00091 HepPoint3D inner = ORIGIN;
00092 HepPoint3D outer = ORIGIN;
00093 unsigned nInner = 0;
00094 unsigned nOuter = 0;
00095 for (unsigned i = 0; i < _links.length(); i++) {
00096 HepPoint3D tmp = _links[i]->position();
00097 double diff = tmp.x() - centerX;
00098 if (diff > M_PI) {
00099 tmp.setX(centerX - 2. * M_PI + diff);
00100 }
00101 else if (diff < - M_PI) {
00102 tmp.setX(centerX + 2. * M_PI + diff);
00103 }
00104
00105 _links[i]->conf(tmp);
00106 _position += tmp;
00107 unsigned id = _links[i]->wire()->layerId();
00108 if (id == _innerMostLayer) {
00109 inner += tmp;
00110 ++nInner;
00111 _inners.append(_links[i]);
00112 }
00113 if (id == _outerMostLayer) {
00114 outer += tmp;
00115 ++nOuter;
00116 _outers.append(_links[i]);
00117 }
00118 }
00119 _innerWidth = Width(_inners);
00120 _outerWidth = Width(_outers);
00121 _position *= (1. / (float) _links.length());
00122
00123 inner *= (1. / (float) nInner);
00124 outer *= (1. / (float) nOuter);
00125 _direction = (inner - outer).unit();
00126
00127 _fitted = true;
00128 }
00129
00130 double
00131 TSegment0::distance(const TSegment0 & c) const {
00132 HepVector3D dir = c.position() - _position;
00133 if (dir.x() > M_PI) dir.setX(dir.x() - 2. * M_PI);
00134 else if (dir.x() < - M_PI) dir.setX(2. * M_PI + dir.x());
00135
00136 float radial = fabs(_direction.dot(dir));
00137 float radial2 = radial * radial;
00138
00139 return (dir.mag2() - radial2) > 0.0 ? sqrt(dir.mag2() - radial2) : 0.;
00140 }
00141
00142 double
00143 TSegment0::distance(const HepPoint3D & p, const HepVector3D & v) const {
00144 HepVector3D dir = _position - p;
00145 if (dir.x() > M_PI) dir.setX(dir.x() - 2. * M_PI);
00146 else if (dir.x() < - M_PI) dir.setX(2. * M_PI + dir.x());
00147
00148 float radial = fabs(v.unit().dot(dir));
00149 float radial2 = radial * radial;
00150
00151 return (dir.mag2() - radial2) > 0.0 ? sqrt(dir.mag2() - radial2) : 0.;
00152 }
00153
00154 Range
00155 TSegment0::rangeX(double min, double max) const {
00156 #ifdef TRKRECO_DEBUG_DETAIL
00157 if (min > max) {
00158 std::cout << "TSegment0::range !!! bad arguments:min,max=";
00159 std::cout << min << "," << max << std::endl;
00160 }
00161 #endif
00162
00163 unsigned n = _links.length();
00164 if (n == 0) return Range(0., 0.);
00165
00166
00167 bool found = false;
00168 double center;
00169 for (unsigned i = 0; i < n; i++) {
00170 double x = _links[i]->position().x();
00171 if (x < min || x > max) continue;
00172 center = x;
00173 found = true;
00174 break;
00175 }
00176 if (! found) return Range(0., 0.);
00177
00178 #ifdef TRKRECO_DEBUG_DETAIL
00179
00180 #endif
00181
00182 double distanceR = 0.;
00183 double distanceL = 0.;
00184 double distanceMax = max - min;
00185 for (unsigned i = 0; i < n; i++) {
00186 double x = _links[i]->position().x();
00187 if (x < min || x > max) continue;
00188
00189 double distance0, distance1;
00190 if (x > center) {
00191 distance0 = x - center;
00192 distance1 = distanceMax - distance0;
00193 }
00194 else {
00195 distance1 = center - x;
00196 distance0 = distanceMax - distance1;
00197 }
00198
00199 if (distance0 < distance1) {
00200 if (distance0 > distanceR) distanceR = distance0;
00201 }
00202 else {
00203 if (distance1 > distanceL) distanceL = distance1;
00204 }
00205
00206 #ifdef TRKRECO_DEBUG_DETAIL
00207
00208
00209
00210
00211
00212
00213
00214 #endif
00215 }
00216
00217 double right = center + distanceR;
00218 double left = center - distanceL;
00219
00220 return Range(left, right);
00221 }
00222
00223 void
00224 TSegment0::updateType(void) const {
00225 if (! nLinks()) return;
00226 if (! _fitted) update();
00227
00228
00229 unsigned fat = 3;
00230 unsigned tall = 3;
00231
00232
00233 updateDuality();
00234
00235
00236 if ((_innerWidth < fat) && (_outerWidth < fat)) {
00237 _clusterType = 1;
00238
00239
00240 if (_nLayer > tall) _clusterType = 2;
00241 return;
00242 }
00243
00244
00245 else if (_outerWidth < fat) {
00246 _clusterType = 3;
00247 return;
00248 }
00249
00250
00251 else if (_innerWidth < fat) {
00252 _clusterType = 4;
00253 return;
00254 }
00255
00256
00257 else {
00258 bool space = true;
00259 for (unsigned i = _innerMostLayer; i <= _outerMostLayer; i++) {
00260 unsigned n = 0;
00261 AList<TMLink> tmp;
00262 for (unsigned j = 0; j < _links.length(); j++)
00263 if (_links[j]->wire()->layerId() == i) {
00264 ++n;
00265 tmp.append(_links[j]);
00266 }
00267
00268 if (n == Width(tmp)) {
00269 space = false;
00270 break;
00271 }
00272 }
00273
00274 _clusterType = 5;
00275 if (space) _clusterType = 6;
00276 return;
00277 }
00278 }
00279
00280 AList<TSegment0>
00281 TSegment0::split(void) const {
00282 AList<TSegment0> list;
00283
00284
00285 unsigned t = clusterType();
00286 #ifdef TRKRECO_DEBUG_DETAIL
00287 std::cout << " ... splitting : type=" << t << std::endl;
00288 #endif
00289 if (t == 0) return list;
00290 else if (t == 2) {
00291
00292
00293 if (_nDual > 2 && _duality > 0.7) return splitDual();
00294 return list;
00295 }
00296 else if (t == 1) return list;
00297 else if (t == 7) return list;
00298
00299
00300 else if (t == 6) return splitParallel();
00301
00302
00303 else if (t > 4) return splitComplicated();
00304
00305
00306 return splitAV();
00307 }
00308
00309 AList<TSegment0>
00310 TSegment0::splitAV(void) const {
00311 unsigned t = clusterType();
00312 AList<TMLink> seeds[2];
00313
00314
00315 const AList<TMLink> * corners;
00316 if (t == 3) corners = & _outers;
00317 else corners = & _inners;
00318 HepPoint3D corner;
00319 for (unsigned i = 0; i < corners->length(); i++)
00320 corner += (* corners)[i]->wire()->xyPosition();
00321 corner *= 1. / (float) corners->length();
00322 seeds[0].append(* corners);
00323 seeds[1].append(* corners);
00324
00325
00326 const AList<TMLink> * links;
00327 if (t == 3) links = & _inners;
00328 else links = & _outers;
00329 AList<TMLink> edge = Edges(* links);
00330 HepPoint3D edgePos[2];
00331 HepVector3D v[2];
00332 for (unsigned i = 0; i < 2; i++) {
00333 edgePos[i] = edge[i]->wire()->xyPosition();
00334 v[i] = (edgePos[i] - corner).unit();
00335 }
00336 seeds[0].append(edge[0]);
00337 seeds[1].append(edge[1]);
00338
00339 #ifdef TRKRECO_DEBUG_DETAIL
00340 std::cout << " corner:" << corner << std::endl;
00341 std::cout << " edge:" << edgePos[0] << "(";
00342 std::cout << edge[0]->wire()->layerId() << "-";
00343 std::cout << edge[0]->wire()->localId() << ")";
00344 std::cout << v[0] << std::endl;
00345 std::cout << " ";
00346 std::cout << edgePos[1] << "(";
00347 std::cout << edge[1]->wire()->layerId() << "-";
00348 std::cout << edge[1]->wire()->localId() << ")";
00349 std::cout << v[1] << std::endl;
00350 #endif
00351
00352
00353 unsigned n = _links.length();
00354 for (unsigned i = 0; i < n; i++) {
00355 TMLink * l = _links[i];
00356 if (edge.member(l)) continue;
00357 if (corners->member(l)) continue;
00358
00359 HepVector3D p = l->wire()->xyPosition() - corner;
00360 double p2 = p.mag2();
00361
00362 double dist[2];
00363 for (unsigned j = 0; j < 2; j++) {
00364 dist[j] = v[j].dot(p);
00365 double d2 = dist[j] * dist[j];
00366 dist[j] = (p2 - d2) > 0. ? sqrt(p2 - d2) : 0.;
00367 }
00368 if (dist[0] < dist[1]) seeds[0].append(l);
00369 else seeds[1].append(l);
00370
00371 #ifdef TRKRECO_DEBUG_DETAIL
00372 std::cout << " p:" << p << std::endl;
00373 std::cout << " " << l->wire()->layerId() << "-";
00374 std::cout << l->wire()->localId() << ":" << dist[0];
00375 std::cout << "," << dist[1] << std::endl;
00376 #endif
00377 }
00378
00379 AList<TSegment0> list;
00380 for (unsigned i = 0; i < 2; i++) {
00381 if (seeds[i].length()) {
00382 TSegment0 * nc = new TSegment0(seeds[i]);
00383 AList<TSegment0> ncx = nc->split();
00384 if (ncx.length() == 0) {
00385 nc->solveDualHits();
00386 list.append(nc);
00387 }
00388 else {
00389 list.append(ncx);
00390 delete nc;
00391 }
00392 }
00393 }
00394 return list;
00395 }
00396
00397 AList<TSegment0>
00398 TSegment0::splitComplicated(void) const {
00399
00400
00401 AList<TSegment0> newClusters;
00402 AList<TMLink> goodHits;
00403 unsigned n = _links.length();
00404 for (unsigned i = 0; i < n; i++) {
00405 const TMDCWireHit * h = _links[i]->hit();
00406 unsigned state = h->state();
00407 if (! (state & WireHitContinuous)) continue;
00408 if (! (state & WireHitIsolated)) continue;
00409 if ((! (state & WireHitPatternLeft)) &&
00410 (! (state & WireHitPatternRight))) continue;
00411 goodHits.append(_links[i]);
00412 }
00413 if (goodHits.length() == 0) return newClusters;
00414
00415
00416 goodHits.sort(SortByWireId);
00417 AList<TMLink> original(_links);
00418 while (goodHits.length()) {
00419
00420
00421 TMLink * seed = goodHits.last();
00422 const TMDCWire * wire = seed->wire();
00423 unsigned localId = wire->localId();
00424 AList<TMLink> used;
00425 unsigned nn = _links.length();
00426 for (unsigned i = 0; i < nn; i++) {
00427 TMLink * t = _links[i];
00428 const TMDCWire * w = t->wire();
00429
00430
00431 if (abs((int) w->localId() - (int) localId) < 2) used.append(t);
00432 }
00433
00434 #ifdef TRKRECO_DEBUG_DETAIL
00435 std::cout << " seed is " << seed->wire()->name() << std::endl;
00436 std::cout << " ";
00437 for (unsigned i = 0; i < used.length(); i++) {
00438 std::cout << used[i]->wire()->name() << ",";
00439 }
00440 std::cout << std::endl;
00441 #endif
00442
00443
00444 if (used.length() == 0) continue;
00445 if (used.length() == nLinks()) return newClusters;
00446 TSegment0 * c = new TSegment0(used);
00447 AList<TSegment0> cx = c->split();
00448 if (cx.length() == 0) {
00449 c->solveDualHits();
00450 newClusters.append(c);
00451 }
00452 else {
00453 newClusters.append(cx);
00454 delete c;
00455 }
00456 goodHits.remove(used);
00457 original.remove(used);
00458 }
00459
00460
00461 if ((original.length()) && (original.length() < nLinks())) {
00462 TSegment0 * c = new TSegment0(original);
00463 AList<TSegment0> cx = c->split();
00464 if (cx.length() == 0) {
00465 c->solveDualHits();
00466 newClusters.append(c);
00467 }
00468 else {
00469 newClusters.append(cx);
00470 delete c;
00471 }
00472 }
00473
00474 return newClusters;
00475 }
00476
00477 AList<TSegment0>
00478 TSegment0::splitParallel(void) const {
00479 AList<TMLink> seeds[2];
00480 AList<TSegment0> newClusters;
00481 for (unsigned i = _innerMostLayer; i <= _outerMostLayer; i++) {
00482 AList<TMLink> list = SameLayer(_links, i);
00483 AList<TMLink> outerList = Edges(list);
00484
00485 #ifdef TRKRECO_DEBUG_DETAIL
00486 if (outerList.length() != 2) {
00487 std::cout << "TSegment0::splitParallel !!! ";
00488 std::cout << "This is not a parallel cluster" << std::endl;
00489 }
00490 #endif
00491
00492 seeds[0].append(outerList[0]);
00493 seeds[1].append(outerList[1]);
00494 if (list.length() == 2) continue;
00495
00496 const TMDCWire & wire0 = * outerList[0]->wire();
00497 const TMDCWire & wire1 = * outerList[1]->wire();
00498 for (unsigned k = 0; k < list.length(); k++) {
00499 TMLink * t = list[k];
00500 if (t == outerList[0]) continue;
00501 if (t == outerList[1]) continue;
00502
00503 if (abs(wire0.localIdDifference(* t->wire())) <
00504 abs(wire1.localIdDifference(* t->wire())))
00505 seeds[0].append(t);
00506 else
00507 seeds[1].append(t);
00508 }
00509 }
00510
00511 if ((seeds[0].length()) && (seeds[0].length() < nLinks())) {
00512 TSegment0 * c0 = new TSegment0(seeds[0]);
00513 AList<TSegment0> c0x = c0->split();
00514 if (c0x.length()) {
00515 newClusters.append(c0x);
00516 delete c0;
00517 }
00518 else {
00519 c0->solveDualHits();
00520 newClusters.append(c0);
00521 }
00522 }
00523
00524 if ((seeds[1].length()) && (seeds[1].length() < nLinks())) {
00525 TSegment0 * c1 = new TSegment0(seeds[1]);
00526 AList<TSegment0> c1x = c1->split();
00527 if (c1x.length()) {
00528 newClusters.append(c1x);
00529 delete c1;
00530 }
00531 else {
00532 c1->solveDualHits();
00533 newClusters.append(c1);
00534 }
00535 }
00536
00537 return newClusters;
00538 }
00539
00540 void
00541 TSegment0::updateDuality(void) const {
00542 _duality = 0.;
00543 _nDual = 0;
00544 HepPoint3D x[2];
00545 for (unsigned i = _innerMostLayer; i <= _outerMostLayer; i++) {
00546 AList<TMLink> list = SameLayer(_links, i);
00547 if (i == _innerMostLayer) {
00548 for (unsigned j = 0; j < list.length(); j++)
00549 x[0] += list[j]->hit()->xyPosition();
00550 x[0] *= 1. / double(list.length());
00551 }
00552 else if (i == _outerMostLayer) {
00553 for (unsigned j = 0; j < list.length(); j++)
00554 x[1] += list[j]->hit()->xyPosition();
00555 x[1] *= 1. / double(list.length());
00556 }
00557
00558 if (list.length() == 2) {
00559 if (Width(list) != 2) continue;
00560 const TMDCWireHit * h0 = list[0]->hit();
00561 const TMDCWireHit * h1 = list[1]->hit();
00562
00563 double distance = (h0->xyPosition() - h1->xyPosition()).mag();
00564 distance = fabs(distance - h0->drift() - h1->drift());
00565 _duality += distance;
00566 ++_nDual;
00567 }
00568 }
00569 if (_nDual > 0) _duality /= float(_nDual);
00570 _angle = (x[1] - x[0]).unit().dot(x[0].unit());
00571 }
00572
00573 AList<TSegment0>
00574 TSegment0::splitDual(void) const {
00575 #ifdef TRKRECO_DEBUG_DETAIL
00576 std::cout << " TSegment0::splitDual called" << std::endl;
00577 #endif
00578 AList<TMLink> seeds[2];
00579 AList<TMLink> unknown;
00580 for (unsigned i = _innerMostLayer; i <= _outerMostLayer; i++) {
00581 AList<TMLink> list = SameLayer(_links, i);
00582
00583 if (list.length() == 2) {
00584 if (Width(list) == 2) {
00585 seeds[0].append(list[0]);
00586 seeds[1].append(list[1]);
00587 continue;
00588 }
00589 }
00590 unknown.append(list);
00591 }
00592
00593 if (unknown.length() > 0) {
00594 #ifdef TRKRECO_DEBUG_DETAIL
00595 if (seeds[0].length() == 0)
00596 std::cout << "TSegment0::splitDual !!! no TMLink for seed 0" << std::endl;
00597 if (seeds[1].length() == 0)
00598 std::cout << "TSegment0::splitDual !!! no TMLink for seed 1" << std::endl;
00599 #endif
00600 const HepPoint3D & p0 = seeds[0][0]->xyPosition();
00601 const HepPoint3D & p1 = seeds[1][0]->xyPosition();
00602 HepVector3D v0 = (seeds[0].last()->xyPosition() - p0).unit();
00603 HepVector3D v1 = (seeds[1].last()->xyPosition() - p1).unit();
00604
00605 for (unsigned i = 0; i < unknown.length(); i++) {
00606 TMLink * t = unknown[i];
00607 HepVector3D x0 = t->xyPosition() - p0;
00608 double d0 = (x0 - (x0.dot(v0) * v0)).mag();
00609 HepVector3D x1 = t->xyPosition() - p1;
00610 double d1 = (x1 - (x1.dot(v0) * v0)).mag();
00611
00612 if (d0 < d1) seeds[0].append(t);
00613 else seeds[1].append(t);
00614 }
00615 }
00616
00617 AList<TSegment0> newClusters;
00618 newClusters.append(new TSegment0(seeds[0]));
00619 newClusters.append(new TSegment0(seeds[1]));
00620 return newClusters;
00621 }
00622
00623 int
00624 TSegment0::solveDualHits(void) {
00625 updateType();
00626 if (_clusterType == 0) return 0;
00627 if (_nDual == 0) return 0;
00628
00629 AList<TMLink> seeds;
00630 AList<TMLink> duals;
00631 for (unsigned i = _innerMostLayer; i <= _outerMostLayer; i++) {
00632 AList<TMLink> list = SameLayer(_links, i);
00633
00634 if (list.length() == 1) {
00635 seeds.append(list[0]);
00636 }
00637 else if (list.length() == 2) {
00638 if (Width(list) > 1) {
00639 const TMDCWireHit * h0 = list[0]->hit();
00640 const TMDCWireHit * h1 = list[1]->hit();
00641 double distance = (h0->xyPosition() - h1->xyPosition()).mag();
00642 distance = fabs(distance - h0->drift() - h1->drift());
00643 if (distance > 0.5) duals.append(list);
00644 #ifdef TRKRECO_DEBUG_DETAIL
00645
00646
00647
00648
00649 #endif
00650 }
00651 }
00652 else if (list.length() == 0) {
00653 continue;
00654 }
00655 #ifdef TRKRECO_DEBUG_DETAIL
00656 else {
00657 std::cout << "TSegment0::solveDualHits !!! this is not expected 2";
00658 std::cout << std::endl;
00659 this->dump("cluster hits mc", " ");
00660 }
00661 #endif
00662 }
00663
00664
00665 if (seeds.length() < 2) return -1;
00666 AList<TMLink> outers = InOut(seeds);
00667 const HepPoint3D & p = outers[0]->xyPosition();
00668 HepVector3D v = (outers[1]->xyPosition() - p).unit();
00669 unsigned n = duals.length() / 2;
00670 for (unsigned i = 0; i < n; i++) {
00671 TMLink * t0 = duals[i * 2 + 0];
00672 TMLink * t1 = duals[i * 2 + 1];
00673 HepVector3D x0 = t0->xyPosition() - p;
00674 HepVector3D x1 = t1->xyPosition() - p;
00675 double d0 = (x0 - (x0.dot(v) * v)).mag();
00676 double d1 = (x1 - (x1.dot(v) * v)).mag();
00677 if (d0 < d1) _links.remove(t1);
00678 else _links.remove(t0);
00679 }
00680 return n;
00681 }
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793 unsigned
00794 NCoreLinks(const CAList<TSegment0> & list) {
00795 unsigned n = 0;
00796 unsigned nList = list.length();
00797 for (unsigned i = 0; i < nList; i++) {
00798 const AList<TMLink> & links = list[i]->links();
00799 for (unsigned j = 0; j < links.length(); j++) {
00800 unsigned state = links[j]->hit()->state();
00801 if ((! (state & WireHitPatternLeft)) &&
00802 (! (state & WireHitPatternRight)))
00803 ++n;
00804 }
00805 }
00806 return n;
00807 }
00808
00809 AList<TMLink>
00810 Links(const TSegment0 & s, const TTrack & t) {
00811 AList<TMLink> a;
00812
00813 const AList<TMLink> & links = s.links();
00814 const AList<TMLink> & trackLinks = t.links();
00815 unsigned n = links.length();
00816 for (unsigned i = 0; i < n; i++) {
00817 if (trackLinks.hasMember(links[i]))
00818 a.append(links[i]);
00819 }
00820
00821 return a;
00822 }