# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

primitive.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "nel/ligo/primitive.h"
00027 #include "nel/misc/i_xml.h"
00028 
00029 using namespace NLMISC;
00030 using namespace std;
00031 
00032 #define NLLIGO_PRIMITVE_VERSION 0
00033 
00034 namespace NLLIGO
00035 {
00036 
00037 // ***************************************************************************
00038 // XML helpers
00039 // ***************************************************************************
00040 
00041 void Error (const char *filename, const char *format, ...)
00042 {
00043         va_list args;
00044         va_start( args, format );
00045         char buffer[1024];
00046         sint ret = vsnprintf( buffer, 1024, format, args );
00047         va_end( args );
00048 
00049         nlwarning ("In File (%s) %s", filename, buffer);
00050 }
00051 
00052 // ***************************************************************************
00053 
00054 void XMLError (xmlNodePtr xmlNode, const char *filename, const char *format, ... )
00055 {
00056         va_list args;
00057         va_start( args, format );
00058         char buffer[1024];
00059         sint ret = vsnprintf( buffer, 1024, format, args );
00060         va_end( args );
00061 
00062         Error (filename, "node (%s), line (%d) : %s", xmlNode->name, (int)xmlNode->content, buffer);
00063 }
00064 
00065 
00066 // ***************************************************************************
00067 
00068 xmlNodePtr GetFirstChildNode (xmlNodePtr xmlNode, const char *filename, const char *childName)
00069 {
00070         // Call the CIXml version
00071         xmlNodePtr result;
00072         if ((result = CIXml::getFirstChildNode (xmlNode, childName)))
00073         {
00074                 return result;
00075         }
00076         else
00077         {
00078                 // Output a formated error
00079                 XMLError (xmlNode, filename, "Can't find XML node named (%s)", childName);
00080                 return NULL;
00081         }
00082 }
00083 
00084 // ***************************************************************************
00085 
00086 bool GetPropertyString (string &result, const char *filename, xmlNodePtr xmlNode, const char *propName)
00087 {
00088         // Call the CIXml version
00089         if (!CIXml::getPropertyString (result, xmlNode, propName))
00090         {
00091                 // Output a formated error
00092                 XMLError (xmlNode, filename, "Can't find XML node property (%s)", propName);
00093                 return false;
00094         }
00095         return true;
00096 }
00097 
00098 // ***************************************************************************
00099 
00100 bool ReadFloat (const char *propName, float &result, const char *filename, xmlNodePtr xmlNode)
00101 {
00102         string value;
00103         if (GetPropertyString (value, filename, xmlNode, propName))
00104         {
00105                 result = (float)atof (value.c_str ());
00106                 return true;
00107         }
00108         return false;
00109 }
00110 
00111 // ***************************************************************************
00112 
00113 bool ReadVector (CPrimVector &point, const char *filename, xmlNodePtr xmlNode)
00114 {
00115         CPrimVector pos;
00116         if (ReadFloat ("X", pos.x, filename, xmlNode))
00117         {
00118                 if (ReadFloat ("Y", pos.y, filename, xmlNode))
00119                 {
00120                         if (ReadFloat ("Z", pos.z, filename, xmlNode))
00121                         {
00122                                 pos.Selected = false;
00123                                 string result;
00124                                 if (CIXml::getPropertyString (result, xmlNode, "SELECTED"))
00125                                 {
00126                                         if (result == "true")
00127                                                 pos.Selected = true;
00128                                 }
00129                                 point = pos;
00130                                 return true;
00131                         }
00132                 }
00133         }
00134         return false;
00135 }
00136 
00137 // ***************************************************************************
00138 
00139 void WriteVector (const CPrimVector &point, xmlNodePtr xmlNode)
00140 {
00141         // Set properties
00142         xmlSetProp (xmlNode, (const xmlChar*)"X", (const xmlChar*)(toString (point.x).c_str ()));
00143         xmlSetProp (xmlNode, (const xmlChar*)"Y", (const xmlChar*)(toString (point.y).c_str ()));
00144         xmlSetProp (xmlNode, (const xmlChar*)"Z", (const xmlChar*)(toString (point.z).c_str ()));
00145         if (point.Selected)
00146                 xmlSetProp (xmlNode, (const xmlChar*)"SELECTED", (const xmlChar*)"true");
00147 }
00148 
00149 // ***************************************************************************
00150 
00151 void WriteFloat (const char *propName, float value, xmlNodePtr xmlNode)
00152 {
00153         // Set properties
00154         xmlSetProp (xmlNode, (const xmlChar*)propName, (const xmlChar*)(toString (value).c_str ()));
00155 }
00156 
00157 // ***************************************************************************
00158 
00159 bool GetNodeString (string &result, const char *filename, xmlNodePtr xmlNode, const char *nodeName)
00160 {
00161         // Look for the node
00162         xmlNodePtr node = CIXml::getFirstChildNode (xmlNode, nodeName);
00163         if (!node)
00164         {
00165                 XMLError (xmlNode, filename, "Can't find XML node named (%s)", nodeName);
00166                 return false;
00167         }
00168         
00169         // Get the node string
00170         if (!CIXml::getContentString (result, node))
00171         {
00172                 XMLError (xmlNode, filename, "Can't find any text in the node named (%s)", nodeName);
00173                 return false;
00174         }
00175 
00176         return true;
00177 }
00178 
00179 // ***************************************************************************
00180 
00181 bool GetContentString (string &result, const char *filename, xmlNodePtr xmlNode)
00182 {
00183         // Get the node string
00184         if (!CIXml::getContentString (result, xmlNode))
00185         {
00186                 XMLError (xmlNode, filename, "Can't find any text in the node");
00187                 return false;
00188         }
00189 
00190         return true;
00191 }
00192 
00193 // ***************************************************************************
00194 // CPropertyString
00195 // ***************************************************************************
00196 
00197 CPropertyString::CPropertyString (const char *str)
00198 {
00199         String = str;
00200 }
00201 
00202 // ***************************************************************************
00203 // CPropertyStringArray
00204 // ***************************************************************************
00205 
00206 CPropertyStringArray::CPropertyStringArray (const std::vector<std::string> &stringArray)
00207 {
00208         StringArray = stringArray;
00209 }
00210 
00211 // ***************************************************************************
00212 
00213 void CPrimPoint::serial (IStream &f)
00214 {
00215         f.xmlPushBegin ("POINT");
00216 
00217         f.xmlSetAttrib ("NAME");
00218         f.serial (Name);
00219         f.xmlSetAttrib ("LAYER");
00220         f.serial (Layer);
00221         f.xmlPushEnd ();
00222 
00223         f.serial (Point);
00224 
00225         if (f.isReading ())
00226         {
00227                 Angle = 0;
00228         }
00229 
00230         f.xmlPop ();
00231 }
00232 
00233 // ***************************************************************************
00234 void CPrimPath::serial (IStream &f)
00235 {
00236         f.xmlPushBegin ("PATH");
00237         
00238         f.xmlSetAttrib ("NAME");
00239         f.serial (Name);
00240         f.xmlSetAttrib ("LAYER");
00241         f.serial (Layer);
00242         f.xmlPushEnd ();
00243 
00244         f.serialCont (VPoints);
00245 
00246         f.xmlPop ();
00247 }
00248 
00249 // ***************************************************************************
00250 
00251 bool CPrimZone::contains (const NLMISC::CVector &v, const std::vector<CPrimVector> &points)
00252 {
00253         uint32 i;
00254         CVector vMin, vMax;
00255 
00256         // Point or line can't contains !
00257         if (points.size() < 3)
00258                 return false;
00259         
00260         // Get the bounding rectangle of the zone
00261         vMax = vMin = points[0];
00262         for (i = 0; i < points.size(); ++i)
00263         {
00264                 if (vMin.x > points[i].x)
00265                         vMin.x = points[i].x;
00266                 if (vMin.y > points[i].y)
00267                         vMin.y = points[i].y;
00268 
00269                 if (vMax.x < points[i].x)
00270                         vMax.x = points[i].x;
00271                 if (vMax.y < points[i].y)
00272                         vMax.y = points[i].y;
00273         }
00274 
00275         if ((v.x < vMin.x) || (v.y < vMin.y) || (v.x > vMax.x) || (v.y > vMax.y))
00276                 return false;
00277 
00278         uint32 nNbIntersection = 0;
00279         for (i = 0; i < points.size(); ++i)
00280         {
00281                 const CVector &p1 = points[i];
00282                 const CVector &p2 = points[(i+1)%points.size()];
00283 
00284                 if (((p1.y-v.y) < 0.0)&&((p2.y-v.y) < 0.0))
00285                         continue;
00286                 if (((p1.y-v.y) > 0.0)&&((p2.y-v.y) > 0.0))
00287                         continue;
00288                 float xinter = p1.x + (p2.x-p1.x) * ((v.y-p1.y)/(p2.y-p1.y));
00289                 if (xinter > v.x)
00290                         ++nNbIntersection;
00291         }
00292         if ((nNbIntersection&1) == 1) // odd intersections so the vertex is inside
00293                 return true;
00294         else
00295                 return false;
00296 }
00297 
00298 // ***************************************************************************
00299 
00300 bool CPrimZone::contains (const NLMISC::CVector &v, const std::vector<NLMISC::CVector> &points)
00301 {
00302         uint32 i;
00303         CVector vMin, vMax;
00304 
00305         // Point or line can't contains !
00306         if (points.size() < 3)
00307                 return false;
00308         
00309         // Get the bounding rectangle of the zone
00310         vMax = vMin = points[0];
00311         for (i = 0; i < points.size(); ++i)
00312         {
00313                 if (vMin.x > points[i].x)
00314                         vMin.x = points[i].x;
00315                 if (vMin.y > points[i].y)
00316                         vMin.y = points[i].y;
00317 
00318                 if (vMax.x < points[i].x)
00319                         vMax.x = points[i].x;
00320                 if (vMax.y < points[i].y)
00321                         vMax.y = points[i].y;
00322         }
00323 
00324         if ((v.x < vMin.x) || (v.y < vMin.y) || (v.x > vMax.x) || (v.y > vMax.y))
00325                 return false;
00326 
00327         uint32 nNbIntersection = 0;
00328         for (i = 0; i < points.size(); ++i)
00329         {
00330                 const CVector &p1 = points[i];
00331                 const CVector &p2 = points[(i+1)%points.size()];
00332 
00333                 if (((p1.y-v.y) < 0.0)&&((p2.y-v.y) < 0.0))
00334                         continue;
00335                 if (((p1.y-v.y) > 0.0)&&((p2.y-v.y) > 0.0))
00336                         continue;
00337                 float xinter = p1.x + (p2.x-p1.x) * ((v.y-p1.y)/(p2.y-p1.y));
00338                 if (xinter > v.x)
00339                         ++nNbIntersection;
00340         }
00341         if ((nNbIntersection&1) == 1) // odd intersections so the vertex is inside
00342                 return true;
00343         else
00344                 return false;
00345 }
00346 
00347 // ***************************************************************************
00348 // CPrimNode
00349 // ***************************************************************************
00350 
00351 bool CPrimNode::read (xmlNodePtr xmlNode, const char *filename, uint version)
00352 {
00353         return IPrimitive::read (xmlNode, filename, version);
00354 }
00355 
00356 // ***************************************************************************
00357 
00358 void CPrimNode::write (xmlNodePtr xmlNode, const char *filename) const
00359 {
00360         // Set the type
00361         xmlSetProp (xmlNode, (const xmlChar*)"TYPE", (const xmlChar*)"node");
00362 
00363         IPrimitive::write (xmlNode, filename);
00364 }
00365 
00366 // ***************************************************************************
00367 
00368 uint CPrimNode::getNumVector () const
00369 {
00370         return 0;
00371 }
00372 
00373 // ***************************************************************************
00374 
00375 const CPrimVector *CPrimNode::getPrimVector () const
00376 {
00377         return NULL;
00378 }
00379 
00380 // ***************************************************************************
00381 
00382 CPrimVector     *CPrimNode::getPrimVector ()
00383 {
00384         return NULL;
00385 }
00386 
00387 // ***************************************************************************
00388 // CPrimNode
00389 // ***************************************************************************
00390 
00391 /*void CPrimNode::operator= (const CPrimNode &node)
00392 {
00393         // Copy the IPrimitive
00394         IPrimitive::operator= (node);
00395 }
00396 
00397 // ***************************************************************************
00398 
00399 void CPrimPoint::operator= (const CPrimPoint &node)
00400 {
00401         // Copy the IPrimitive
00402         IPrimitive::operator= (node);
00403 }
00404 
00405 // ***************************************************************************
00406 
00407 void CPrimPath::operator= (const CPrimPath &node)
00408 {
00409         // Copy the IPrimitive
00410 }
00411 
00412 // ***************************************************************************
00413 
00414 void CPrimZone::operator= (const CPrimZone &node)
00415 {
00416         // Copy the IPrimitive
00417         IPrimitive::operator= (node);
00418 }
00419 */
00420 
00421 // ***************************************************************************
00422 
00423 uint CPrimPoint::getNumVector () const
00424 {
00425         return 1;
00426 }
00427 
00428 // ***************************************************************************
00429 
00430 const CPrimVector *CPrimPoint::getPrimVector () const
00431 {
00432         return &Point;
00433 }
00434 
00435 // ***************************************************************************
00436 
00437 CPrimVector     *CPrimPoint::getPrimVector ()
00438 {
00439         return &Point;
00440 }
00441 
00442 // ***************************************************************************
00443 
00444 bool CPrimPoint::read (xmlNodePtr xmlNode, const char *filename, uint version)
00445 {
00446         // Read points
00447         xmlNodePtr ptNode = GetFirstChildNode (xmlNode, filename, "PT");
00448         if (ptNode)
00449         {
00450                 // Read a vector
00451                 if (!ReadVector (Point, filename, ptNode))
00452                         return false;
00453 
00454                 ptNode = GetFirstChildNode (xmlNode, filename, "ANGLE");
00455                 if (ptNode)
00456                 {
00457                         // Read a float
00458                         if (!ReadFloat ("VALUE", Angle, filename, ptNode))
00459                                 return false;
00460                 }
00461                 else
00462                         Angle = 0;
00463         }
00464         else
00465         {
00466                 return false;
00467         }
00468 
00469         return IPrimitive::read (xmlNode, filename, version);
00470 }
00471 
00472 // ***************************************************************************
00473 
00474 void CPrimPoint::write (xmlNodePtr xmlNode, const char *filename) const
00475 {
00476         // Set the type
00477         xmlSetProp (xmlNode, (const xmlChar*)"TYPE", (const xmlChar*)"point");
00478 
00479         // Save the point
00480         xmlNodePtr ptNode = xmlNewChild ( xmlNode, NULL, (const xmlChar*)"PT", NULL);
00481         WriteVector (Point, ptNode);
00482 
00483         // Save the angle
00484         if (Angle != 0)
00485         {
00486                 xmlNodePtr ptNode = xmlNewChild ( xmlNode, NULL, (const xmlChar*)"ANGLE", NULL);
00487                 WriteFloat ("VALUE", Angle, ptNode);
00488         }
00489 
00490         IPrimitive::write (xmlNode, filename);
00491 }
00492 
00493 // ***************************************************************************
00494 // CPrimPath
00495 // ***************************************************************************
00496 
00497 uint CPrimPath::getNumVector () const
00498 {
00499         return VPoints.size ();
00500 }
00501 
00502 // ***************************************************************************
00503 
00504 const CPrimVector *CPrimPath::getPrimVector () const
00505 {
00506         return &(VPoints[0]);
00507 }
00508 
00509 // ***************************************************************************
00510 
00511 CPrimVector     *CPrimPath::getPrimVector ()
00512 {
00513         return &(VPoints[0]);
00514 }
00515 
00516 // ***************************************************************************
00517 
00518 bool CPrimPath::read (xmlNodePtr xmlNode, const char *filename, uint version)
00519 {
00520         // Read points
00521         VPoints.clear ();
00522         VPoints.reserve (CIXml::countChildren (xmlNode, "PT"));
00523         xmlNodePtr ptNode = CIXml::getFirstChildNode (xmlNode, "PT");
00524         if (ptNode)
00525         {
00526                 do
00527                 {
00528                         // Read a vector
00529                         VPoints.push_back (CPrimVector ());
00530                         if (!ReadVector (VPoints.back (), filename, ptNode))
00531                                 return false;
00532                 }
00533                 while ((ptNode = CIXml::getNextChildNode (ptNode, "PT")));
00534         }
00535 
00536         return IPrimitive::read (xmlNode, filename, version);
00537 }
00538 
00539 // ***************************************************************************
00540 
00541 void CPrimPath::write (xmlNodePtr xmlNode, const char *filename) const
00542 {
00543         // Set the type
00544         xmlSetProp (xmlNode, (const xmlChar*)"TYPE", (const xmlChar*)"path");
00545 
00546         // Save the points
00547         for (uint i=0; i<VPoints.size (); i++)
00548         {
00549                 xmlNodePtr ptNode = xmlNewChild ( xmlNode, NULL, (const xmlChar*)"PT", NULL);
00550                 WriteVector (VPoints[i], ptNode);
00551         }
00552 
00553         IPrimitive::write (xmlNode, filename);
00554 }
00555 
00556 // ***************************************************************************
00557 // CPrimZone
00558 // ***************************************************************************
00559 
00560 uint CPrimZone::getNumVector () const
00561 {
00562         return VPoints.size ();
00563 }
00564 
00565 // ***************************************************************************
00566 
00567 const CPrimVector *CPrimZone::getPrimVector () const
00568 {
00569         return &(VPoints[0]);
00570 }
00571 
00572 // ***************************************************************************
00573 
00574 CPrimVector     *CPrimZone::getPrimVector ()
00575 {
00576         return &(VPoints[0]);
00577 }
00578 
00579 // ***************************************************************************
00580 
00581 bool CPrimZone::read (xmlNodePtr xmlNode, const char *filename, uint version)
00582 {
00583         // Read points
00584         VPoints.clear ();
00585         VPoints.reserve (CIXml::countChildren (xmlNode, "PT"));
00586         xmlNodePtr ptNode = CIXml::getFirstChildNode (xmlNode, "PT");
00587         if (ptNode)
00588         {
00589                 do
00590                 {
00591                         // Read a vector
00592                         VPoints.push_back (CPrimVector ());
00593                         if (!ReadVector (VPoints.back (), filename, ptNode))
00594                                 return false;
00595                 }
00596                 while ((ptNode = CIXml::getNextChildNode (ptNode, "PT")));
00597         }
00598 
00599         return IPrimitive::read (xmlNode, filename, version);
00600 }
00601 
00602 // ***************************************************************************
00603 
00604 void CPrimZone::write (xmlNodePtr xmlNode, const char *filename) const
00605 {
00606         // Set the type
00607         xmlSetProp (xmlNode, (const xmlChar*)"TYPE", (const xmlChar*)"zone");
00608 
00609         // Save the points
00610         for (uint i=0; i<VPoints.size (); i++)
00611         {
00612                 xmlNodePtr ptNode = xmlNewChild ( xmlNode, NULL, (const xmlChar*)"PT", NULL);
00613                 WriteVector (VPoints[i], ptNode);
00614         }
00615 
00616         IPrimitive::write (xmlNode, filename);
00617 }
00618 
00619 // ***************************************************************************
00620 
00621 bool CPrimZone::contains (const NLMISC::CVector &v, const std::vector<CPrimVector> &points, float &distance, NLMISC::CVector &nearPos, bool isPath)
00622 {
00623         uint32 i;
00624         CVector vMin, vMax;
00625         float nearest = FLT_MAX;
00626         CVector pos;
00627 
00628         // Point or line can't contains !
00629         if (points.size() < 3 || isPath)
00630         {
00631                 // only compute the distance.
00632                 if (points.size() == 1)
00633                 {
00634                         distance = (points[0] - v).norm();
00635                         nearPos = points[0];
00636                 }
00637                 else if (points.size() == 2)
00638                 {
00639                         distance = getSegmentDist(v, points[0], points[1], nearPos);
00640                 }
00641                 else
00642                 {
00643                         // compute nearest segment
00644                         for (i = 0; i < points.size()-1; ++i)
00645                         {
00646                                 const CVector &p1 = points[i];
00647                                 const CVector &p2 = points[i+1];
00648 
00649                                 float dist = getSegmentDist(v, p1, p2, pos);
00650                                 if( dist < nearest)
00651                                 {
00652                                         nearest = dist;
00653                                         nearPos = pos;
00654                                 }
00655                         }
00656                         distance = nearest;
00657                 }
00658                 return false;
00659         }
00660         
00661         // Get the bounding rectangle of the zone
00662         vMax = vMin = points[0];
00663         for (i = 0; i < points.size(); ++i)
00664         {
00665                 vMin.x = min(vMin.x, points[i].x);
00666                 vMin.y = min(vMin.y, points[i].y);
00667                 vMax.x = max(vMax.x, points[i].x);
00668                 vMax.y = max(vMax.y, points[i].y);
00669         }
00670 
00671         if ((v.x < vMin.x) || (v.y < vMin.y) || (v.x > vMax.x) || (v.y > vMax.y))
00672         {
00673                 // find the nearest distance of all segment
00674                 for (uint i=0; i<points.size(); ++i)
00675                 {
00676                         float dist = getSegmentDist(v, points[i], points[(i+1) % points.size()], pos);
00677 
00678                         if (dist < nearest)
00679                         {
00680                                 nearest = dist;
00681                                 nearPos = pos;
00682                         }
00683                 }
00684                 distance = nearest;
00685                 return false;
00686         }
00687 
00688         uint32 nNbIntersection = 0;
00689         for (i = 0; i < points.size(); ++i)
00690         {
00691                 const CVector &p1 = points[i];
00692                 const CVector &p2 = points[(i+1)%points.size()];
00693 
00694                 float dist = getSegmentDist(v, p1, p2, pos);
00695                 if( dist < nearest)
00696                 {
00697                         nearest = dist;
00698                         nearPos = pos;
00699                 }
00700 
00701                 if (((p1.y-v.y) < 0.0)&&((p2.y-v.y) < 0.0))
00702                         continue;
00703                 if (((p1.y-v.y) > 0.0)&&((p2.y-v.y) > 0.0))
00704                         continue;
00705                 float xinter = p1.x + (p2.x-p1.x) * ((v.y-p1.y)/(p2.y-p1.y));
00706                 if (xinter > v.x)
00707                         ++nNbIntersection;
00708         }
00709 
00710         distance = nearest;
00711         if ((nNbIntersection&1) == 1) // odd intersections so the vertex is inside
00712                 return true;
00713         else
00714                 return false;
00715 }
00716 
00717 // ***************************************************************************
00718 
00719 bool CPrimZone::contains (const NLMISC::CVector &v, const std::vector<CVector> &points, float &distance, NLMISC::CVector &nearPos, bool isPath)
00720 {
00721         uint32 i;
00722         CVector vMin, vMax;
00723         float nearest = FLT_MAX;
00724         CVector pos;
00725 
00726         // Point or line can't contains !
00727         if (points.size() < 3 || isPath)
00728         {
00729                 // only compute the distance.
00730                 if (points.size() == 1)
00731                 {
00732                         distance = (points[0] - v).norm();
00733                         nearPos = points[0];
00734                 }
00735                 else if (points.size() == 2)
00736                 {
00737                         distance = getSegmentDist(v, points[0], points[1], nearPos);
00738                 }
00739                 else
00740                 {
00741                         // compute nearest segment
00742                         for (i = 0; i < points.size()-1; ++i)
00743                         {
00744                                 const CVector &p1 = points[i];
00745                                 const CVector &p2 = points[i+1];
00746 
00747                                 float dist = getSegmentDist(v, p1, p2, pos);
00748                                 if( dist < nearest)
00749                                 {
00750                                         nearest = dist;
00751                                         nearPos = pos;
00752                                 }
00753                         }
00754                         distance = nearest;
00755                 }
00756                 return false;
00757         }
00758         
00759         // Get the bounding rectangle of the zone
00760         vMax = vMin = points[0];
00761         for (i = 0; i < points.size(); ++i)
00762         {
00763                 vMin.x = min(vMin.x, points[i].x);
00764                 vMin.y = min(vMin.y, points[i].y);
00765                 vMax.x = max(vMax.x, points[i].x);
00766                 vMax.y = max(vMax.y, points[i].y);
00767         }
00768 
00769         if ((v.x < vMin.x) || (v.y < vMin.y) || (v.x > vMax.x) || (v.y > vMax.y))
00770         {
00771                 // find the nearest distance of all segment
00772                 for (uint i=0; i<points.size(); ++i)
00773                 {
00774                         float dist = getSegmentDist(v, points[i], points[(i+1) % points.size()], pos);
00775 
00776                         if (dist < nearest)
00777                         {
00778                                 nearest = dist;
00779                                 nearPos = pos;
00780                         }
00781                 }
00782                 distance = nearest;
00783                 return false;
00784         }
00785 
00786         uint32 nNbIntersection = 0;
00787         for (i = 0; i < points.size(); ++i)
00788         {
00789                 const CVector &p1 = points[i];
00790                 const CVector &p2 = points[(i+1)%points.size()];
00791 
00792                 float dist = getSegmentDist(v, p1, p2, pos);
00793                 if( dist < nearest)
00794                 {
00795                         nearest = dist;
00796                         nearPos = pos;
00797                 }
00798 
00799                 if (((p1.y-v.y) < 0.0)&&((p2.y-v.y) < 0.0))
00800                         continue;
00801                 if (((p1.y-v.y) > 0.0)&&((p2.y-v.y) > 0.0))
00802                         continue;
00803                 float xinter = p1.x + (p2.x-p1.x) * ((v.y-p1.y)/(p2.y-p1.y));
00804                 if (xinter > v.x)
00805                         ++nNbIntersection;
00806         }
00807 
00808         distance = nearest;
00809         if ((nNbIntersection&1) == 1) // odd intersections so the vertex is inside
00810                 return true;
00811         else
00812                 return false;
00813 }
00814 
00815 // ***************************************************************************
00816 
00817 float CPrimZone::getSegmentDist(const NLMISC::CVector v, const NLMISC::CVector &p1, const NLMISC::CVector &p2, NLMISC::CVector &nearPos)
00818 {
00819         // too point, compute distance to the segment.
00820         CVector V = (p2-p1).normed();
00821         float t = ((v-p1)*V)/(p2-p1).norm();
00822         float distance;
00823         if (t < 0.0f)
00824         {
00825                 nearPos = p1;
00826                 distance = (p1-v).norm();
00827         }
00828         else if (t > 1.0f)
00829         {
00830                 nearPos = p2;
00831                 distance = (p2-v).norm();
00832         }
00833         else
00834         {
00835                 nearPos = p1 + t*(p2-p1);
00836                 distance = (v-nearPos).norm();
00837         }
00838 
00839         return distance;
00840 }
00841 
00842 
00843 
00844 // ***************************************************************************
00845 void CPrimZone::serial (IStream &f)
00846 {
00847         f.xmlPushBegin ("ZONE");
00848         
00849         f.xmlSetAttrib ("NAME");
00850         f.serial (Name);
00851         f.xmlSetAttrib ("LAYER");
00852         f.serial (Layer);
00853         f.xmlPushEnd ();
00854 
00855         f.serialCont (VPoints);
00856 
00857         f.xmlPop ();
00858 }
00859 
00860 // ***************************************************************************
00861 void CPrimRegion::serial (IStream &f)
00862 {
00863         f.xmlPushBegin ("REGION");
00864         
00865         f.xmlSetAttrib ("NAME");
00866         f.serial (Name);
00867 
00868         f.xmlPushEnd();
00869 
00870         sint version = 2;
00871         version = f.serialVersion (version);
00872         string check = "REGION";
00873         f.serialCheck (check);
00874 
00875         f.xmlPush ("POINTS");
00876                 f.serialCont (VPoints);
00877         f.xmlPop ();
00878         f.xmlPush ("PATHES");
00879                 f.serialCont (VPaths);
00880         f.xmlPop ();
00881         f.xmlPush ("ZONES");
00882                 f.serialCont (VZones);
00883         f.xmlPop ();
00884 
00885         if (version > 1)
00886         {
00887                 f.xmlPush ("HIDEPOINTS");
00888                         f.serialCont (VHidePoints);
00889                 f.xmlPop ();
00890                 f.xmlPush ("HIDEZONES");
00891                         f.serialCont (VHideZones);
00892                 f.xmlPop ();
00893                 f.xmlPush ("HIDEPATHS");
00894                         f.serialCont (VHidePaths);
00895                 f.xmlPop ();
00896         }
00897         else
00898         {
00899                 VHidePoints.resize      (VPoints.size(), false);
00900                 VHideZones.resize       (VZones.size(), false);
00901                 VHidePaths.resize       (VPaths.size(), false);
00902         }
00903 }
00904 
00905 // ***************************************************************************
00906 // IPrimitive
00907 // ***************************************************************************
00908 
00909 IPrimitive::IPrimitive (const IPrimitive &node)
00910 {
00911         _Parent = NULL;
00912         IPrimitive::operator= (node);
00913 }
00914 
00915 // ***************************************************************************
00916 
00917 IPrimitive*     IPrimitive::copy () const
00918 {
00919         // What is this primitive ?
00920 
00921         // The copy
00922         IPrimitive *theCopy;
00923 
00924         // Is it a prim node ?
00925         const CPrimNode *primNode = dynamic_cast<const CPrimNode*>(this);
00926         if (primNode)
00927         {
00928                 theCopy = new CPrimNode;
00929                 *(CPrimNode*)theCopy = *(const CPrimNode*)this;
00930         }
00931         else
00932         {
00933                 // Is it a point node ?
00934                 const CPrimPoint *pointNode = dynamic_cast<const CPrimPoint*>(this);
00935                 if (pointNode)
00936                 {
00937                         theCopy = new CPrimPoint;
00938                         *(CPrimPoint*)theCopy = *(const CPrimPoint*)this;
00939                 }
00940                 else
00941                 {
00942                         // Is it a path node ?
00943                         const CPrimPath *pathNode = dynamic_cast<const CPrimPath*>(this);
00944                         if (pathNode)
00945                         {
00946                                 theCopy = new CPrimPath;
00947                                 *(CPrimPath*)theCopy = *(const CPrimPath*)this;
00948                         }
00949                         else
00950                         {
00951                                 // Is it a path node ?
00952                                 const CPrimZone *zoneNode = dynamic_cast<const CPrimZone*>(this);
00953                                 nlverify (zoneNode);
00954                                 theCopy = new CPrimZone;
00955                                 *(CPrimZone*)theCopy = *(const CPrimZone*)this;
00956                         }
00957                 }
00958         }
00959 
00960 
00961         // Copy children
00962         theCopy->_Children.resize (_Children.size ());
00963         for (uint child = 0; child < _Children.size (); child++)
00964         {
00965                 // Copy the child
00966                 theCopy->_Children[child] = _Children[child]->copy ();
00967 
00968                 // Set the parent
00969                 theCopy->_Children[child]->_Parent = theCopy;
00970         }
00971 
00972         // Copy properties
00973         std::map<std::string, IProperty*>::const_iterator ite = _Properties.begin ();
00974         while (ite != _Properties.end ())
00975         {
00976                 // Get the property
00977                 CPropertyString *propString = dynamic_cast<CPropertyString *>(ite->second);
00978                 if (propString)
00979                 {
00980                         // New property
00981                         CPropertyString *newProp = new CPropertyString ();
00982                         *newProp = *propString;
00983                         theCopy->_Properties.insert (std::map<std::string, IProperty*>::value_type (ite->first, newProp));
00984                 }
00985                 else
00986                 {
00987                         CPropertyStringArray *propStringArray = dynamic_cast<CPropertyStringArray *>(ite->second);
00988                         if (propStringArray)
00989                         {
00990                                 // New property
00991                                 CPropertyStringArray *newProp = new CPropertyStringArray ();
00992                                 *newProp = *propStringArray;
00993                                 theCopy->_Properties.insert (std::map<std::string, IProperty*>::value_type (ite->first, newProp));
00994                         }
00995                         else
00996                         {
00997                                 CPropertyColor *propColor = dynamic_cast<CPropertyColor *>(ite->second);
00998                                 nlverify (propColor);
00999 
01000                                 // New property
01001                                 CPropertyColor *newProp = new CPropertyColor ();
01002                                 *newProp = *propColor;
01003                                 theCopy->_Properties.insert (std::map<std::string, IProperty*>::value_type (ite->first, newProp));
01004                         }
01005                 }
01006 
01007                 ite++;
01008         }
01009 
01010         return theCopy;
01011 }
01012 
01013 // ***************************************************************************
01014 
01015 void IPrimitive::operator= (const IPrimitive &node)
01016 {
01017         // Clean dest
01018         removeChildren ();
01019         removeProperties ();
01020 
01021         // Copy children
01022         _Children.resize (node._Children.size ());
01023         for (uint child = 0; child < node._Children.size (); child++)
01024         {
01025                 // Copy the child
01026                 _Children[child] = node._Children[child]->copy ();
01027 
01028                 // Set the parent
01029                 _Children[child]->_Parent = this;
01030         }
01031 
01032         // Copy properties
01033         std::map<std::string, IProperty*>::const_iterator ite = node._Properties.begin ();
01034         while (ite != node._Properties.end ())
01035         {
01036                 // Get the property
01037                 CPropertyString *propString = dynamic_cast<CPropertyString *>(ite->second);
01038                 if (propString)
01039                 {
01040                         // New property
01041                         CPropertyString *newProp = new CPropertyString ();
01042                         *newProp = *propString;
01043                         _Properties.insert (std::map<std::string, IProperty*>::value_type (ite->first, newProp));
01044                 }
01045                 else
01046                 {
01047                         CPropertyStringArray *propStringArray = dynamic_cast<CPropertyStringArray *>(ite->second);
01048                         if (propStringArray)
01049                         {
01050                                 // New property
01051                                 CPropertyStringArray *newProp = new CPropertyStringArray ();
01052                                 *newProp = *propStringArray;
01053                                 _Properties.insert (std::map<std::string, IProperty*>::value_type (ite->first, newProp));
01054                         }
01055                         else
01056                         {
01057                                 CPropertyColor *propColor = dynamic_cast<CPropertyColor *>(ite->second);
01058                                 nlverify (propColor);
01059 
01060                                 // New property
01061                                 CPropertyColor *newProp = new CPropertyColor ();
01062                                 *newProp = *propColor;
01063                                 _Properties.insert (std::map<std::string, IProperty*>::value_type (ite->first, newProp));
01064                         }
01065                 }
01066 
01067                 ite++;
01068         }
01069 }
01070 
01071 // ***************************************************************************
01072 
01073 bool IPrimitive::getProperty (uint index, std::string &property_name, const IProperty *&result) const
01074 {
01075         // Look for the property
01076         std::map<std::string, IProperty*>::const_iterator ite = _Properties.begin ();
01077         while (ite != _Properties.end ())
01078         {
01079                 if (index == 0)
01080                 {
01081                         property_name = ite->first;
01082                         result = ite->second;
01083                         return true;
01084                 }
01085                 index--;
01086                 ite ++;
01087         }
01088         nlwarning ("NLLIGO::IPrimitive::getProperty : invalid index (index : %d, size : %d).", index, _Properties.size ());
01089         return false;
01090 }
01091 
01092 // ***************************************************************************
01093 
01094 bool IPrimitive::getProperty (uint index, std::string &property_name, IProperty *&result)
01095 {
01096         // Look for the property
01097         std::map<std::string, IProperty*>::iterator ite = _Properties.begin ();
01098         while (ite != _Properties.end ())
01099         {
01100                 if (index == 0)
01101                 {
01102                         property_name = ite->first;
01103                         result = ite->second;
01104                         return true;
01105                 }
01106                 index--;
01107                 ite ++;
01108         }
01109         nlwarning ("NLLIGO::IPrimitive::getProperty : invalid index (index : %d, size : %d).", index, _Properties.size ());
01110         return false;
01111 }
01112 
01113 // ***************************************************************************
01114 
01115 bool IPrimitive::getPropertyByName (const char *property_name, const IProperty *&result) const
01116 {
01117         // Look for the property
01118         std::map<std::string, IProperty*>::const_iterator ite = _Properties.find (property_name);
01119         if (ite != _Properties.end ())
01120         {
01121                 result = ite->second;
01122                 return true;
01123         }
01124         return false;
01125 }
01126 
01127 // ***************************************************************************
01128 
01129 bool IPrimitive::getPropertyByName (const char *property_name, IProperty *&result)
01130 {
01131         // Look for the property
01132         std::map<std::string, IProperty*>::iterator ite = _Properties.find (property_name);
01133         if (ite != _Properties.end ())
01134         {
01135                 result = ite->second;
01136                 return true;
01137         }
01138         return false;
01139 }
01140 
01141 // ***************************************************************************
01142 
01143 bool IPrimitive::getPropertyByName (const char *property_name, std::string *&result)
01144 {
01145         // Get the property
01146         IProperty *prop;
01147         if (getPropertyByName (property_name, prop))
01148         {
01149                 CPropertyString *strProp = dynamic_cast<CPropertyString *> (prop);
01150                 if (strProp)
01151                 {
01152                         result = &(strProp->String);
01153                         return true;
01154                 }
01155                 else
01156                 {
01157                         nlwarning ("NLLIGO::IPrimitive::getPropertyByName : property (%s) in not a string.", property_name);
01158                 }
01159         }
01160         return false;
01161 }
01162 
01163 // ***************************************************************************
01164 
01165 bool IPrimitive::getPropertyByName (const char *property_name, std::string &result) const
01166 {
01167         // Get the property
01168         const IProperty *prop;
01169         if (getPropertyByName (property_name, prop))
01170         {
01171                 const CPropertyString *strProp = dynamic_cast<const CPropertyString *> (prop);
01172                 if (strProp)
01173                 {
01174                         result = strProp->String;
01175                         return true;
01176                 }
01177                 else
01178                 {
01179                         nlwarning ("NLLIGO::IPrimitive::getPropertyByName : property (%s) in not a string.", property_name);
01180                 }
01181         }
01182         return false;
01183 }
01184 
01185 // ***************************************************************************
01186 
01187 bool IPrimitive::getPropertyByName (const char *property_name, std::vector<std::string> *&result)
01188 {
01189         // Get the property
01190         IProperty *prop;
01191         if (getPropertyByName (property_name, prop))
01192         {
01193                 CPropertyStringArray *strProp = dynamic_cast<CPropertyStringArray *> (prop);
01194                 if (strProp)
01195                 {
01196                         result = &(strProp->StringArray);
01197                         return true;
01198                 }
01199                 else
01200                 {
01201                         nlwarning ("NLLIGO::IPrimitive::getPropertyByName : property (%s) in not a string.", property_name);
01202                 }
01203         }
01204         return false;
01205 }
01206 
01207 // ***************************************************************************
01208 
01209 bool IPrimitive::getPropertyByName (const char *property_name, const std::vector<std::string> *&result) const
01210 {
01211         // Get the property
01212         IProperty *prop;
01213         if (getPropertyByName (property_name, prop))
01214         {
01215                 const CPropertyStringArray *strProp = dynamic_cast<const CPropertyStringArray *> (prop);
01216                 if (strProp)
01217                 {
01218                         result = &(strProp->StringArray);
01219                         return true;
01220                 }
01221                 else
01222                 {
01223                         nlwarning ("NLLIGO::IPrimitive::getPropertyByName : property (%s) in not a string.", property_name);
01224                 }
01225         }
01226         return false;
01227 }
01228 
01229 // ***************************************************************************
01230 
01231 bool IPrimitive::getPropertyByName (const char *property_name, NLMISC::CRGBA &result) const
01232 {
01233         // Get the property
01234         IProperty *prop;
01235         if (getPropertyByName (property_name, prop))
01236         {
01237                 const CPropertyColor *colorProp = dynamic_cast<const CPropertyColor *> (prop);
01238                 if (colorProp)
01239                 {
01240                         result = colorProp->Color;
01241                         return true;
01242                 }
01243                 else
01244                 {
01245                         nlwarning ("NLLIGO::IPrimitive::getPropertyByName : property (%s) in not a color.", property_name);
01246                 }
01247         }
01248         return false;
01249 }
01250 
01251 // ***************************************************************************
01252 
01253 bool IPrimitive::removeProperty (uint index)
01254 {
01255         // Look for the property
01256         std::map<std::string, IProperty*>::iterator ite = _Properties.begin ();
01257         while (ite != _Properties.end ())
01258         {
01259                 if (index == 0)
01260                 {
01261                         _Properties.erase (ite);
01262                         return true;
01263                 }
01264                 index--;
01265                 ite ++;
01266         }
01267         nlwarning ("NLLIGO::IPrimitive::removeProperty : invalid index (index : %d, size : %d).", index, _Properties.size ());
01268         return false;
01269 }
01270 
01271 // ***************************************************************************
01272 
01273 bool IPrimitive::removePropertyByName (const char *property_name)
01274 {
01275         // Look for the property
01276         std::map<std::string, IProperty*>::iterator ite = _Properties.find (property_name);
01277         if (ite != _Properties.end ())
01278         {
01279                 _Properties.erase (ite);
01280                 return true;
01281         }
01282         return false;
01283 }
01284 
01285 // ***************************************************************************
01286 
01287 void IPrimitive::removeProperties ()
01288 {
01289         std::map<std::string, IProperty*>::iterator ite = _Properties.begin ();
01290         while (ite != _Properties.end ())
01291         {
01292                 delete ite->second;
01293                 ite++;
01294         }
01295         _Properties.clear ();
01296 }
01297 
01298 // ***************************************************************************
01299 
01300 bool IPrimitive::getChild (const IPrimitive *&result, uint childId) const
01301 {
01302         if (childId < _Children.size ())
01303         {
01304                 result = _Children[childId];
01305                 return true;
01306         }
01307         else
01308         {
01309                 nlwarning ("NLLIGO::IPrimitive::getChild : invalid index (index : %d, size %d).", childId, _Children.size ());
01310         }
01311         return false;
01312 }
01313 
01314 // ***************************************************************************
01315 
01316 bool IPrimitive::getChild (IPrimitive *&result, uint childId)
01317 {
01318         if (childId < _Children.size ())
01319         {
01320                 result = _Children[childId];
01321                 return true;
01322         }
01323         else
01324         {
01325                 nlwarning ("NLLIGO::IPrimitive::getChild : invalid index (index : %d, size %d).", childId, _Children.size ());
01326         }
01327         return false;
01328 }
01329 
01330 // ***************************************************************************
01331 
01332 bool IPrimitive::removeChild (uint childId)
01333 {
01334         if (childId < _Children.size ())
01335         {
01336                 delete _Children[childId];
01337                 _Children.erase (_Children.begin()+childId);
01338                 return true;
01339         }
01340         else
01341         {
01342                 nlwarning ("NLLIGO::IPrimitive::removeChild : invalid index (index : %d, size %d).", childId, _Children.size ());
01343         }
01344         return false;
01345 }
01346 
01347 // ***************************************************************************
01348 
01349 void IPrimitive::removeChildren ()
01350 {
01351         // Erase children
01352         for (uint i=0; i<_Children.size (); i++)
01353         {
01354                 delete _Children[i];
01355         }
01356         _Children.clear ();
01357 }
01358 
01359 // ***************************************************************************
01360 
01361 bool IPrimitive::insertChild (IPrimitive *primitive, uint index)
01362 {
01363         // At the end ?
01364         if (index == AtTheEnd)
01365                 index = _Children.size ();
01366 
01367         // Index valid ?
01368         if (index>_Children.size ())
01369                 return false;
01370 
01371         // Insert
01372         _Children.insert (_Children.begin () + index, primitive);
01373 
01374         // Link to the parent
01375         primitive->_Parent = this;
01376 
01377         return true;
01378 }
01379 
01380 // ***************************************************************************
01381 
01382 IPrimitive::~IPrimitive ()
01383 {
01384         // Remove children
01385         removeChildren ();
01386 
01387         // Erase properties
01388         removeProperties ();
01389 }
01390 
01391 // ***************************************************************************
01392 
01393 bool IPrimitive::addPropertyByName (const char *property_name, IProperty *result)
01394 {
01395         bool inserted = _Properties.insert (std::map<std::string, IProperty*>::value_type (property_name, result)).second;
01396         if (inserted)
01397         {
01398                 return true;
01399         }
01400         return false;
01401 }
01402 
01403 // ***************************************************************************
01404 
01405 bool IPrimitive::read (xmlNodePtr xmlNode, const char *filename, uint version)
01406 {
01407         // Erase old properties
01408         _Properties.clear ();
01409 
01410         // Read the properties
01411         xmlNodePtr propNode;
01412         propNode = CIXml::getFirstChildNode (xmlNode, "PROPERTY");
01413         if (propNode)
01414         {
01415                 do
01416                 {
01417                         // Read the name
01418                         string name;
01419                         if (GetNodeString (name, filename, propNode, "NAME"))
01420                         {
01421                                 // Get the property type
01422                                 string type;
01423                                 if (GetPropertyString (type, filename, propNode, "TYPE"))
01424                                 {
01425                                         // The property
01426                                         IProperty *property = NULL;
01427 
01428                                         // Check the type
01429                                         if (type == "string")
01430                                         {
01431                                                 // Create a new property
01432                                                 CPropertyString *propertyString = new CPropertyString;
01433                                                 property = propertyString;
01434                                                 
01435                                                 // Read it
01436                                                 if (!GetNodeString (propertyString->String, filename, propNode, "STRING"))
01437                                                 {
01438                                                         return false;
01439                                                 }
01440                                         }
01441                                         else if (type == "string_array")
01442                                         {
01443                                                 // Create a new property
01444                                                 CPropertyStringArray *propertyStringArray = new CPropertyStringArray;
01445                                                 property = propertyStringArray;
01446 
01447                                                 // Read strings
01448                                                 xmlNodePtr stringNode;
01449                                                 propertyStringArray->StringArray.reserve (CIXml::countChildren (xmlNode, "STRING"));
01450                                                 stringNode = CIXml::getFirstChildNode (xmlNode, "STRING");
01451                                                 if (stringNode)
01452                                                 {
01453                                                         do
01454                                                         {
01455                                                                 // Add the string
01456                                                                 string content;
01457                                                                 GetContentString (content, filename, stringNode);
01458                                                                 propertyStringArray->StringArray.push_back (content);
01459                                                         }
01460                                                         while ((stringNode = CIXml::getNextChildNode (stringNode, "STRING")));
01461                                                 }
01462                                         }
01463                                         else if (type == "color")
01464                                         {
01465                                                 // Create a new property
01466                                                 CPropertyColor *propertyColor= new CPropertyColor;
01467                                                 property = propertyColor;
01468 
01469                                                 // Read strings
01470                                                 xmlNodePtr colorNode;
01471                                                 colorNode = CIXml::getFirstChildNode (xmlNode, "COLOR");
01472                                                 string R, G, B, A;
01473                                                 if (GetPropertyString (R, filename, colorNode, "R") &&
01474                                                         GetPropertyString (G, filename, colorNode, "G") &&
01475                                                         GetPropertyString (B, filename, colorNode, "B") &&
01476                                                         GetPropertyString (A, filename, colorNode, "A"))
01477                                                 {
01478                                                         sint32 sR=0, sG=0, sB=0, sA=255;
01479                                                         sR = atoi (R.c_str ());
01480                                                         clamp (sR, 0, 255);
01481                                                         sG = atoi (G.c_str ());
01482                                                         clamp (sG, 0, 255);
01483                                                         sB = atoi (B.c_str ());
01484                                                         clamp (sB, 0, 255);
01485                                                         sA = atoi (A.c_str ());
01486                                                         clamp (sR, 0, 255);
01487                                                         propertyColor->Color.R = (uint8)sR;
01488                                                         propertyColor->Color.G = (uint8)sG;
01489                                                         propertyColor->Color.B = (uint8)sB;
01490                                                         propertyColor->Color.A = (uint8)sA;
01491                                                 }
01492                                                 else
01493                                                         return false;
01494                                         }
01495 
01496                                         // Property found ?
01497                                         if (property == NULL)
01498                                         {
01499                                                 XMLError (propNode, filename, "IPrimitive::read : Unknown property type (%s)", type.c_str ());
01500                                                 return false;
01501                                         }
01502 
01503                                         // Add it
01504                                         _Properties.insert (std::map<std::string, IProperty*>::value_type (name, property));
01505                                 }
01506                                 else
01507                                 {
01508                                         return false;
01509                                 }
01510                         }
01511                         else
01512                         {
01513                                 return false;
01514                         }
01515                 }
01516                 while (propNode = CIXml::getNextChildNode (propNode, "PROPERTY"));
01517         }
01518 
01519         // Read children
01520         xmlNodePtr childNode;
01521         childNode = CIXml::getFirstChildNode (xmlNode, "CHILD");
01522         if (childNode)
01523         {
01524                 do
01525                 {
01526                         // Get the property class
01527                         string type;
01528                         if (GetPropertyString (type, filename, childNode, "TYPE"))
01529                         {
01530                                 // Primitive
01531                                 IPrimitive *primitive = NULL;
01532 
01533                                 // Check the type
01534                                 if (type == "node")
01535                                 {
01536                                         // Create new primitive
01537                                         primitive = new CPrimNode;
01538                                 }
01539                                 else if (type == "point")
01540                                 {
01541                                         // Create new primitive
01542                                         primitive = new CPrimPoint;
01543                                 }
01544                                 else if (type == "path")
01545                                 {
01546                                         // Create new primitive
01547                                         primitive = new CPrimPath;
01548                                 }
01549                                 else if (type == "zone")
01550                                 {
01551                                         // Create new primitive
01552                                         primitive = new CPrimZone;
01553                                 }
01554 
01555                                 // Primitive type not found ?
01556                                 if (primitive == NULL)
01557                                 {
01558                                         XMLError (childNode, filename, "IPrimitive::read : Unknown primitive type (%s)", type.c_str ());
01559                                         return false;
01560                                 }
01561 
01562                                 // Read it
01563                                 primitive->read (childNode, filename, version);
01564 
01565                                 // Add it
01566                                 insertChild (primitive);
01567                         }
01568                         else
01569                         {
01570                                 return false;
01571                         }
01572                 }
01573                 while (childNode = CIXml::getNextChildNode (childNode, "CHILD"));
01574         }
01575 
01576         // Done
01577         return true;
01578 }
01579 
01580 // ***************************************************************************
01581 
01582 void IPrimitive::write (xmlNodePtr xmlNode, const char *filename) const
01583 {
01584         // Save the properties
01585         std::map<std::string, IProperty*>::const_iterator ite = _Properties.begin ();
01586         while (ite != _Properties.end ())
01587         {
01588                 // Create new nodes
01589                 xmlNodePtr propNode = xmlNewChild ( xmlNode, NULL, (const xmlChar*)"PROPERTY", NULL);
01590                 xmlNodePtr nameNode = xmlNewChild ( propNode, NULL, (const xmlChar*)"NAME", NULL);
01591                 xmlNodePtr textNode = xmlNewText ((const xmlChar *)(ite->first.c_str ()));
01592                 xmlAddChild (nameNode, textNode);
01593 
01594                 // Type
01595                 const CPropertyString *str = dynamic_cast<const CPropertyString *> (ite->second);
01596                 if (str)
01597                 {
01598                         // Set the type
01599                         xmlSetProp (propNode, (const xmlChar*)"TYPE", (const xmlChar*)"string");
01600 
01601                         // Create new nodes
01602                         xmlNodePtr stringNode = xmlNewChild ( propNode, NULL, (const xmlChar*)"STRING", NULL);
01603                         xmlNodePtr textNode = xmlNewText ((const xmlChar *)(str->String.c_str ()));
01604                         xmlAddChild (stringNode, textNode);
01605                 }
01606                 else
01607                 {
01608                         // Should be an array
01609                         const CPropertyStringArray *array = dynamic_cast<const CPropertyStringArray *> (ite->second);
01610                         if (array)
01611                         {
01612                                 // Set the type
01613                                 xmlSetProp (propNode, (const xmlChar*)"TYPE", (const xmlChar*)"string_array");
01614 
01615                                 // For each strings in the array
01616                                 for (uint i=0; i<array->StringArray.size (); i++)
01617                                 {
01618                                         // Create new nodes
01619                                         xmlNodePtr stringNode = xmlNewChild ( propNode, NULL, (const xmlChar*)"STRING", NULL);
01620                                         xmlNodePtr textNode = xmlNewText ((const xmlChar *)(array->StringArray[i].c_str ()));
01621                                         xmlAddChild (stringNode, textNode);
01622                                 }
01623                         }
01624                         else
01625                         {
01626                                 // Should be a color
01627                                 const CPropertyColor *color = safe_cast<const CPropertyColor *> (ite->second);
01628 
01629                                 // Set the type
01630                                 xmlSetProp (propNode, (const xmlChar*)"TYPE", (const xmlChar*)"color");
01631 
01632                                 // Create new nodes
01633                                 xmlNodePtr colorNode = xmlNewChild ( propNode, NULL, (const xmlChar*)"COLOR", NULL);
01634                                 xmlSetProp (colorNode, (const xmlChar*)"R", (const xmlChar*)toString (color->Color.R).c_str ());
01635                                 xmlSetProp (colorNode, (const xmlChar*)"G", (const xmlChar*)toString (color->Color.G).c_str ());
01636                                 xmlSetProp (colorNode, (const xmlChar*)"B", (const xmlChar*)toString (color->Color.B).c_str ());
01637                                 xmlSetProp (colorNode, (const xmlChar*)"A", (const xmlChar*)toString (color->Color.A).c_str ());
01638                         }
01639                 }
01640 
01641                 ite++;
01642         }
01643 
01644         // Save the children
01645         for (uint i=0; i<_Children.size (); i++)
01646         {
01647                 // New node
01648                 xmlNodePtr childNode = xmlNewChild ( xmlNode, NULL, (const xmlChar*)"CHILD", NULL);
01649 
01650                 // Write it
01651                 _Children[i]->write (childNode, filename);
01652         }
01653 }
01654 
01655 // ***************************************************************************
01656 
01657 bool IPrimitive::getChildId (uint &childId, const IPrimitive *child) const
01658 {
01659         const uint childrenSize = _Children.size ();
01660         for (uint i=0; i<childrenSize; i++)
01661         {
01662                 if (_Children[i] == child)
01663                 {
01664                         childId = i;
01665                         return true;
01666                 }
01667         }
01668         childId = 0xffffffff;
01669         return false;
01670 }
01671 
01672 // ***************************************************************************
01673 
01674 uint IPrimitive::getNumProperty () const 
01675 {
01676         return _Properties.size ();
01677 }
01678 
01679 // ***************************************************************************
01680 // CPrimitives
01681 // ***************************************************************************
01682 
01683 bool CPrimitives::read (xmlNodePtr xmlNode, const char *filename)
01684 {
01685         nlassert (xmlNode);
01686 
01687         // Get the name
01688         if (strcmp ((const char*)xmlNode->name, "PRIMITIVES") == 0)
01689         {
01690                 // Get the version
01691                 string versionName = "0";
01692                 if (GetPropertyString (versionName, filename, xmlNode, "VERSION"))
01693                 {
01694                         // Get the version
01695                         uint version = atoi (versionName.c_str ());
01696 
01697                         // Check the version
01698                         if (version <= NLLIGO_PRIMITVE_VERSION)
01699                         {
01700                                 // Read the primitives
01701                                 xmlNode = GetFirstChildNode (xmlNode, filename, "ROOT_PRIMITIVE");
01702                                 if (xmlNode)
01703                                 {
01704                                         // Read the primitive tree
01705                                         ((IPrimitive*)&RootNode)->read (xmlNode, filename, version);
01706                                 }
01707                         }
01708                         else
01709                         {
01710                                 Error (filename, "CPrimitives::read : Unknown file version (%d)", version);
01711                                 return false;
01712                         }
01713                 }
01714                 else
01715                 {
01716                         return false;
01717                 }
01718         }
01719         else
01720         {
01721                 XMLError (xmlNode, filename, "This XML document is not a NeL primitive file");
01722                 return false;
01723         }
01724 
01725         return true;
01726 }
01727 
01728 // ***************************************************************************
01729 
01730 void CPrimitives::write (xmlDocPtr doc, const char *filename) const
01731 {
01732         nlassert (doc);
01733 
01734         // Primitive node
01735         xmlNodePtr primNode = xmlNewDocNode (doc, NULL, (const xmlChar*)"PRIMITIVES", NULL);
01736         xmlDocSetRootElement (doc, primNode);
01737 
01738         // Version node
01739         xmlSetProp (primNode, (const xmlChar*)"VERSION", (const xmlChar*)toString (NLLIGO_PRIMITVE_VERSION).c_str ());
01740 
01741         // The primitive root node
01742         xmlNodePtr nameNode = xmlNewChild ( primNode, NULL, (const xmlChar*)"ROOT_PRIMITIVE", NULL);
01743 
01744         // Write the primitive tree
01745         ((IPrimitive*)&RootNode)->write (nameNode, filename);
01746 }
01747 
01748 // ***************************************************************************
01749 
01750 void CPrimitives::convertAddPrimitive (IPrimitive *child, const IPrimitive *prim, bool hidden)
01751 {
01752         // The primitve
01753         IPrimitive *primitive = NULL;
01754 
01755         // What kind of primitive ?
01756         const CPrimPoint *oldPoint = dynamic_cast<const CPrimPoint *>(prim);
01757         if (oldPoint)
01758         {
01759                 // Create a primitive
01760                 CPrimPoint *point = new CPrimPoint ();
01761                 primitive = point;
01762 
01763                 // Copy it
01764                 *point = *oldPoint;
01765         }
01766         else
01767         {
01768                 // Path ?
01769                 const CPrimPath *oldPath = dynamic_cast<const CPrimPath *>(prim);
01770                 if (oldPath)
01771                 {
01772                         // Create a primitive
01773                         CPrimPath *path = new CPrimPath ();
01774                         primitive = path;
01775 
01776                         // Copy it
01777                         *path = *oldPath;
01778                 }
01779                 else
01780                 {
01781                         const CPrimZone *oldZone = safe_cast<const CPrimZone *>(prim);
01782                         if (oldZone)
01783                         {
01784                                 // Create a primitive
01785                                 CPrimZone *zone = new CPrimZone ();
01786                                 primitive = zone;
01787 
01788                                 // Copy it
01789                                 *zone = *oldZone;
01790                         }
01791                 }
01792         }
01793 
01794         // Primitive has been created ?
01795         if (primitive)
01796         {
01797                 // Create a property for the name
01798                 CPropertyString *nameProp = new CPropertyString;
01799                 nameProp->String = prim->Name;
01800 
01801                 // Add the property
01802                 primitive->addPropertyByName ("Name", nameProp);
01803 
01804                 // The primitive is hidden ?
01805                 if (hidden)
01806                 {
01807                         // Create a property for hidden
01808                         nameProp = new CPropertyString;
01809 
01810                         // Add the property
01811                         primitive->addPropertyByName ("Hidden", nameProp);
01812                 }
01813 
01814                 // Add the child
01815                 child->insertChild (primitive);
01816         }
01817 }
01818 
01819 // ***************************************************************************
01820 
01821 void CPrimitives::convertPrimitive (const IPrimitive *prim, bool hidden)
01822 {
01823         // Look for the group
01824         uint numChildren = RootNode.getNumChildren ();
01825         uint j;
01826         for (j=0; j<numChildren; j++)
01827         {
01828                 IPrimitive *child;
01829                 nlverify (RootNode.getChild (child, j));
01830                 const IProperty *prop;
01831                 if (child->getPropertyByName ("Name", prop))
01832                 {
01833                         // Prop string
01834                         const CPropertyString *name = dynamic_cast<const CPropertyString *>(prop);
01835                         if (name)
01836                         {
01837                                 // This one ?
01838                                 if (name->String == prim->Layer)
01839                                 {
01840                                         convertAddPrimitive (child, prim, hidden);
01841                                         break;
01842                                 }
01843                         }
01844                 }
01845         }
01846 
01847         // Not found ?
01848         if (j==numChildren)
01849         {
01850                 // Create a node
01851                 CPrimNode *primNode = new CPrimNode;
01852         
01853                 // Create a property for the layer
01854                 CPropertyString *nameProp = new CPropertyString;
01855                 nameProp->String = prim->Layer;
01856 
01857                 // Add the property
01858                 primNode->addPropertyByName ("Name", nameProp);
01859 
01860                 // Add the child
01861                 RootNode.insertChild (primNode);
01862 
01863                 // Add the primitive
01864                 convertAddPrimitive (primNode, prim, hidden);
01865         }
01866 }
01867 
01868 // ***************************************************************************
01869 
01870 void CPrimitives::convert (const CPrimRegion &region)
01871 {
01872         // Delete
01873         RootNode.removeChildren ();
01874         RootNode.removeProperties ();
01875 
01876         // For each primitives
01877         uint i;
01878         for (i=0; i<region.VPoints.size (); i++)
01879         {
01880                 convertPrimitive (&(region.VPoints[i]), region.VHidePoints[i]);
01881         }
01882         for (i=0; i<region.VPaths.size (); i++)
01883         {
01884                 convertPrimitive (&(region.VPaths[i]), region.VHidePaths[i]);
01885         }
01886         for (i=0; i<region.VZones.size (); i++)
01887         {
01888                 convertPrimitive (&(region.VZones[i]), region.VHideZones[i]);
01889         }
01890 }
01891 
01892 // ***************************************************************************
01893 
01894 
01895 } // namespace NLLIGO
01896