#include <zone_template.h>
Nevrax France
Definition at line 49 of file zone_template.h.
Public Member Functions | |
| bool | build (const std::vector< NLMISC::CVector > &vertices, const std::vector< std::pair< uint, uint > > &indexes, const CLigoConfig &config, CLigoError &errors) |
| const std::vector< CZoneEdge > & | getEdges () const |
| Get the vertex array of the template. | |
| void | getMask (std::vector< bool > &mask, uint &width, uint &height) |
| Get the mask of the template. | |
| void | serial (NLMISC::IStream &s) |
| Serialisation. | |
Static Private Member Functions | |
| sint32 | getSnappedIndex (float value, float resolution, float snap) |
| Return the interger index of a snappable value. | |
| bool | isSnapedOnGrid (float value, float resolution, float snap) |
| Return true if this value is snapped. | |
| void | snap (float &value, float snap) |
| Round a value on the snap resolution. | |
| bool | snapOnGrid (float &value, float resolution, float snap) |
| Snap a value on the grid. | |
Private Attributes | |
| std::vector< CZoneEdge > | _Edges |
| Vertex array. | |
|
||||||||||||||||||||
|
Build method. Build the zone template with a vertex list and an edge list.
Definition at line 107 of file zone_template.cpp. References _Edges, NLLIGO::CLigoConfig::CellSize, NLLIGO::CLigoError::clear(), getSnappedIndex(), isSnapedOnGrid(), NLLIGO::CLigoError::MainError, nlassert, NLMISC::Pi, NLLIGO::CLigoError::pushVertexError(), sint32, NLLIGO::CLigoConfig::Snap, NLLIGO::SnappedXFlag, NLLIGO::SnappedYFlag, uint, x, and y.
00108 {
00109 // Clear the error message
00110 errors.clear ();
00111
00112 // Make an boundary flag array
00113 vector<uint> boundaryFlags;
00114
00115 // Vertices count
00116 uint vertexCount = vertices.size();
00117
00118 // Resize the array
00119 boundaryFlags.resize (vertexCount, 0);
00120
00121 // *** Build the flag array and the snapped vertex array
00122
00123 // For each vertices
00124 uint vertex;
00125 for (vertex = 0; vertex < vertexCount; vertex++)
00126 {
00127 // Snap the point on the X grid
00128 if (isSnapedOnGrid (vertices[vertex].x, config.CellSize, config.Snap))
00129 // Flag on X
00130 boundaryFlags[vertex]|=SnappedXFlag;
00131
00132 // Snap the point on the Y grid
00133 if (isSnapedOnGrid (vertices[vertex].y, config.CellSize, config.Snap))
00134 // Flag on Y
00135 boundaryFlags[vertex]|=SnappedYFlag;
00136 }
00137
00138 // *** Build the edge set
00139 multimap<uint, uint> edgePair;
00140 multimap<uint, uint> edgePairReverse;
00141
00142 // Index count
00143 uint edgeCount = indexes.size();
00144
00145 // For each vertices
00146 uint edge;
00147 for (edge = 0; edge < edgeCount; edge++)
00148 {
00149 // Ref on the pair
00150 const pair<uint, uint> &theEdge = indexes[edge];
00151
00152 // Vertex snapped ?
00153 if ( boundaryFlags[theEdge.first] && boundaryFlags[theEdge.second] )
00154 {
00155 // Common coordinates
00156 uint common = boundaryFlags[theEdge.first] & boundaryFlags[theEdge.second];
00157
00158 // Snapped on the same kind of coordinates ?
00159 if ( common )
00160 {
00161 // Keep this edge ?
00162 bool keep = false;
00163
00164 // Snapped both on X ?
00165 if ( common & SnappedXFlag )
00166 {
00167 // Keep it
00168 keep = true;
00169 }
00170
00171 // Snapped both on X ?
00172 if ( common & SnappedYFlag )
00173 {
00174 // Keep it
00175 keep = true;
00176 }
00177
00178 // Keep this edge ?
00179 if (keep)
00180 {
00181 // Already inserted ?
00182 bool first = edgePair.find (theEdge.first) != edgePair.end();
00183 bool second = edgePairReverse.find (theEdge.second) != edgePairReverse.end();
00184
00185 // First already inserted
00186 if (first || second)
00187 {
00188 // Error, two times the same vertex
00189 errors.MainError = CLigoError::VertexAlreadyUsed;
00190
00191 if (first)
00192 errors.pushVertexError (CLigoError::VertexAlreadyUsed, theEdge.first, 0);
00193
00194 if (second)
00195 errors.pushVertexError (CLigoError::VertexAlreadyUsed, theEdge.second, 0);
00196
00197 return false;
00198 }
00199
00200 if ((!first) && (!second))
00201 {
00202 // Add to the map
00203 edgePair.insert (map<uint, uint>::value_type(theEdge.first, theEdge.second));
00204 edgePairReverse.insert (map<uint, uint>::value_type(theEdge.second, theEdge.first));
00205 }
00206 }
00207 }
00208 }
00209 }
00210
00211 // *** Build the list of non included vertices
00212
00213 // For each vertices
00214 for (uint i=0; i<vertexCount; i++)
00215 {
00216 // Vertex is inserted ?
00217 if (edgePair.find (i) == edgePair.end())
00218 {
00219 // No, add an error message
00220 errors.pushVertexError (CLigoError::NotInserted, i, 0);
00221 }
00222 else
00223 {
00224 // No, add an error message
00225 errors.pushVertexError (CLigoError::Inserted, i, 0);
00226 }
00227 }
00228
00229 // *** Build the linked list
00230
00231 // No vertices found ?
00232 if (edgePair.begin() == edgePair.end())
00233 {
00234 // Error message
00235 errors.MainError = CLigoError::NoEdgeVertices;
00236 return false;
00237 }
00238
00239 // Build the linked segments
00240 list<list<uint> > segmentList;
00241 multimap<uint, uint>::iterator currentVert = edgePair.begin();
00242
00243 // For each remaining segment
00244 while (currentVert != edgePair.end())
00245 {
00246 // Get next vert
00247 uint first = currentVert->first;
00248 uint next = currentVert->second;
00249
00250 // New list
00251 segmentList.push_front (list<uint>());
00252 list<uint> &listVert = *segmentList.begin();
00253
00254 // Put the first vertices of the edge list
00255 listVert.push_back (first);
00256 listVert.push_back (next);
00257
00258 // Erase it and
00259 edgePair.erase (currentVert);
00260
00261 // Erase the reverse one
00262 currentVert = edgePairReverse.find (next);
00263 nlassert (currentVert != edgePairReverse.end());
00264 edgePairReverse.erase (currentVert);
00265
00266 // Look forward
00267 currentVert = edgePair.find (next);
00268 while (currentVert != edgePair.end())
00269 {
00270 // Backup
00271 //uint current = currentVert->first;
00272 next = currentVert->second;
00273
00274 // Push the next vertex
00275 listVert.push_back (next);
00276
00277 // Erase it and
00278 edgePair.erase (currentVert);
00279
00280 // Erase the reverse one
00281 currentVert = edgePairReverse.find (next);
00282 nlassert (currentVert != edgePairReverse.end());
00283 edgePairReverse.erase (currentVert);
00284
00285 // Look forward
00286 currentVert = edgePair.find (next);
00287 }
00288
00289 // Edgelist ok ?
00290 if (next != first)
00291 {
00292 // No, look backward
00293 currentVert = edgePairReverse.find (first);
00294 while (currentVert != edgePairReverse.end())
00295 {
00296 // Backup
00297 uint current = currentVert->second;
00298 next = currentVert->first;
00299
00300 // Push the next vertex
00301 listVert.push_front (current);
00302
00303 // Erase it
00304 edgePairReverse.erase (currentVert);
00305
00306 // Erase the reverse one
00307 currentVert = edgePair.find (current);
00308 nlassert (currentVert != edgePair.end());
00309 edgePair.erase (currentVert);
00310
00311 // Look forward
00312 currentVert = edgePairReverse.find (current);
00313 }
00314 }
00315
00316 // Next edge list
00317 currentVert = edgePair.begin();
00318 }
00319
00320 // ** Error traitment
00321
00322 // Ok
00323 bool ok = true;
00324
00325 // Edge index
00326 uint edgeIndex = 0;
00327
00328 // List ok ?
00329 list<list<uint> >::iterator iteList = segmentList.begin ();
00330 while (iteList != segmentList.end())
00331 {
00332 // Only one list
00333 list<uint> &listVert = *iteList;
00334
00335 // First and last edge
00336 uint first = *listVert.begin();
00337 uint last = *(--listVert.end());
00338
00339 // Opened edge ?
00340 if ( first != last )
00341 {
00342 // Opened edge
00343 errors.pushVertexError (CLigoError::OpenedEdge, first, edgeIndex);
00344 errors.pushVertexError (CLigoError::OpenedEdge, last, edgeIndex);
00345
00346 // Main error
00347 errors.MainError = CLigoError::OpenedEdge;
00348
00349 // Not ko
00350 ok = false;
00351 }
00352
00353 // Next edge list
00354 edgeIndex++;
00355 iteList++;
00356 }
00357
00358 if (segmentList.size () > 1)
00359 {
00360 // Main error
00361 errors.MainError = CLigoError::MultipleEdge;
00362
00363 // Not ok
00364 ok = false;
00365 }
00366
00367 // Ok ?
00368 if (ok)
00369 {
00370 // Only one list
00371 list<uint> &listVert = *segmentList.begin ();
00372
00373 // Test vertex enchainement
00374 list<uint>::iterator vertIte = listVert.begin();
00375
00376 // Current vertex id
00377 uint previous = *(--listVert.end());
00378 vertIte++;
00379
00380 // Error vertex set
00381 set<uint> errored;
00382
00383 // For each vertices
00384 while (vertIte != listVert.end ())
00385 {
00386 // Vertex id
00387 uint next = *vertIte;
00388
00389 // Common flags
00390 uint commonFlags = boundaryFlags[previous]&boundaryFlags[next];
00391
00392 // The both on X ?
00393 if ( commonFlags & SnappedXFlag )
00394 {
00395 // Get x index
00396 sint32 prevIndex = getSnappedIndex (vertices[previous].x, config.CellSize, config.Snap);
00397 sint32 nextIndex = getSnappedIndex (vertices[next].x, config.CellSize, config.Snap);
00398
00399 // Not the same ?
00400 if (prevIndex != nextIndex)
00401 {
00402 // Vertex list error
00403 if (errored.insert (previous).second)
00404 errors.pushVertexError (CLigoError::VertexList, previous, 0);
00405 if (errored.insert (next).second)
00406 errors.pushVertexError (CLigoError::VertexList, next, 0);
00407
00408 // Main error
00409 errors.MainError = CLigoError::VertexList;
00410 }
00411 }
00412
00413 // Next vertex
00414 previous = next;
00415 vertIte++;
00416 }
00417
00418 // No error ?
00419 if (errored.empty())
00420 {
00421 // Only one list
00422 nlassert (segmentList.size()==1);
00423
00424 // First of the list
00425 vertIte = listVert.begin();
00426
00427 // Remove first
00428 listVert.erase (vertIte);
00429
00430 // Find a corner
00431 list<uint>::iterator firstIte = listVert.begin();
00432 while (firstIte != listVert.end())
00433 {
00434 // Corner ?
00435 if ( (boundaryFlags[*firstIte] & (SnappedXFlag|SnappedYFlag)) == (SnappedXFlag|SnappedYFlag) )
00436 // Yes, exit
00437 break;
00438
00439 // Next
00440 firstIte++;
00441 }
00442
00443 // Can't be the last
00444 if (firstIte == listVert.end())
00445 {
00446 // No corner found
00447 errors.MainError = CLigoError::NoCornerFound;
00448
00449 return false;
00450 }
00451
00452 // First of the segment
00453 vertIte = firstIte;
00454
00455 // Current edge list
00456 std::vector<uint32> edge;
00457
00458 // Push the first
00459 edge.push_back (*vertIte);
00460
00461 // Next
00462 vertIte++;
00463
00464 // End ?
00465 if (vertIte == listVert.end())
00466 // Start
00467 vertIte = listVert.begin();
00468
00469 // Edge index
00470 uint edgeIndex = 0;
00471
00472 // Build the edges
00473 while (1)
00474 {
00475 // Add it
00476 edge.push_back (*vertIte);
00477
00478 // Corner ?
00479 if ( (boundaryFlags[*vertIte] & (SnappedXFlag|SnappedYFlag)) == (SnappedXFlag|SnappedYFlag) )
00480 {
00481 // Get the index of start and end of the edge
00482 sint32 startX = getSnappedIndex (vertices[edge[0]].x, config.CellSize, config.Snap);
00483 sint32 startY = getSnappedIndex (vertices[edge[0]].y, config.CellSize, config.Snap);
00484 sint32 endX = getSnappedIndex (vertices[edge[edge.size()-1]].x, config.CellSize, config.Snap);
00485 sint32 endY = getSnappedIndex (vertices[edge[edge.size()-1]].y, config.CellSize, config.Snap);
00486
00487 // Same point ?
00488 if ((startX==endX) && (startY==endY))
00489 {
00490 // Error, two times the same vertex
00491 errors.MainError = CLigoError::TwoCornerVertices;
00492 errors.pushVertexError (CLigoError::TwoCornerVertices, edge[0], 0);
00493 errors.pushVertexError (CLigoError::TwoCornerVertices, edge[edge.size()-1], 0);
00494
00495 return false;
00496 }
00497
00498 // Same point ?
00499 if ((abs(startX-endX)>1) || (abs(startY-endY)>1))
00500 {
00501 // Error, two times the same vertex
00502 errors.MainError = CLigoError::CornerIsMissing;
00503 errors.pushVertexError (CLigoError::CornerIsMissing, edge[0], 0);
00504 errors.pushVertexError (CLigoError::CornerIsMissing, edge[edge.size()-1], 0);
00505
00506 return false;
00507 }
00508
00509 // Get rotation
00510 uint rotation = 4;
00511 if ((endX-startX)==1)
00512 {
00513 if ((endY-startY)==0)
00514 rotation = 0;
00515 }
00516 else if ((endX-startX)==-1)
00517 {
00518 if ((endY-startY)==0)
00519 rotation = 2;
00520 }
00521 else if ((endX-startX)==0)
00522 {
00523 if ((endY-startY)==1)
00524 rotation = 1;
00525 else if ((endY-startY)==-1)
00526 rotation = 3;
00527 }
00528
00529 // Checks
00530 nlassert (rotation != 4);
00531
00532 // Build the vertex array
00533 vector<CVector> vertexArray;
00534 vertexArray.resize (edge.size());
00535
00536 // Rotate matrix
00537 CMatrix mat;
00538 mat.identity();
00539 mat.rotateZ ((float)rotation * (float)Pi / 2);
00540 mat.setPos (CVector (vertices[edge[0]].x, vertices[edge[0]].y, 0));
00541 mat.invert ();
00542
00543 // Rotate the array
00544 for (uint i=0; i<edge.size(); i++)
00545 {
00546 // Get the value on the edge
00547 vertexArray[i] = mat * vertices[edge[i]];
00548 }
00549
00550 // Build the edge
00551 _Edges.resize (edgeIndex+1);
00552
00553 // It must work without errors
00554 CLigoError errorBis;
00555 if (!_Edges[edgeIndex].build (vertexArray, edge, rotation, startX, startY, config, errorBis))
00556 {
00557 // Flat zone
00558 errors.MainError = CLigoError::FlatZone;
00559
00560 return false;
00561 }
00562
00563 // One more edge
00564 edgeIndex++;
00565
00566 // Exit ?
00567 if (vertIte == firstIte)
00568 break;
00569
00570 // Clear the temp edge
00571 edge.clear ();
00572
00573 // Push back the last vertex
00574 edge.push_back (*vertIte);
00575 }
00576
00577 // Next vertex
00578 vertIte++;
00579
00580 // End ?
00581 if (vertIte == listVert.end())
00582 // Start
00583 vertIte = listVert.begin();
00584 }
00585
00586 sint32 bestX = 0x7fffffff;
00587 sint32 bestY = 0x80000000;
00588 uint bestEdge = 0xffffffff;
00589
00590 // Sort edges : the first as the lower x then greater y
00591 uint edgeId;
00592 for (edgeId=0; edgeId<_Edges.size(); edgeId++)
00593 {
00594 // Get the matrix
00595 CMatrix mat;
00596 _Edges[edgeId].buildMatrix (mat, config);
00597
00598 // First vertex
00599 CVector pos = mat * _Edges[edgeId].getVertex (0);
00600
00601 // Get X and Y
00602 sint32 x = getSnappedIndex (pos.x, config.CellSize, config.Snap);
00603 sint32 y = getSnappedIndex (pos.y, config.CellSize, config.Snap);
00604
00605 // Best ?
00606 if ((x<bestX)||((x==bestX)&&(y>bestY)))
00607 {
00608 // This edgeId is best
00609 bestX=x;
00610 bestY=y;
00611 bestEdge = edgeId;
00612 }
00613 }
00614
00615 // Check
00616 nlassert (bestEdge!=0xffffffff);
00617
00618 // Reoder
00619 std::vector<CZoneEdge> newEdge (_Edges.size());
00620 for (edgeId=0; edgeId<_Edges.size(); edgeId++)
00621 {
00622 // Copy the edge
00623 newEdge[edgeId]=_Edges[bestEdge++];
00624
00625 // Next
00626 if (bestEdge==_Edges.size())
00627 bestEdge=0;
00628 }
00629
00630 // Copy the final array
00631 _Edges=newEdge;
00632
00633 // Return ok
00634 return true;
00635 }
00636 }
00637
00638 // Errors.
00639 return false;
00640 }
|
|
|
Get the vertex array of the template.
Definition at line 68 of file zone_template.h. References _Edges. Referenced by NLLIGO::CMaterial::build(), and NLLIGO::CTransition::check().
00068 { return _Edges; }
|
|
||||||||||||||||
|
Get the mask of the template.
Definition at line 667 of file zone_template.cpp. References _Edges, height, nlassert, sint32, uint, uint32, width, x, and y.
00668 {
00669 // Some constantes
00670 const static sint32 addX[4] = { 1, 0, -1, 0 };
00671 const static sint32 addY[4] = { 0, 1, 0, -1 };
00672 const static sint32 cellX[4] = { 0, -1, -1, 0 };
00673 const static sint32 cellY[4] = { 0, 0, -1, -1 };
00674 const static sint32 moveX[4] = { 0, 1, 0, -1 };
00675 const static sint32 moveY[4] = { -1, 0, 1, 0 };
00676
00677 // Max
00678 sint32 xMax = 0x80000000;
00679 sint32 yMax = 0x80000000;
00680
00681 // For each edges
00682 uint edges;
00683 for (edges=0; edges<_Edges.size(); edges++)
00684 {
00685 // Get the rotation
00686 uint32 rot = _Edges[edges].getRotation ();
00687 nlassert (rot<4);
00688
00689 // Get X and Y max coordinates
00690 sint32 x = _Edges[edges].getOffsetX () + addX[rot];
00691 sint32 y = _Edges[edges].getOffsetY () + addY[rot];
00692
00693 // Greater ?
00694 if (x > xMax)
00695 xMax = x;
00696 if (y > yMax)
00697 yMax = y;
00698 }
00699
00700 // Build the array
00701 width = (uint32) xMax;
00702 height = (uint32) yMax;
00703
00704 // Bit array for each cell
00705 vector<uint32> edgeArray (xMax*yMax, 0);
00706
00707 // Resize it
00708 mask.resize (xMax*yMax, false);
00709
00710 // Set of the cells in the mask
00711 set<pair<sint32, sint32> > setCell;
00712
00713 // For each edge
00714 for (edges=0; edges<_Edges.size(); edges++)
00715 {
00716 // Get the rotation
00717 uint32 rot = _Edges[edges].getRotation ();
00718 nlassert (rot<4);
00719
00720 // Get its x and y cell coordinate
00721 sint32 x = _Edges[edges].getOffsetX () + cellX[rot];
00722 sint32 y = _Edges[edges].getOffsetY () + cellY[rot];
00723
00724 // Fill the edge array
00725 edgeArray[x+y*width] |= (1<<rot);
00726
00727 // Insert the cell
00728 setCell.insert ( pair<sint32, sint32> (x, y) );
00729 }
00730
00731 // Second set
00732 set<pair<sint32, sint32> > setCell2;
00733
00734 // For each element in the set
00735 set<pair<sint32, sint32> >::iterator ite = setCell.begin();
00736 while (ite != setCell.end())
00737 {
00738 // For each direction
00739 for (uint dir=0; dir<4; dir++)
00740 {
00741 // Get its x and y cell coordinate
00742 sint32 x = ite->first;
00743 sint32 y = ite->second;
00744
00745 // Edge in this direction ?
00746 while ( (edgeArray[x+y*width] & (1<<dir) ) == 0)
00747 {
00748 // Move in this direction
00749 x += moveX[dir];
00750 y += moveY[dir];
00751
00752 // insert it
00753 setCell2.insert ( pair<sint32, sint32> (x, y) );
00754
00755 // Some checks
00756 nlassert (x>=0);
00757 nlassert (x<(sint32)width);
00758 nlassert (y>=0);
00759 nlassert (y<(sint32)height);
00760 }
00761 }
00762
00763 // Next one
00764 ite++;
00765 }
00766
00767 // Merge the two set
00768 ite = setCell2.begin();
00769 while (ite != setCell2.end())
00770 {
00771 // Merge
00772 setCell.insert (*ite);
00773
00774 // Next element
00775 ite++;
00776 }
00777
00778 // Done, fill the array
00779 ite = setCell.begin();
00780 while (ite != setCell.end())
00781 {
00782 // Merge
00783 mask[ite->first+ite->second*width] = true;
00784
00785 // Next element
00786 ite++;
00787 }
00788 }
|
|
||||||||||||||||
|
Return the interger index of a snappable value.
Definition at line 93 of file zone_template.cpp. References nlverify, sint32, and value. Referenced by build().
|
|
||||||||||||||||
|
Return true if this value is snapped.
Definition at line 84 of file zone_template.cpp. References snapOnGrid(), and value. Referenced by build().
00085 {
00086 // Snapped
00087 float snapped = value;
00088 return snapOnGrid (snapped, resolution, snap);
00089 }
|
|
|
Serialisation.
Definition at line 644 of file zone_template.cpp.
00645 {
00646 // open an XML node
00647 s.xmlPush ("LIGO_ZONE_TEMPLATE");
00648
00649 // An header file
00650 s.serialCheck (string ("LigoZoneTemplate") );
00651
00652 // Node for the boundaries
00653 s.xmlPush ("EDGES");
00654
00655 // Serial the Vertices
00656 s.serialCont (_Edges);
00657
00658 // Node for the boundaries
00659 s.xmlPop ();
00660
00661 // Close the node
00662 s.xmlPop ();
00663 }
|
|
||||||||||||
|
Round a value on the snap resolution.
Definition at line 44 of file zone_template.cpp. References value.
00045 {
00046 // Snap it
00047 value = snap * (float) floor ( (value / snap) + 0.5f );
00048 }
|
|
||||||||||||||||
|
Snap a value on the grid.
Definition at line 52 of file zone_template.cpp. References nlassert, and value. Referenced by isSnapedOnGrid().
00053 {
00054 // Calc the floor
00055 float _floor = (float) ( resolution * floor (value / resolution) );
00056 nlassert (_floor<=value);
00057
00058 // Calc the remainder
00059 float remainder = value - _floor;
00060 //nlassert ( (remainder>=0) && (remainder<resolution) );
00061
00062 // Check the snape
00063 if ( remainder <= snap )
00064 {
00065 // Flag it
00066 value = _floor;
00067
00068 // Floor is good
00069 return true;
00070 }
00071 else if ( (resolution - remainder) <= snap )
00072 {
00073 // Flag it
00074 value = _floor + resolution;
00075
00076 // Floor + resolution is good
00077 return true;
00078 }
00079 return false;
00080 }
|
|
|
Vertex array.
Definition at line 88 of file zone_template.h. Referenced by build(), getEdges(), getMask(), and serial(). |
1.3.6