#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(). |