From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/primitive_8cpp-source.html | 1965 +++++++++++++++++++++++++++ 1 file changed, 1965 insertions(+) create mode 100644 docs/doxygen/nel/primitive_8cpp-source.html (limited to 'docs/doxygen/nel/primitive_8cpp-source.html') diff --git a/docs/doxygen/nel/primitive_8cpp-source.html b/docs/doxygen/nel/primitive_8cpp-source.html new file mode 100644 index 00000000..da3c406d --- /dev/null +++ b/docs/doxygen/nel/primitive_8cpp-source.html @@ -0,0 +1,1965 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# 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 
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1