"Fossies" - the Fresh Open Source Software Archive

Member "asymptote-2.61/prc/oPRCFile.cc" (18 Nov 2019, 70751 Bytes) of package /linux/misc/asymptote-2.61.src.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "oPRCFile.cc" see the Fossies "Dox" file reference documentation.

    1 /************
    2 *
    3 *   This file is part of a tool for producing 3D content in the PRC format.
    4 *   Copyright (C) 2008  Orest Shardt <shardtor (at) gmail dot com> and
    5 *                       Michail Vidiassov <master@iaas.msu.ru>
    6 *
    7 *   This program is free software: you can redistribute it and/or modify
    8 *   it under the terms of the GNU Lesser General Public License as published by
    9 *   the Free Software Foundation, either version 3 of the License, or
   10 *   (at your option) any later version.
   11 *
   12 *   This program is distributed in the hope that it will be useful,
   13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15 *   GNU Lesser General Public License for more details.
   16 *
   17 *   You should have received a copy of the GNU Lesser General Public License
   18 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
   19 *
   20 *************/
   21 
   22 #include "oPRCFile.h"
   23 #include <time.h>
   24 #include <sstream>
   25 #include <iostream>
   26 #include <fstream>
   27 #include <iomanip>
   28 #include <cstring>
   29 #include <zlib.h>
   30 
   31 namespace prc {
   32 
   33 #define WriteUnsignedInteger( value ) out << (uint32_t)(value);
   34 #define WriteInteger( value ) out << (int32_t)(value);
   35 #define WriteDouble( value ) out << (double)(value);
   36 #define WriteString( value ) out << (value);
   37 #define WriteUncompressedUnsignedInteger( value ) writeUncompressedUnsignedInteger(out, (uint32_t)(value));
   38 #define WriteUncompressedBlock( value, count ) out.write((char *)(value),(count));
   39 #define SerializeFileStructureUncompressedUniqueId( value ) (value).serializeFileStructureUncompressedUniqueId(out);
   40 #define SerializeCompressedUniqueId( value ) (value).serializeCompressedUniqueId(out);
   41 #define SerializeContentPRCBase write(out);
   42 #define SerializeRgbColor( value ) (value).serializeRgbColor(out);
   43 #define SerializePicture( value ) (value).serializePicture(out);
   44 #define SerializeTextureDefinition( value ) (value)->serializeTextureDefinition(out);
   45 #define SerializeMarkup( value ) (value)->serializeMarkup(out);
   46 #define SerializeAnnotationEntity( value ) (value)->serializeAnnotationEntity(out);
   47 #define SerializeFontKeysSameFont( value ) (value).serializeFontKeysSameFont(out);
   48 #define SerializeMaterial( value ) (value)->serializeMaterial(out);
   49 
   50 #define SerializeUserData UserData(0,0).write(out);
   51 #define SerializeEmptyContentPRCBase ContentPRCBase(PRC_TYPE_ROOT_PRCBase).serializeContentPRCBase(out);
   52 #define SerializeCategory1LineStyle( value ) (value)->serializeCategory1LineStyle(out);
   53 #define SerializeCoordinateSystem( value ) (value)->serializeCoordinateSystem(out);
   54 #define SerializeRepresentationItem( value ) (value)->serializeRepresentationItem(out);
   55 #define SerializePartDefinition( value ) (value)->serializePartDefinition(out);
   56 #define SerializeProductOccurrence( value ) (value)->serializeProductOccurrence(out);
   57 #define SerializeContextAndBodies( value ) (value)->serializeContextAndBodies(out);
   58 #define SerializeGeometrySummary( value ) (value)->serializeGeometrySummary(out);
   59 #define SerializeContextGraphics( value ) (value)->serializeContextGraphics(out);
   60 #define SerializeStartHeader serializeStartHeader(out);
   61 #define SerializeUncompressedFiles  \
   62  { \
   63   const uint32_t number_of_uncompressed_files = uncompressed_files.size(); \
   64   WriteUncompressedUnsignedInteger (number_of_uncompressed_files) \
   65   for(PRCUncompressedFileList::const_iterator it = uncompressed_files.begin(); it != uncompressed_files.end(); it++) \
   66   { \
   67     WriteUncompressedUnsignedInteger ((*it)->file_size) \
   68     WriteUncompressedBlock ((*it)->data, (*it)->file_size) \
   69   } \
   70  }
   71 #define SerializeModelFileData serializeModelFileData(modelFile_out); modelFile_out.compress();
   72 #define SerializeUnit( value ) (value).serializeUnit(out);
   73 
   74 using namespace std;
   75 
   76 void PRCFileStructure::serializeFileStructureGlobals(PRCbitStream &out)
   77 {
   78   // even though this is technically not part of this section,
   79   // it is handled here for convenience
   80   const uint32_t number_of_schema = 0;
   81   WriteUnsignedInteger (number_of_schema)
   82 
   83   WriteUnsignedInteger (PRC_TYPE_ASM_FileStructureGlobals)
   84 
   85   PRCSingleAttribute sa((int32_t)PRCVersion);
   86   PRCAttribute a("__PRC_RESERVED_ATTRIBUTE_PRCInternalVersion");
   87   a.addKey(sa);
   88   ContentPRCBase cb(PRC_TYPE_ROOT_PRCBase);
   89   cb.addAttribute(a);
   90   cb.serializeContentPRCBase(out);
   91   WriteUnsignedInteger (number_of_referenced_file_structures)
   92   // SerializeFileStructureInternalGlobalData
   93   WriteDouble (tessellation_chord_height_ratio)
   94   WriteDouble (tessellation_angle_degree)
   95 
   96   // SerializeMarkupSerializationHelper
   97   WriteString (default_font_family_name)
   98 
   99   const uint32_t number_of_fonts = font_keys_of_font.size();
  100   WriteUnsignedInteger (number_of_fonts)
  101   for (uint32_t i=0;i<number_of_fonts;i++)
  102   {
  103     SerializeFontKeysSameFont (font_keys_of_font[i])
  104   }
  105 
  106   const uint32_t number_of_colors = colors.size();
  107   WriteUnsignedInteger (number_of_colors)
  108   for (uint32_t i=0;i<number_of_colors;i++)
  109       SerializeRgbColor (colors[i])
  110 
  111   const uint32_t number_of_pictures = pictures.size();
  112   WriteUnsignedInteger (number_of_pictures)
  113   for (uint32_t i=0;i<number_of_pictures;i++)
  114      SerializePicture (pictures[i])
  115 
  116   const uint32_t number_of_texture_definitions = texture_definitions.size();
  117   WriteUnsignedInteger (number_of_texture_definitions)
  118   for (uint32_t i=0;i<number_of_texture_definitions;i++)
  119      SerializeTextureDefinition (texture_definitions[i])
  120 
  121   const uint32_t number_of_materials = materials.size();
  122   WriteUnsignedInteger (number_of_materials)
  123   for (uint32_t i=0;i<number_of_materials;i++)
  124      SerializeMaterial (materials[i])
  125 
  126   // number of line patterns hard coded for now
  127   const uint32_t number_of_line_patterns = 1;
  128   WriteUnsignedInteger (number_of_line_patterns)
  129   PRCLinePattern().serializeLinePattern(out);
  130 
  131   const uint32_t number_of_styles = styles.size();
  132   WriteUnsignedInteger (number_of_styles)
  133   for (uint32_t i=0;i<number_of_styles;i++)
  134      SerializeCategory1LineStyle (styles[i])
  135 
  136   const uint32_t number_of_fill_patterns = 0;
  137   WriteUnsignedInteger (number_of_fill_patterns)
  138 
  139   const uint32_t number_of_reference_coordinate_systems = reference_coordinate_systems.size();
  140   WriteUnsignedInteger (number_of_reference_coordinate_systems)
  141   for (uint32_t i=0;i<number_of_reference_coordinate_systems;i++)
  142      SerializeCoordinateSystem (reference_coordinate_systems[i])
  143 
  144   SerializeUserData
  145 }
  146 
  147 void PRCFileStructure::serializeFileStructureTree(PRCbitStream &out)
  148 {
  149   WriteUnsignedInteger (PRC_TYPE_ASM_FileStructureTree)
  150 
  151   SerializeEmptyContentPRCBase
  152 
  153   const uint32_t number_of_part_definitions = part_definitions.size();
  154   WriteUnsignedInteger (number_of_part_definitions)
  155   for (uint32_t i=0;i<number_of_part_definitions;i++)
  156     SerializePartDefinition (part_definitions[i])
  157     
  158   const uint32_t number_of_product_occurrences = product_occurrences.size();
  159   WriteUnsignedInteger (number_of_product_occurrences)
  160   for (uint32_t i=0;i<number_of_product_occurrences;i++)
  161   {
  162     product_occurrences[i]->unit_information.unit_from_CAD_file = true;
  163     product_occurrences[i]->unit_information.unit = unit;
  164     SerializeProductOccurrence (product_occurrences[i])
  165   }
  166 
  167   // SerializeFileStructureInternalData
  168   WriteUnsignedInteger (PRC_TYPE_ASM_FileStructure)
  169   SerializeEmptyContentPRCBase
  170   const uint32_t next_available_index = makePRCID();
  171   WriteUnsignedInteger (next_available_index)
  172   const uint32_t index_product_occurence = number_of_product_occurrences;  // Asymptote (oPRCFile) specific - we write the root product last
  173   WriteUnsignedInteger (index_product_occurence)
  174 
  175   SerializeUserData
  176 }
  177 
  178 void PRCFileStructure::serializeFileStructureTessellation(PRCbitStream &out)
  179 {
  180   WriteUnsignedInteger (PRC_TYPE_ASM_FileStructureTessellation)
  181 
  182   SerializeEmptyContentPRCBase
  183   const uint32_t number_of_tessellations = tessellations.size();
  184   WriteUnsignedInteger (number_of_tessellations)
  185   for (uint32_t i=0;i<number_of_tessellations;i++)
  186     tessellations[i]->serializeBaseTessData(out);
  187 
  188   SerializeUserData
  189 }
  190 
  191 void PRCFileStructure::serializeFileStructureGeometry(PRCbitStream &out)
  192 {
  193   WriteUnsignedInteger (PRC_TYPE_ASM_FileStructureGeometry)
  194 
  195   SerializeEmptyContentPRCBase
  196   const uint32_t number_of_contexts = contexts.size();
  197   WriteUnsignedInteger (number_of_contexts)
  198   for (uint32_t i=0;i<number_of_contexts;i++)
  199     SerializeContextAndBodies (contexts[i])
  200 
  201   SerializeUserData
  202 }
  203 
  204 void PRCFileStructure::serializeFileStructureExtraGeometry(PRCbitStream &out)
  205 {
  206   WriteUnsignedInteger (PRC_TYPE_ASM_FileStructureExtraGeometry)
  207 
  208   SerializeEmptyContentPRCBase
  209   const uint32_t number_of_contexts = contexts.size();
  210   WriteUnsignedInteger (number_of_contexts)
  211   for (uint32_t i=0;i<number_of_contexts;i++)
  212   {
  213      SerializeGeometrySummary (contexts[i])
  214      SerializeContextGraphics (contexts[i])
  215   }
  216 
  217   SerializeUserData
  218 }
  219 
  220 void oPRCFile::serializeModelFileData(PRCbitStream &out)
  221 {
  222   // even though this is technically not part of this section,
  223   // it is handled here for convenience
  224   const uint32_t number_of_schema = 0;
  225   WriteUnsignedInteger (number_of_schema)
  226   WriteUnsignedInteger (PRC_TYPE_ASM_ModelFile)
  227 
  228   PRCSingleAttribute sa((int32_t)PRCVersion);
  229   PRCAttribute a("__PRC_RESERVED_ATTRIBUTE_PRCInternalVersion");
  230   a.addKey(sa);
  231   ContentPRCBase cb(PRC_TYPE_ROOT_PRCBase,"PRC file");
  232   cb.addAttribute(a);
  233   cb.serializeContentPRCBase(out);
  234 
  235   SerializeUnit (unit)
  236 
  237   out << (uint32_t)1; // 1 product occurrence
  238   //UUID
  239   SerializeCompressedUniqueId( fileStructures[0]->file_structure_uuid )
  240   // index+1
  241   out << (uint32_t)fileStructures[0]->product_occurrences.size();
  242   // active
  243   out << true;
  244   out << (uint32_t)0; // index in model file
  245 
  246   SerializeUserData
  247 }
  248 
  249 void makeFileUUID(PRCUniqueId& UUID)
  250 {
  251   // make a UUID
  252   static uint32_t count = 0;
  253   ++count;
  254   // the minimum requirement on UUIDs is that all must be unique in the file
  255   UUID.id0 = 0x33595341; // some constant
  256   UUID.id1 = (uint32_t)time(NULL); // the time
  257   UUID.id2 = count;
  258   UUID.id3 = 0xa5a55a5a; // Something random, not seeded by the time, would be nice. But for now, a constant
  259   // maybe add something else to make it more unique
  260   // so multiple files can be combined
  261   // a hash of some data perhaps?
  262 }
  263 
  264 void makeAppUUID(PRCUniqueId& UUID)
  265 {
  266   UUID.id0 = UUID.id1 = UUID.id2 = UUID.id3 = 0;
  267 }
  268 
  269 void PRCUncompressedFile::write(ostream &out) const
  270 {
  271   if(data!=NULL)
  272   {
  273     WriteUncompressedUnsignedInteger (file_size)
  274     out.write((char*)data,file_size);
  275   }
  276 }
  277 
  278 uint32_t PRCUncompressedFile::getSize() const
  279 {
  280   return sizeof(file_size)+file_size;
  281 }
  282 
  283 
  284 void PRCStartHeader::serializeStartHeader(ostream &out) const
  285 {
  286   WriteUncompressedBlock ("PRC",3)
  287   WriteUncompressedUnsignedInteger (minimal_version_for_read)
  288   WriteUncompressedUnsignedInteger (authoring_version)
  289   SerializeFileStructureUncompressedUniqueId( file_structure_uuid );
  290   SerializeFileStructureUncompressedUniqueId( application_uuid );
  291 }
  292 
  293 uint32_t PRCStartHeader::getStartHeaderSize() const
  294 {
  295   return 3+(2+2*4)*sizeof(uint32_t);
  296 }
  297 
  298 
  299 void PRCFileStructure::write(ostream &out)
  300 {
  301   // SerializeFileStructureHeader
  302   SerializeStartHeader
  303   SerializeUncompressedFiles
  304   globals_out.write(out);
  305   tree_out.write(out);
  306   tessellations_out.write(out);
  307   geometry_out.write(out);
  308   extraGeometry_out.write(out);
  309 }
  310 
  311 #define SerializeFileStructureGlobals serializeFileStructureGlobals(globals_out); globals_out.compress(); sizes[1]=globals_out.getSize();
  312 #define SerializeFileStructureTree serializeFileStructureTree(tree_out); tree_out.compress(); sizes[2]=tree_out.getSize();
  313 #define SerializeFileStructureTessellation serializeFileStructureTessellation(tessellations_out); tessellations_out.compress(); sizes[3]=tessellations_out.getSize();
  314 #define SerializeFileStructureGeometry serializeFileStructureGeometry(geometry_out); geometry_out.compress(); sizes[4]=geometry_out.getSize();
  315 #define SerializeFileStructureExtraGeometry serializeFileStructureExtraGeometry(extraGeometry_out); extraGeometry_out.compress(); sizes[5]=extraGeometry_out.getSize();
  316 #define FlushSerialization resetGraphicsAndName();
  317 void PRCFileStructure::prepare()
  318 {
  319   uint32_t size = 0;
  320   size += getStartHeaderSize();
  321   size += sizeof(uint32_t);
  322   for(PRCUncompressedFileList::const_iterator it = uncompressed_files.begin(); it != uncompressed_files.end(); it++)
  323     size += (*it)->getSize();
  324   sizes[0]=size;
  325 
  326   SerializeFileStructureGlobals
  327   FlushSerialization
  328 
  329   SerializeFileStructureTree
  330   FlushSerialization
  331 
  332   SerializeFileStructureTessellation
  333   FlushSerialization
  334 
  335   SerializeFileStructureGeometry
  336   FlushSerialization
  337 
  338   SerializeFileStructureExtraGeometry
  339   FlushSerialization
  340 }
  341 
  342 uint32_t PRCFileStructure::getSize()
  343 {
  344   uint32_t size = 0;
  345   for(size_t i=0; i<6; i++)
  346     size += sizes[i];
  347   return size;
  348 }
  349 
  350 
  351 void PRCFileStructureInformation::write(ostream &out)
  352 {
  353   SerializeFileStructureUncompressedUniqueId( UUID );
  354 
  355   WriteUncompressedUnsignedInteger (reserved)
  356   WriteUncompressedUnsignedInteger (number_of_offsets)
  357   for(uint32_t i = 0; i < number_of_offsets; ++i)
  358   {
  359     WriteUncompressedUnsignedInteger (offsets[i])
  360   }
  361 }
  362 
  363 uint32_t PRCFileStructureInformation::getSize()
  364 {
  365   return (4+2+number_of_offsets)*sizeof(uint32_t);
  366 }
  367 
  368 void PRCHeader::write(ostream &out)
  369 {
  370   SerializeStartHeader
  371   WriteUncompressedUnsignedInteger (number_of_file_structures)
  372   for(uint32_t i = 0; i < number_of_file_structures; ++i)
  373   {
  374     fileStructureInformation[i].write(out);
  375   }
  376   WriteUncompressedUnsignedInteger (model_file_offset)
  377   WriteUncompressedUnsignedInteger (file_size)
  378   SerializeUncompressedFiles
  379 }
  380 
  381 uint32_t PRCHeader::getSize()
  382 {
  383   uint32_t size = getStartHeaderSize() + sizeof(uint32_t);
  384   for(uint32_t i = 0; i < number_of_file_structures; ++i)
  385     size += fileStructureInformation[i].getSize();
  386   size += 3*sizeof(uint32_t);
  387   for(PRCUncompressedFileList::const_iterator it = uncompressed_files.begin(); it != uncompressed_files.end(); it++)
  388     size += (*it)->getSize();
  389   return size;
  390 }
  391 
  392 void oPRCFile::doGroup(PRCgroup& group)
  393 {
  394     const std::string& name = group.name;
  395 
  396     PRCProductOccurrence*& product_occurrence        = group.product_occurrence;
  397     PRCProductOccurrence*& parent_product_occurrence = group.parent_product_occurrence;
  398     PRCPartDefinition*& part_definition              = group.part_definition;
  399     PRCPartDefinition*& parent_part_definition       = group.parent_part_definition;
  400 
  401     if(group.options.tess)
  402     {
  403       if(!group.lines.empty())
  404       {
  405         for(PRCtesslineMap::const_iterator wit=group.lines.begin(); wit!=group.lines.end(); wit++)
  406         {
  407           bool same_color = true;
  408           const PRCtesslineList& lines = wit->second;
  409           const PRCRgbColor &color = lines.front().color;
  410           for(PRCtesslineList::const_iterator lit=lines.begin(); lit!=lines.end(); lit++)
  411             if(color!=lit->color)
  412             {
  413               same_color = false;
  414               break;
  415             }
  416           map<PRCVector3d,uint32_t> points;
  417           PRC3DWireTess *tess = new PRC3DWireTess();
  418           if(!same_color)
  419           {
  420             tess->is_segment_color = true;
  421             tess->is_rgba = false;
  422           }
  423           for(PRCtesslineList::const_iterator lit=lines.begin(); lit!=lines.end(); lit++)
  424           {
  425             tess->wire_indexes.push_back(lit->point.size());
  426             for(uint32_t i=0; i<lit->point.size(); i++)
  427             {
  428               map<PRCVector3d,uint32_t>::iterator pPoint = points.find(lit->point[i]);
  429               if(pPoint!=points.end())
  430                 tess->wire_indexes.push_back(pPoint->second);
  431               else
  432               {
  433                 const uint32_t point_index = tess->coordinates.size();
  434                 points.insert(make_pair(lit->point[i],point_index));
  435                 tess->wire_indexes.push_back(point_index);
  436                 tess->coordinates.push_back(lit->point[i].x);
  437                 tess->coordinates.push_back(lit->point[i].y);
  438                 tess->coordinates.push_back(lit->point[i].z);
  439               }
  440               if(!same_color && i>0)
  441               {
  442                 tess->rgba_vertices.push_back(byte(lit->color.red));
  443                 tess->rgba_vertices.push_back(byte(lit->color.green));
  444                 tess->rgba_vertices.push_back(byte(lit->color.blue));
  445               }
  446             }
  447           }
  448           const uint32_t tess_index = add3DWireTess(tess);
  449           PRCPolyWire *polyWire = new PRCPolyWire();
  450           polyWire->index_tessellation = tess_index;
  451           if(same_color)
  452             polyWire->index_of_line_style = addColourWidth(RGBAColour(color.red,color.green,color.blue),wit->first);
  453           else
  454             polyWire->index_of_line_style = addColourWidth(RGBAColour(1,1,1),wit->first);
  455           part_definition->addPolyWire(polyWire);
  456         }
  457       }
  458 //    make rectangles pairs of triangles in a tesselation
  459       if(!group.rectangles.empty())
  460       {
  461         bool same_color = true;
  462         const uint32_t &style = group.rectangles.front().style;
  463         for(PRCtessrectangleList::const_iterator rit=group.rectangles.begin(); rit!=group.rectangles.end(); rit++)
  464           if(style!=rit->style)
  465           {
  466             same_color = false;
  467             break;
  468           }
  469         map<PRCVector3d,uint32_t> points;
  470         PRC3DTess *tess = new PRC3DTess();
  471         tess->crease_angle = group.options.crease_angle;
  472         PRCTessFace *tessFace = new PRCTessFace();
  473         tessFace->used_entities_flag=PRC_FACETESSDATA_Triangle;
  474         uint32_t triangles = 0;
  475         for(PRCtessrectangleList::const_iterator rit=group.rectangles.begin(); rit!=group.rectangles.end(); rit++)
  476         {
  477           const bool degenerate = (rit->vertices[0]==rit->vertices[1]);
  478           uint32_t vertex_indices[4];
  479           for(size_t i = (degenerate?1:0); i < 4; ++i)
  480           {
  481             map<PRCVector3d,uint32_t>::const_iterator pPoint = points.find(rit->vertices[i]);
  482             if(pPoint!=points.end())
  483               vertex_indices[i] =  pPoint->second;
  484             else
  485             {
  486               points.insert(make_pair(rit->vertices[i],(vertex_indices[i] = tess->coordinates.size())));
  487               tess->coordinates.push_back(rit->vertices[i].x);
  488               tess->coordinates.push_back(rit->vertices[i].y);
  489               tess->coordinates.push_back(rit->vertices[i].z);
  490             }
  491           }
  492           if(degenerate)
  493           {
  494             tess->triangulated_index.push_back(vertex_indices[1]);
  495             tess->triangulated_index.push_back(vertex_indices[2]);
  496             tess->triangulated_index.push_back(vertex_indices[3]);
  497             triangles++;
  498             if(!same_color)
  499               tessFace->line_attributes.push_back(rit->style);
  500           }
  501           else
  502           {
  503             tess->triangulated_index.push_back(vertex_indices[0]);
  504             tess->triangulated_index.push_back(vertex_indices[2]);
  505             tess->triangulated_index.push_back(vertex_indices[3]);
  506             triangles++;
  507             if(!same_color)
  508               tessFace->line_attributes.push_back(rit->style);
  509             tess->triangulated_index.push_back(vertex_indices[3]);
  510             tess->triangulated_index.push_back(vertex_indices[1]);
  511             tess->triangulated_index.push_back(vertex_indices[0]);
  512             triangles++;
  513             if(!same_color)
  514               tessFace->line_attributes.push_back(rit->style);
  515           }
  516         }
  517         tessFace->sizes_triangulated.push_back(triangles);
  518         tess->addTessFace(tessFace);
  519         const uint32_t tess_index = add3DTess(tess);
  520         PRCPolyBrepModel *polyBrepModel = new PRCPolyBrepModel();
  521         polyBrepModel->index_tessellation = tess_index;
  522         polyBrepModel->is_closed = group.options.closed;
  523         if(same_color)
  524           polyBrepModel->index_of_line_style = style;
  525         part_definition->addPolyBrepModel(polyBrepModel);
  526       }
  527     }
  528 
  529     if(!group.quads.empty())
  530     {
  531       map<PRCVector3d,uint32_t> points;
  532       PRC3DTess *tess = new PRC3DTess();
  533       tess->crease_angle = group.options.crease_angle;
  534       PRCTessFace *tessFace = new PRCTessFace();
  535       tessFace->used_entities_flag=PRC_FACETESSDATA_Triangle;
  536       uint32_t triangles = 0;
  537 
  538       tessFace->is_rgba = false;
  539       for(PRCtessquadList::const_iterator qit=group.quads.begin(); qit!=group.quads.end(); qit++)
  540       {
  541         const RGBAColour* C = qit->colours;
  542         if(C[0].A != 1.0 || C[1].A != 1.0 || C[2].A != 1.0 || C[3].A != 1.0)
  543         {
  544           tessFace->is_rgba = true;
  545           break;
  546         }
  547       }
  548       bool same_colour = true;
  549       const RGBAColour& colour = group.quads.front().colours[0];
  550       for(PRCtessquadList::const_iterator qit=group.quads.begin(); qit!=group.quads.end(); qit++)
  551       {
  552         const RGBAColour* C = qit->colours;
  553         if(colour!=C[0] || colour!=C[1] || colour!=C[2] || colour!=C[3])
  554         {
  555           same_colour = false;
  556           break;
  557         }
  558       }
  559       
  560       for(PRCtessquadList::const_iterator qit=group.quads.begin(); qit!=group.quads.end(); qit++)
  561       {
  562         const RGBAColour* C = qit->colours;
  563         const bool degenerate = (qit->vertices[0]==qit->vertices[1]);
  564         uint32_t vertex_indices[4];
  565         for(size_t i = (degenerate?1:0); i < 4; ++i)
  566         {
  567           map<PRCVector3d,uint32_t>::const_iterator pPoint = points.find(qit->vertices[i]);
  568           if(pPoint!=points.end())
  569             vertex_indices[i] =  pPoint->second;
  570           else
  571           {
  572             points.insert(make_pair(qit->vertices[i],(vertex_indices[i] = tess->coordinates.size())));
  573             tess->coordinates.push_back(qit->vertices[i].x);
  574             tess->coordinates.push_back(qit->vertices[i].y);
  575             tess->coordinates.push_back(qit->vertices[i].z);
  576           }
  577         }
  578         if(degenerate)
  579         {
  580           tess->triangulated_index.push_back(vertex_indices[1]);
  581           tess->triangulated_index.push_back(vertex_indices[2]);
  582           tess->triangulated_index.push_back(vertex_indices[3]);
  583           triangles++;
  584           if(!same_colour)
  585           {
  586             tessFace->rgba_vertices.push_back(byte(C[1].R));
  587             tessFace->rgba_vertices.push_back(byte(C[1].G));
  588             tessFace->rgba_vertices.push_back(byte(C[1].B));
  589             if(tessFace->is_rgba)
  590               tessFace->rgba_vertices.push_back(byte(C[1].A));
  591             
  592             tessFace->rgba_vertices.push_back(byte(C[2].R));
  593             tessFace->rgba_vertices.push_back(byte(C[2].G));
  594             tessFace->rgba_vertices.push_back(byte(C[2].B));
  595             if(tessFace->is_rgba)
  596               tessFace->rgba_vertices.push_back(byte(C[2].A));
  597             
  598             tessFace->rgba_vertices.push_back(byte(C[3].R));
  599             tessFace->rgba_vertices.push_back(byte(C[3].G));
  600             tessFace->rgba_vertices.push_back(byte(C[3].B));
  601             if(tessFace->is_rgba)
  602               tessFace->rgba_vertices.push_back(byte(C[3].A));
  603           }
  604         }
  605         else
  606         {
  607           tess->triangulated_index.push_back(vertex_indices[0]);
  608           tess->triangulated_index.push_back(vertex_indices[2]);
  609           tess->triangulated_index.push_back(vertex_indices[3]);
  610           triangles++;
  611           if(!same_colour)
  612           {
  613             tessFace->rgba_vertices.push_back(byte(C[0].R));
  614             tessFace->rgba_vertices.push_back(byte(C[0].G));
  615             tessFace->rgba_vertices.push_back(byte(C[0].B));
  616             if(tessFace->is_rgba)
  617               tessFace->rgba_vertices.push_back(byte(C[0].A));
  618             
  619             tessFace->rgba_vertices.push_back(byte(C[2].R));
  620             tessFace->rgba_vertices.push_back(byte(C[2].G));
  621             tessFace->rgba_vertices.push_back(byte(C[2].B));
  622             if(tessFace->is_rgba)
  623               tessFace->rgba_vertices.push_back(byte(C[2].A));
  624             
  625             tessFace->rgba_vertices.push_back(byte(C[3].R));
  626             tessFace->rgba_vertices.push_back(byte(C[3].G));
  627             tessFace->rgba_vertices.push_back(byte(C[3].B));
  628             if(tessFace->is_rgba)
  629               tessFace->rgba_vertices.push_back(byte(C[3].A));
  630           }
  631           tess->triangulated_index.push_back(vertex_indices[3]);
  632           tess->triangulated_index.push_back(vertex_indices[1]);
  633           tess->triangulated_index.push_back(vertex_indices[0]);
  634           triangles++;
  635           if(!same_colour)
  636           {
  637             tessFace->rgba_vertices.push_back(byte(C[3].R));
  638             tessFace->rgba_vertices.push_back(byte(C[3].G));
  639             tessFace->rgba_vertices.push_back(byte(C[3].B));
  640             if(tessFace->is_rgba)
  641               tessFace->rgba_vertices.push_back(byte(C[3].A));
  642           
  643             tessFace->rgba_vertices.push_back(byte(C[1].R));
  644             tessFace->rgba_vertices.push_back(byte(C[1].G));
  645             tessFace->rgba_vertices.push_back(byte(C[1].B));
  646             if(tessFace->is_rgba)
  647               tessFace->rgba_vertices.push_back(byte(C[1].A));
  648           
  649             tessFace->rgba_vertices.push_back(byte(C[0].R));
  650             tessFace->rgba_vertices.push_back(byte(C[0].G));
  651             tessFace->rgba_vertices.push_back(byte(C[0].B));
  652             if(tessFace->is_rgba)
  653               tessFace->rgba_vertices.push_back(byte(C[0].A));
  654           }
  655         }
  656       }
  657       tessFace->sizes_triangulated.push_back(triangles);
  658       tess->addTessFace(tessFace);
  659       const uint32_t tess_index = add3DTess(tess);
  660       PRCPolyBrepModel *polyBrepModel = new PRCPolyBrepModel();
  661       polyBrepModel->index_tessellation = tess_index;
  662       polyBrepModel->is_closed = group.options.closed;
  663       if(same_colour)
  664         polyBrepModel->index_of_line_style = addColour(colour);
  665       part_definition->addPolyBrepModel(polyBrepModel);
  666     }
  667 
  668     if(!group.points.empty())
  669     {
  670       for(PRCpointsetMap::const_iterator pit=group.points.begin(); pit!=group.points.end(); pit++)
  671       {
  672         PRCPointSet *pointset = new PRCPointSet();
  673         pointset->index_of_line_style = pit->first;
  674         pointset->point = pit->second;
  675         part_definition->addPointSet(pointset);
  676       }
  677     }
  678 
  679     if(!group.pointsets.empty())
  680     {
  681       for(std::vector<PRCPointSet*>::iterator pit=group.pointsets.begin(); pit!=group.pointsets.end(); pit++)
  682       {
  683         part_definition->addPointSet(*pit);
  684       }
  685     }
  686 
  687     if(!group.polymodels.empty())
  688     {
  689       for(std::vector<PRCPolyBrepModel*>::iterator pit=group.polymodels.begin(); pit!=group.polymodels.end(); pit++)
  690       {
  691         (*pit)->is_closed = group.options.closed;
  692         part_definition->addPolyBrepModel(*pit);
  693       }
  694     }
  695 
  696     if(!group.polywires.empty())
  697     {
  698       for(std::vector<PRCPolyWire*>::iterator pit=group.polywires.begin(); pit!=group.polywires.end(); pit++)
  699       {
  700         part_definition->addPolyWire(*pit);
  701       }
  702     }
  703 
  704     if(!group.wires.empty())
  705     {
  706       PRCTopoContext *wireContext = NULL;
  707       const uint32_t context_index = getTopoContext(wireContext);
  708       for(PRCwireList::iterator wit=group.wires.begin(); wit!=group.wires.end(); wit++)
  709       {
  710         PRCWireEdge *wireEdge = new PRCWireEdge;
  711         wireEdge->curve_3d = wit->curve;
  712         PRCSingleWireBody *wireBody = new PRCSingleWireBody;
  713         wireBody->setWireEdge(wireEdge);
  714         const uint32_t wire_body_index = wireContext->addSingleWireBody(wireBody);
  715         PRCWire *wire = new PRCWire();
  716         wire->index_of_line_style = wit->style;
  717         wire->context_id = context_index;
  718         wire->body_id = wire_body_index;
  719         if(wit->transform)
  720             wire->index_local_coordinate_system = addTransform(wit->transform);
  721         part_definition->addWire(wire);
  722       }
  723     }
  724 
  725     PRCfaceList &faces = group.faces;
  726     if(!faces.empty())
  727     {
  728       bool same_color = true;
  729       const uint32_t style = faces.front().style;
  730       for(PRCfaceList::const_iterator fit=faces.begin(); fit!=faces.end(); fit++)
  731         if(style!=fit->style)
  732         {
  733           same_color = false;
  734           break;
  735         }
  736       PRCTopoContext *context = NULL;
  737       const uint32_t context_index = getTopoContext(context);
  738       context->granularity = group.options.granularity;
  739    // Acrobat 9 also does the following:
  740    // context->tolerance = group.options.granularity;
  741    // context->have_smallest_face_thickness = true;
  742    // context->smallest_thickness = group.options.granularity;
  743       PRCShell *shell = new PRCShell;
  744 
  745       for(PRCfaceList::iterator fit=faces.begin(); fit!=faces.end(); fit++)
  746       {
  747         if(fit->transform || group.options.do_break ||
  748            (fit->transparent && !group.options.no_break))
  749         {
  750           PRCShell *shell = new PRCShell;
  751           shell->addFace(fit->face);
  752           PRCConnex *connex = new PRCConnex;
  753           connex->addShell(shell);
  754           PRCBrepData *body = new PRCBrepData;
  755           body->addConnex(connex);
  756           const uint32_t body_index = context->addBrepData(body);
  757 
  758           PRCBrepModel *brepmodel = new PRCBrepModel();
  759           brepmodel->index_of_line_style = fit->style;
  760           brepmodel->context_id = context_index;
  761           brepmodel->body_id = body_index;
  762           brepmodel->is_closed = group.options.closed;
  763 
  764           brepmodel->index_local_coordinate_system = addTransform(fit->transform);
  765 
  766           part_definition->addBrepModel(brepmodel);
  767         }
  768         else
  769         {
  770           if(!same_color)
  771             fit->face->index_of_line_style = fit->style;
  772           shell->addFace(fit->face);
  773         }
  774       }
  775       if(shell->face.empty())
  776       {
  777         delete shell;
  778       }
  779       else
  780       {
  781         PRCConnex *connex = new PRCConnex;
  782         connex->addShell(shell);
  783         PRCBrepData *body = new PRCBrepData;
  784         body->addConnex(connex);
  785         const uint32_t body_index = context->addBrepData(body);
  786         PRCBrepModel *brepmodel = new PRCBrepModel();
  787         if(same_color)
  788           brepmodel->index_of_line_style = style;
  789         brepmodel->context_id = context_index;
  790         brepmodel->body_id = body_index;
  791         brepmodel->is_closed = group.options.closed;
  792         part_definition->addBrepModel(brepmodel);
  793       }
  794     }
  795 
  796     PRCcompfaceList &compfaces = group.compfaces;
  797     if(!compfaces.empty())
  798     {
  799       bool same_color = true;
  800       const uint32_t style = compfaces.front().style;
  801       for(PRCcompfaceList::const_iterator fit=compfaces.begin(); fit!=compfaces.end(); fit++)
  802         if(style!=fit->style)
  803         {
  804           same_color = false;
  805           break;
  806         }
  807       PRCTopoContext *context = NULL;
  808       const uint32_t context_index = getTopoContext(context);
  809       PRCCompressedBrepData *body = new PRCCompressedBrepData;
  810 
  811       body->serial_tolerance=group.options.compression;
  812       body->brep_data_compressed_tolerance=0.1*group.options.compression;
  813 
  814       for(PRCcompfaceList::const_iterator fit=compfaces.begin(); fit!=compfaces.end(); fit++)
  815       {
  816         if(group.options.do_break ||
  817            (fit->transparent && !group.options.no_break))
  818         {
  819           PRCCompressedBrepData *body = new PRCCompressedBrepData;
  820           body->face.push_back(fit->face);
  821 
  822           body->serial_tolerance=group.options.compression;
  823           body->brep_data_compressed_tolerance=2.8346456*
  824             group.options.compression;
  825           const uint32_t body_index = context->addCompressedBrepData(body);
  826 
  827           PRCBrepModel *brepmodel = new PRCBrepModel();
  828           brepmodel->index_of_line_style = fit->style;
  829           brepmodel->context_id = context_index;
  830           brepmodel->body_id = body_index;
  831           brepmodel->is_closed = group.options.closed;
  832 
  833           part_definition->addBrepModel(brepmodel);
  834         }
  835         else
  836         {
  837           if(!same_color)
  838             fit->face->index_of_line_style = fit->style;
  839           body->face.push_back(fit->face);
  840         }
  841       }
  842       if(body->face.empty())
  843       {
  844         delete body;
  845       }
  846       else
  847       {
  848         const uint32_t body_index = context->addCompressedBrepData(body);
  849         PRCBrepModel *brepmodel = new PRCBrepModel();
  850         if(same_color)
  851           brepmodel->index_of_line_style = style;
  852         brepmodel->context_id = context_index;
  853         brepmodel->body_id = body_index;
  854         brepmodel->is_closed = group.options.closed;
  855         part_definition->addBrepModel(brepmodel);
  856       }
  857     }
  858 
  859     // Simplify and reduce to as simple entities as possible
  860     // products with named representation items can not be reduced to sets, since 
  861     // outside references are already set
  862     bool nonamedparts = true;
  863     for(PRCRepresentationItemList::const_iterator it=part_definition->representation_item.begin(); it!=part_definition->representation_item.end(); it++)
  864     {
  865       if (!(*it)->name.empty())
  866       {
  867         nonamedparts = false;
  868         break;
  869     }
  870     }
  871     lastgroupname.clear();
  872     lastgroupnames.clear();
  873     // First option - reduce to one element in parent
  874     if (parent_part_definition && product_occurrence->index_son_occurrence.empty() &&
  875         part_definition->representation_item.size() == 1 &&
  876         ( name.empty() || part_definition->representation_item.front()->name.empty() ) &&
  877         ( !group.transform  || part_definition->representation_item.front()->index_local_coordinate_system==m1) )
  878     {
  879       if(part_definition->representation_item.front()->name.empty() )
  880         part_definition->representation_item.front()->name = name;
  881       if(part_definition->representation_item.front()->index_local_coordinate_system==m1)
  882         part_definition->representation_item.front()->index_local_coordinate_system = addTransform(group.transform);
  883       lastgroupname = calculate_unique_name(part_definition->representation_item.front(), parent_product_occurrence);
  884       parent_part_definition->addRepresentationItem(part_definition->representation_item.front());
  885       part_definition->representation_item.clear();
  886       delete product_occurrence; product_occurrence = NULL;
  887       delete part_definition; part_definition = NULL;
  888     }
  889     // Second option - reduce to a set
  890     else if (parent_part_definition && product_occurrence->index_son_occurrence.empty() &&
  891       !part_definition->representation_item.empty() &&
  892       !group.options.do_break && nonamedparts)
  893     {
  894       PRCSet *set = new PRCSet(name);
  895       set->index_local_coordinate_system = addTransform(group.transform);
  896       lastgroupname = calculate_unique_name(set, parent_product_occurrence);
  897       for(PRCRepresentationItemList::iterator it=part_definition->representation_item.begin(); it!=part_definition->representation_item.end(); it++)
  898       {
  899         lastgroupnames.push_back(calculate_unique_name(*it, parent_product_occurrence));
  900         set->addRepresentationItem(*it);
  901       }
  902       part_definition->representation_item.clear();
  903       parent_part_definition->addSet(set);
  904       delete product_occurrence; product_occurrence = NULL;
  905       delete part_definition; part_definition = NULL;
  906     }
  907     // Third option - create product
  908     else if ( !product_occurrence->index_son_occurrence.empty() || !part_definition->representation_item.empty())
  909     {
  910       // if everything is enclosed in one group - drop the root group
  911       if (parent_product_occurrence == NULL && group.transform == NULL &&
  912           part_definition->representation_item.empty() && product_occurrence->index_son_occurrence.size()==1) {
  913         delete part_definition; part_definition = NULL;
  914         delete product_occurrence; product_occurrence = NULL;
  915       }
  916       else
  917       {
  918         lastgroupname = calculate_unique_name(product_occurrence, NULL);
  919         if (part_definition->representation_item.empty()) {
  920           delete part_definition; part_definition = NULL;
  921         }
  922       else
  923         {
  924           for(PRCRepresentationItemList::const_iterator it=part_definition->representation_item.begin(); it!=part_definition->representation_item.end(); it++)
  925             if ((*it)->name.empty())
  926               lastgroupnames.push_back(calculate_unique_name(*it, product_occurrence));
  927         product_occurrence->index_part = addPartDefinition(part_definition);
  928         }
  929       if (group.transform) {
  930         product_occurrence->location = group.transform;
  931         group.transform = NULL;
  932       }
  933       if (parent_product_occurrence) {
  934         parent_product_occurrence->index_son_occurrence.push_back(addProductOccurrence(product_occurrence));
  935       }
  936       else {
  937         addProductOccurrence(product_occurrence);
  938       }
  939     }
  940     }
  941     // Last case - absolutely nothing to do
  942     else
  943     {
  944       delete product_occurrence; product_occurrence = NULL;
  945       delete part_definition; part_definition = NULL;
  946     }
  947 
  948 }
  949 
  950 std::string oPRCFile::calculate_unique_name(const ContentPRCBase *prc_entity,const ContentPRCBase *prc_occurence)
  951 {
  952   std::stringstream ss (std::stringstream::in | std::stringstream::out);
  953   uint8_t *serialization_buffer = NULL;
  954   PRCbitStream serialization(serialization_buffer,0u);
  955   const PRCFileStructure *pfile_structure = fileStructures[0];
  956   const PRCUniqueId& uuid = pfile_structure->file_structure_uuid;
  957 // ConvertUniqueIdentifierToString (prc_entity)
  958 // SerializeCompressedUniqueId (file_structure)
  959   serialization << uuid.id0 << uuid.id1 << uuid.id2 << uuid.id3;
  960 // WriteUnsignedInteger (type)
  961   serialization << prc_entity->getType();
  962 // WriteUnsignedInteger (unique_identifier)
  963   serialization << prc_entity->getPRCID();
  964   if (prc_occurence)
  965   {
  966 // serialization_buffer = Flush serialization (serialization) 
  967   {
  968     const uint32_t size_serialization = serialization.getSize();
  969     while(size_serialization == serialization.getSize())
  970       serialization << false;
  971   }
  972 // ConvertUniqueIdentifierToString (prc_occurrence_unique_id)
  973 // SerializeCompressedUniqueId (file_structure)
  974     serialization << uuid.id0 << uuid.id1 << uuid.id2 << uuid.id3;
  975 // WriteUnsignedInteger (type)
  976     serialization << (uint32_t)PRC_TYPE_ASM_ProductOccurence;
  977 // WriteUnsignedInteger (unique_identifier)
  978     serialization << prc_occurence->getPRCID();
  979   }
  980   ss << (prc_entity->name.empty()?"node":prc_entity->name) << '.';
  981   const uint32_t size_serialization = serialization.getSize();
  982   for(size_t j=0; j<size_serialization; j++)
  983     ss << hex << setfill('0') << setw(2) << (uint32_t)(serialization_buffer[j]);
  984 
  985   return ss.str();
  986 }
  987 
  988 bool oPRCFile::finish()
  989 {
  990   if(groups.size()!=1) {
  991     fputs("begingroup without matching endgroup",stderr);
  992     exit(1);
  993   }
  994   doGroup(groups.top());
  995 
  996   // write each section's bit data
  997   fileStructures[0]->prepare();
  998   SerializeModelFileData
  999 
 1000   // create the header
 1001 
 1002   // fill out enough info so that sizes can be computed correctly
 1003   header.number_of_file_structures = number_of_file_structures;
 1004   header.fileStructureInformation = new PRCFileStructureInformation[number_of_file_structures];
 1005   for(uint32_t i = 0; i < number_of_file_structures; ++i)
 1006   {
 1007     header.fileStructureInformation[i].UUID = fileStructures[i]->file_structure_uuid;
 1008     header.fileStructureInformation[i].reserved = 0;
 1009     header.fileStructureInformation[i].number_of_offsets = 6;
 1010     header.fileStructureInformation[i].offsets = new uint32_t[6];
 1011   }
 1012 
 1013   header.minimal_version_for_read = PRCVersion;
 1014   header.authoring_version = PRCVersion;
 1015   makeFileUUID(header.file_structure_uuid);
 1016   makeAppUUID(header.application_uuid);
 1017 
 1018   header.file_size = getSize();
 1019   header.model_file_offset = header.file_size - modelFile_out.getSize();
 1020 
 1021   uint32_t currentOffset = header.getSize();
 1022 
 1023   for(uint32_t i = 0; i < number_of_file_structures; ++i)
 1024   {
 1025     for(size_t j=0; j<6; j++)
 1026     {
 1027       header.fileStructureInformation[i].offsets[j] = currentOffset;
 1028       currentOffset += fileStructures[i]->sizes[j];
 1029     }
 1030   }
 1031 
 1032   // write the data
 1033   header.write(output);
 1034 
 1035   for(uint32_t i = 0; i < number_of_file_structures; ++i)
 1036   {
 1037     fileStructures[i]->write(output);
 1038   }
 1039 
 1040   modelFile_out.write(output);
 1041   output.flush();
 1042 
 1043   for(uint32_t i = 0; i < number_of_file_structures; ++i)
 1044     delete[] header.fileStructureInformation[i].offsets;
 1045   delete[] header.fileStructureInformation;
 1046 
 1047   return true;
 1048 }
 1049 
 1050 uint32_t oPRCFile::getSize()
 1051 {
 1052   uint32_t size = header.getSize();
 1053 
 1054   for(uint32_t i = 0; i < number_of_file_structures; ++i)
 1055   {
 1056     size += fileStructures[i]->getSize();
 1057   }
 1058 
 1059   size += modelFile_out.getSize();
 1060   return size;
 1061 }
 1062 
 1063 uint32_t PRCFileStructure::addPicture(EPRCPictureDataFormat format, uint32_t size, const uint8_t *p, uint32_t width, uint32_t height, std::string name)
 1064 {
 1065   uint8_t *data = NULL;
 1066   uint32_t components=0;
 1067   PRCPicture picture(name);
 1068   if(size==0 || p==NULL)
 1069     { cerr << "image not set" << endl; return m1; }
 1070   PRCUncompressedFile* uncompressed_file = new PRCUncompressedFile;
 1071   if(format==KEPRCPicture_PNG || format==KEPRCPicture_JPG)
 1072   {
 1073     data = new uint8_t[size];
 1074     memcpy(data, p, size);
 1075     uncompressed_files.push_back(uncompressed_file);
 1076     uncompressed_files.back()->file_size = size;
 1077     uncompressed_files.back()->data = data;
 1078     picture.format = format;
 1079     picture.uncompressed_file_index = uncompressed_files.size()-1;
 1080     picture.pixel_width = 0; // width and height are ignored for JPG and PNG pictures - but let us keep things clean
 1081     picture.pixel_height = 0;
 1082     pictures.push_back(picture);
 1083     return pictures.size()-1;
 1084   }
 1085 
 1086   switch(format)
 1087   {
 1088     case KEPRCPicture_BITMAP_RGB_BYTE:
 1089       components = 3; break;
 1090     case KEPRCPicture_BITMAP_RGBA_BYTE:
 1091       components = 4; break;
 1092     case KEPRCPicture_BITMAP_GREY_BYTE:
 1093       components = 1; break;
 1094     case KEPRCPicture_BITMAP_GREYA_BYTE:
 1095       components = 2; break;
 1096     default:
 1097       { cerr << "unknown picture format" << endl; return m1; }
 1098   }
 1099       if(width==0 || height==0)
 1100         { cerr << "width or height parameter not set" << endl; return m1; }
 1101       if (size < width*height*components)
 1102         { cerr << "image too small" << endl; return m1; }
 1103 
 1104       {
 1105         uint32_t compressedDataSize = 0;
 1106         const int CHUNK= 1024; // is this reasonable?
 1107 
 1108         z_stream strm;
 1109         strm.zalloc = Z_NULL;
 1110         strm.zfree = Z_NULL;
 1111         strm.opaque = Z_NULL;
 1112         if(deflateInit(&strm,Z_DEFAULT_COMPRESSION) != Z_OK)
 1113           { cerr << "Compression initialization failed" << endl; return m1; }
 1114         unsigned int sizeAvailable = deflateBound(&strm,size);
 1115         uint8_t *compressedData = (uint8_t*) malloc(sizeAvailable);
 1116         strm.avail_in = size;
 1117         strm.next_in = (unsigned char*)p;
 1118         strm.next_out = (unsigned char*)compressedData;
 1119         strm.avail_out = sizeAvailable;
 1120 
 1121         int code;
 1122         unsigned int chunks = 0;
 1123         while((code = deflate(&strm,Z_FINISH)) == Z_OK)
 1124         {
 1125           ++chunks;
 1126           // strm.avail_out should be 0 if we got Z_OK
 1127           compressedDataSize = sizeAvailable - strm.avail_out;
 1128           compressedData = (uint8_t*) realloc(compressedData,CHUNK*chunks);
 1129           strm.next_out = (Bytef*)(compressedData + compressedDataSize);
 1130           strm.avail_out += CHUNK;
 1131           sizeAvailable += CHUNK;
 1132         }
 1133         compressedDataSize = sizeAvailable-strm.avail_out;
 1134 
 1135         if(code != Z_STREAM_END)
 1136         {
 1137           deflateEnd(&strm);
 1138           free(compressedData);
 1139           { cerr << "Compression error" << endl; return m1; }
 1140         }
 1141 
 1142         deflateEnd(&strm);
 1143         size = compressedDataSize;
 1144         data = new uint8_t[compressedDataSize];
 1145         memcpy(data, compressedData, compressedDataSize);
 1146         free(compressedData);
 1147       }
 1148       uncompressed_files.push_back(uncompressed_file);
 1149       uncompressed_files.back()->file_size = size;
 1150       uncompressed_files.back()->data = data;
 1151       picture.format = format;
 1152       picture.uncompressed_file_index = uncompressed_files.size()-1;
 1153       picture.pixel_width = width;
 1154       picture.pixel_height = height;
 1155       pictures.push_back(picture);
 1156       return pictures.size()-1;
 1157 }
 1158 
 1159 uint32_t PRCFileStructure::addTextureDefinition(PRCTextureDefinition*& pTextureDefinition)
 1160 {
 1161   texture_definitions.push_back(pTextureDefinition);
 1162   pTextureDefinition = NULL;
 1163   return texture_definitions.size()-1;
 1164 }
 1165 
 1166 uint32_t PRCFileStructure::addRgbColor(const PRCRgbColor &color)
 1167 {
 1168   colors.push_back(color);
 1169   return 3*(colors.size()-1);
 1170 }
 1171 
 1172 uint32_t PRCFileStructure::addRgbColorUnique(const PRCRgbColor &color)
 1173 {
 1174   for(uint32_t i = 0; i < colors.size(); ++i)
 1175   {
 1176     if(colors[i] == color)
 1177       return 3*i;
 1178   }
 1179   colors.push_back(color);
 1180   return 3*(colors.size()-1);
 1181 }
 1182 
 1183 uint32_t oPRCFile::addColor(const PRCRgbColor &color)
 1184 {
 1185   PRCcolorMap::const_iterator pColor = colorMap.find(color);
 1186   if(pColor!=colorMap.end())
 1187     return pColor->second;
 1188 //  color_index = addRgbColorUnique(color);
 1189   const uint32_t color_index = fileStructures[0]->addRgbColor(color);
 1190   colorMap.insert(make_pair(color,color_index));
 1191   return color_index;
 1192 }
 1193 
 1194 uint32_t oPRCFile::addColour(const RGBAColour &colour)
 1195 {
 1196   PRCcolourMap::const_iterator pColour = colourMap.find(colour);
 1197   if(pColour!=colourMap.end())
 1198     return pColour->second;
 1199   const uint32_t color_index = addColor(PRCRgbColor(colour.R, colour.G, colour.B));
 1200   PRCStyle *style = new PRCStyle();
 1201   style->line_width = 1.0;
 1202   style->is_vpicture = false;
 1203   style->line_pattern_vpicture_index = 0;
 1204   style->is_material = false;
 1205   style->color_material_index = color_index;
 1206   style->is_transparency_defined = (colour.A < 1.0);
 1207   style->transparency = (uint8_t)(colour.A * 256);
 1208   style->additional = 0;
 1209   const uint32_t style_index = fileStructures[0]->addStyle(style);
 1210   colourMap.insert(make_pair(colour,style_index));
 1211   return style_index;
 1212 }
 1213 
 1214 uint32_t oPRCFile::addColourWidth(const RGBAColour &colour, double width)
 1215 {
 1216   RGBAColourWidth colourwidth(colour.R, colour.G, colour.B, colour.A, width);
 1217   PRCcolourwidthMap::const_iterator pColour = colourwidthMap.find(colourwidth);
 1218   if(pColour!=colourwidthMap.end())
 1219     return pColour->second;
 1220   const uint32_t color_index = addColor(PRCRgbColor(colour.R, colour.G, colour.B));
 1221   PRCStyle *style = new PRCStyle();
 1222   style->line_width = width;
 1223   style->is_vpicture = false;
 1224   style->line_pattern_vpicture_index = 0;
 1225   style->is_material = false;
 1226   style->color_material_index = color_index;
 1227   style->is_transparency_defined = (colour.A < 1.0);
 1228   style->transparency = (uint8_t)(colour.A * 256);
 1229   style->additional = 0;
 1230   const uint32_t style_index = fileStructures[0]->addStyle(style);
 1231   colourwidthMap.insert(make_pair(colourwidth,style_index));
 1232   return style_index;
 1233 }
 1234 
 1235 uint32_t oPRCFile::addTransform(PRCGeneralTransformation3d*& transform)
 1236 {
 1237   if(!transform)
 1238     return m1;
 1239   PRCtransformMap::const_iterator pTransform = transformMap.find(*transform);
 1240   if(pTransform!=transformMap.end())
 1241     return pTransform->second;
 1242   PRCCoordinateSystem *coordinateSystem = new PRCCoordinateSystem();
 1243   bool transform_replaced = false;
 1244   if(                         transform->M(0,1)==0 && transform->M(0,2)==0 &&
 1245       transform->M(1,0)==0 &&                         transform->M(1,2)==0 &&
 1246       transform->M(2,0)==0 && transform->M(2,1)==0 &&
 1247       transform->M(3,0)==0 && transform->M(3,1)==0 && transform->M(3,2)==0 && transform->M(3,3)==1 )
 1248   {
 1249     transform_replaced = true;
 1250     PRCCartesianTransformation3d *carttransform = new PRCCartesianTransformation3d;
 1251 //  if(transform->M(0,3)==0 && transform->M(1,3)==0 && transform->M(1,3)==0 &&
 1252 //     transform->M(0,0)==1 && transform->M(1,1)==1 && transform->M(2,2)==1 )
 1253 //    carttransform->behaviour = PRC_TRANSFORMATION_Identity;
 1254     if(transform->M(0,3)!=0 || transform->M(1,3)!=0 || transform->M(2,3)!=0)
 1255     {
 1256       carttransform->behaviour |= PRC_TRANSFORMATION_Translate;
 1257       carttransform->origin.Set(transform->M(0,3),transform->M(1,3),transform->M(2,3));
 1258     }
 1259     if(transform->M(0,0)!=transform->M(1,1) || transform->M(0,0)!=transform->M(2,2))
 1260     {
 1261       carttransform->behaviour |= PRC_TRANSFORMATION_NonUniformScale;
 1262       carttransform->scale.Set(transform->M(0,0),transform->M(1,1),transform->M(2,2));
 1263     }
 1264     else
 1265       if(transform->M(0,0)!=1)
 1266       {
 1267         carttransform->behaviour |= PRC_TRANSFORMATION_Scale;
 1268         carttransform->uniform_scale=transform->M(0,0);
 1269       }
 1270     coordinateSystem->axis_set = carttransform;
 1271   }
 1272   else
 1273   coordinateSystem->axis_set = transform;
 1274   const uint32_t coordinate_system_index = fileStructures[0]->addCoordinateSystem(coordinateSystem);
 1275   transformMap.insert(make_pair(*transform,coordinate_system_index));
 1276   if(transform_replaced)
 1277     delete transform;
 1278   transform = NULL;
 1279   return coordinate_system_index;
 1280 }
 1281 
 1282 uint32_t oPRCFile::addTransform(const double* t)
 1283 {
 1284   if(!t)
 1285     return m1;
 1286   PRCGeneralTransformation3d* transform = new PRCGeneralTransformation3d(t);
 1287   return addTransform(transform);
 1288 }
 1289 
 1290 uint32_t oPRCFile::addTransform(const double origin[3], const double x_axis[3], const double y_axis[3], double scale)
 1291 {
 1292   PRCCartesianTransformation3d* transform = new PRCCartesianTransformation3d(origin, x_axis, y_axis, scale);
 1293   if(transform->behaviour==PRC_TRANSFORMATION_Identity)
 1294     return m1;
 1295   PRCCoordinateSystem *coordinateSystem = new PRCCoordinateSystem();
 1296   coordinateSystem->axis_set = transform;
 1297   const uint32_t coordinate_system_index = fileStructures[0]->addCoordinateSystem(coordinateSystem);
 1298   return coordinate_system_index;
 1299 }
 1300 
 1301 uint32_t oPRCFile::addMaterial(const PRCmaterial& m)
 1302 {
 1303   uint32_t material_index = m1;
 1304   const PRCmaterialgeneric materialgeneric(m);
 1305   PRCmaterialgenericMap::const_iterator pMaterialgeneric = materialgenericMap.find(materialgeneric);
 1306   if(pMaterialgeneric!=materialgenericMap.end())
 1307     material_index = pMaterialgeneric->second;
 1308   else
 1309 {
 1310   PRCMaterialGeneric *materialGeneric = new PRCMaterialGeneric();
 1311   const PRCRgbColor ambient(m.ambient.R, m.ambient.G, m.ambient.B);
 1312   materialGeneric->ambient = addColor(ambient);
 1313     const PRCRgbColor diffuse(m.diffuse.R, m.diffuse.G, m.diffuse.B);
 1314   materialGeneric->diffuse = addColor(diffuse);
 1315     const PRCRgbColor emissive(m.emissive.R, m.emissive.G, m.emissive.B);
 1316 
 1317   materialGeneric->emissive = addColor(emissive);
 1318     const PRCRgbColor specular(m.specular.R, m.specular.G, m.specular.B);
 1319   materialGeneric->specular = addColor(specular);
 1320 
 1321     materialGeneric->shininess = m.shininess;
 1322     materialGeneric->ambient_alpha = m.ambient.A;
 1323     materialGeneric->diffuse_alpha = m.diffuse.A;
 1324     materialGeneric->emissive_alpha = m.emissive.A;
 1325     materialGeneric->specular_alpha = m.specular.A;
 1326     material_index = addMaterialGeneric(materialGeneric);
 1327     materialgenericMap.insert(make_pair(materialgeneric,material_index));
 1328   }
 1329   uint32_t color_material_index = m1;
 1330   if(m.picture_data!=NULL)
 1331   {
 1332     uint32_t picture_index = m1;
 1333     PRCpicture picture(m);
 1334     PRCpictureMap::const_iterator pPicture = pictureMap.find(picture);
 1335     if(pPicture!=pictureMap.end())
 1336       picture_index = pPicture->second;
 1337     else
 1338     {
 1339       picture_index = addPicture(picture);
 1340       uint8_t* data = new uint8_t[picture.size];
 1341       memcpy(data,picture.data,picture.size);
 1342       picture.data = data;
 1343       pictureMap.insert(make_pair(picture,picture_index));
 1344     }
 1345 
 1346     uint32_t texture_definition_index = m1;
 1347     PRCtexturedefinition texturedefinition(picture_index, m);
 1348     PRCtexturedefinitionMap::const_iterator pTexturedefinition = texturedefinitionMap.find(texturedefinition);
 1349     if(pTexturedefinition!=texturedefinitionMap.end())
 1350       texture_definition_index = pTexturedefinition->second;
 1351     else
 1352     {
 1353       PRCTextureDefinition *TextureDefinition = new PRCTextureDefinition;
 1354       if (m.picture_size==216688 && m.picture_format==KEPRCPicture_JPG)
 1355         TextureDefinition->texture_mapping_attribute=PRC_TEXTURE_MAPPING_OPACITY;
 1356       TextureDefinition->picture_index = picture_index;
 1357       TextureDefinition->texture_function = m.picture_replace ? KEPRCTextureFunction_Replace : KEPRCTextureFunction_Modulate;
 1358       TextureDefinition->texture_wrapping_mode_S = m.picture_repeat ? KEPRCTextureWrappingMode_Repeat : KEPRCTextureWrappingMode_ClampToEdge;
 1359       TextureDefinition->texture_wrapping_mode_T = m.picture_repeat ? KEPRCTextureWrappingMode_Repeat : KEPRCTextureWrappingMode_ClampToEdge;
 1360       TextureDefinition->texture_mapping_attribute_components = (m.picture_format==KEPRCPicture_BITMAP_RGB_BYTE || m.picture_format==KEPRCPicture_JPG) ? PRC_TEXTURE_MAPPING_COMPONENTS_RGB : PRC_TEXTURE_MAPPING_COMPONENTS_RGBA;
 1361       texture_definition_index = addTextureDefinition(TextureDefinition);
 1362       texturedefinitionMap.insert(make_pair(texturedefinition,texture_definition_index));
 1363     }
 1364 
 1365     uint32_t texture_application_index = m1;
 1366     const PRCtextureapplication textureapplication(material_index, texture_definition_index);
 1367     PRCtextureapplicationMap::const_iterator pTextureapplication = textureapplicationMap.find(textureapplication);
 1368     if(pTextureapplication!=textureapplicationMap.end())
 1369       texture_application_index = pTextureapplication->second;
 1370     else
 1371     {
 1372       PRCTextureApplication *TextureApplication = new PRCTextureApplication;
 1373       TextureApplication->material_generic_index = material_index;
 1374       TextureApplication->texture_definition_index = texture_definition_index;
 1375       texture_application_index = addTextureApplication(TextureApplication);
 1376       textureapplicationMap.insert(make_pair(textureapplication,texture_application_index));
 1377     }
 1378 
 1379     color_material_index = texture_application_index;
 1380   }
 1381   else
 1382     color_material_index = material_index;
 1383 
 1384   uint32_t style_index = m1;
 1385   PRCstyle style(0,m.alpha,true,color_material_index);
 1386   PRCstyleMap::const_iterator pStyle = styleMap.find(style);
 1387   if(pStyle!=styleMap.end())
 1388     style_index = pStyle->second;
 1389   else
 1390   {
 1391     PRCStyle *Style = new PRCStyle();
 1392     Style->line_width = 0.0;
 1393     Style->is_vpicture = false;
 1394     Style->line_pattern_vpicture_index = 0;
 1395     Style->is_material = true;
 1396     Style->is_transparency_defined = (m.alpha < 1.0);
 1397     Style->transparency = (uint8_t)(m.alpha * 256);
 1398     Style->additional = 0;
 1399     Style->color_material_index = color_material_index;
 1400     style_index = addStyle(Style);
 1401     styleMap.insert(make_pair(style,style_index));
 1402   }
 1403 //  materialMap.insert(make_pair(material,style_index));
 1404    return style_index;
 1405 }
 1406 
 1407 void oPRCFile::begingroup(const char *name, PRCoptions *options,
 1408                           const double* t)
 1409 {
 1410   const PRCgroup &parent_group = groups.top();
 1411   groups.push(PRCgroup());
 1412   PRCgroup &group = groups.top();
 1413   group.name=name;
 1414   if(options) group.options=*options;
 1415   if(t&&!isid(t))
 1416     group.transform = new PRCGeneralTransformation3d(t);
 1417   group.product_occurrence = new PRCProductOccurrence(name);
 1418   group.parent_product_occurrence = parent_group.product_occurrence;
 1419   group.part_definition = new PRCPartDefinition;
 1420   group.parent_part_definition = parent_group.part_definition;
 1421 }
 1422 
 1423 void oPRCFile::endgroup()
 1424 {
 1425   if(groups.size()<2) {
 1426     fputs("begingroup without matching endgroup",stderr);
 1427     exit(1);
 1428   }
 1429   doGroup(groups.top());
 1430   groups.pop();
 1431 
 1432 // std::cout << lastgroupname << std::endl;
 1433 // for(std::vector<std::string>::const_iterator it=lastgroupnames.begin(); it!=lastgroupnames.end(); it++)
 1434 //   std::cout << " " << *it << std::endl;
 1435 
 1436 }
 1437 
 1438 PRCgroup& oPRCFile::findGroup()
 1439 {
 1440   return groups.top();
 1441 }
 1442 
 1443 void oPRCFile::addPoints(uint32_t n, const double P[][3], const RGBAColour &c, double w)
 1444 {
 1445   if(n==0 || P==NULL)
 1446      return;
 1447   PRCgroup &group = findGroup();
 1448   PRCPointSet *pointset = new PRCPointSet();
 1449   group.pointsets.push_back(pointset);
 1450   pointset->index_of_line_style = addColourWidth(c,w);
 1451   pointset->point.reserve(n);
 1452   for(uint32_t i=0; i<n; i++)
 1453     pointset->point.push_back(PRCVector3d(P[i][0],P[i][1],P[i][2]));
 1454 }
 1455 
 1456 void oPRCFile::useMesh(uint32_t tess_index, uint32_t style_index, const double origin[3], const double x_axis[3], const double y_axis[3], double scale)
 1457 {
 1458   PRCgroup &group = findGroup();
 1459   PRCPolyBrepModel *polyBrepModel = new PRCPolyBrepModel();
 1460   polyBrepModel->index_local_coordinate_system = addTransform(origin, x_axis, y_axis, scale);
 1461   polyBrepModel->index_tessellation = tess_index;
 1462   polyBrepModel->is_closed = group.options.closed;
 1463   polyBrepModel->index_of_line_style = style_index;
 1464   group.polymodels.push_back(polyBrepModel);
 1465 }
 1466 
 1467 void oPRCFile::useMesh(uint32_t tess_index, uint32_t style_index, const double* t)
 1468 {
 1469   PRCgroup &group = findGroup();
 1470   PRCPolyBrepModel *polyBrepModel = new PRCPolyBrepModel();
 1471   polyBrepModel->index_local_coordinate_system = addTransform(t);
 1472   polyBrepModel->index_tessellation = tess_index;
 1473   polyBrepModel->is_closed = group.options.closed;
 1474   polyBrepModel->index_of_line_style = style_index;
 1475   group.polymodels.push_back(polyBrepModel);
 1476 }
 1477 
 1478 void oPRCFile::useLines(uint32_t tess_index, uint32_t style_index, const double origin[3], const double x_axis[3], const double y_axis[3], double scale)
 1479 {
 1480   PRCgroup &group = findGroup();
 1481   PRCPolyWire *polyWire = new PRCPolyWire();
 1482   polyWire->index_local_coordinate_system = addTransform(origin, x_axis, y_axis, scale);
 1483   polyWire->index_tessellation = tess_index;
 1484   polyWire->index_of_line_style = style_index;
 1485   group.polywires.push_back(polyWire);
 1486 }
 1487 
 1488 void oPRCFile::useLines(uint32_t tess_index, uint32_t style_index, const double* t)
 1489 {
 1490   PRCgroup &group = findGroup();
 1491   PRCPolyWire *polyWire = new PRCPolyWire();
 1492   polyWire->index_local_coordinate_system = addTransform(t);
 1493   polyWire->index_tessellation = tess_index;
 1494   polyWire->index_of_line_style = style_index;
 1495   group.polywires.push_back(polyWire);
 1496 }
 1497 
 1498 void oPRCFile::addQuads(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][4], const PRCmaterial &m,
 1499  uint32_t nN, const double N[][3],   const uint32_t NI[][4],
 1500  uint32_t nT, const double T[][2],   const uint32_t TI[][4],
 1501  uint32_t nC, const RGBAColour C[],  const uint32_t CI[][4],
 1502  uint32_t nM, const PRCmaterial M[], const uint32_t MI[], double ca)
 1503 {
 1504   if(nP==0 || P==NULL || nI==0 || PI==NULL)
 1505      return;
 1506   const uint32_t tess_index = createQuadMesh(nP, P, nI, PI, m, nN, N, NI, nT, T, TI, nC, C, CI, nM, M, MI, ca);
 1507   useMesh(tess_index,m1);
 1508 }
 1509 
 1510 uint32_t oPRCFile::createQuadMesh(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][4], uint32_t style_index,
 1511  uint32_t nN, const double N[][3],   const uint32_t NI[][4],
 1512  uint32_t nT, const double T[][2],   const uint32_t TI[][4],
 1513  uint32_t nC, const RGBAColour C[],  const uint32_t CI[][4],
 1514  uint32_t nS, const uint32_t S[],    const uint32_t SI[], double ca)
 1515 {
 1516   if(nP==0 || P==NULL || nI==0 || PI==NULL)
 1517      return m1;
 1518 
 1519   const bool triangle_color = (nS != 0 && S != NULL && SI != NULL);
 1520   const bool vertex_color   = (nC != 0 && C != NULL && CI != NULL);
 1521   const bool has_normals    = (nN != 0 && N != NULL && NI != NULL);
 1522   const bool textured       = (nT != 0 && T != NULL && TI != NULL);
 1523 
 1524   PRC3DTess *tess = new PRC3DTess();
 1525   PRCTessFace *tessFace = new PRCTessFace();
 1526   tessFace->used_entities_flag = textured ? PRC_FACETESSDATA_TriangleTextured : PRC_FACETESSDATA_Triangle;
 1527   tessFace->number_of_texture_coordinate_indexes = textured ? 1 : 0;
 1528   tess->coordinates.reserve(3*nP);
 1529   for(uint32_t i=0; i<nP; i++)
 1530   {
 1531     tess->coordinates.push_back(P[i][0]);
 1532     tess->coordinates.push_back(P[i][1]);
 1533     tess->coordinates.push_back(P[i][2]);
 1534   }
 1535   if(has_normals)
 1536   {
 1537     tess->normal_coordinate.reserve(3*nN);
 1538   for(uint32_t i=0; i<nN; i++)
 1539   {
 1540     tess->normal_coordinate.push_back(N[i][0]);
 1541     tess->normal_coordinate.push_back(N[i][1]);
 1542     tess->normal_coordinate.push_back(N[i][2]);
 1543   }
 1544   }
 1545   else
 1546     tess->crease_angle = ca;
 1547   if(textured)
 1548   {
 1549     tess->texture_coordinate.reserve(2*nT);
 1550   for(uint32_t i=0; i<nT; i++)
 1551   {
 1552     tess->texture_coordinate.push_back(T[i][0]);
 1553     tess->texture_coordinate.push_back(T[i][1]);
 1554   }
 1555   }
 1556   tess->triangulated_index.reserve(2*(3*nI+(has_normals?3:0)*nI+(textured?3:0)*nI));
 1557   for(uint32_t i=0; i<nI; i++)
 1558   {
 1559     // first triangle
 1560     if(has_normals)
 1561     tess->triangulated_index.push_back(3*NI[i][0]);
 1562     if(textured)
 1563     tess->triangulated_index.push_back(2*TI[i][0]);
 1564     tess->triangulated_index.push_back(3*PI[i][0]);
 1565     if(has_normals)
 1566     tess->triangulated_index.push_back(3*NI[i][1]);
 1567     if(textured)
 1568     tess->triangulated_index.push_back(2*TI[i][1]);
 1569     tess->triangulated_index.push_back(3*PI[i][1]);
 1570     if(has_normals)
 1571     tess->triangulated_index.push_back(3*NI[i][3]);
 1572     if(textured)
 1573     tess->triangulated_index.push_back(2*TI[i][3]);
 1574     tess->triangulated_index.push_back(3*PI[i][3]);
 1575     // second triangle
 1576     if(has_normals)
 1577     tess->triangulated_index.push_back(3*NI[i][1]);
 1578     if(textured)
 1579     tess->triangulated_index.push_back(2*TI[i][1]);
 1580     tess->triangulated_index.push_back(3*PI[i][1]);
 1581     if(has_normals)
 1582     tess->triangulated_index.push_back(3*NI[i][2]);
 1583     if(textured)
 1584     tess->triangulated_index.push_back(2*TI[i][2]);
 1585     tess->triangulated_index.push_back(3*PI[i][2]);
 1586     if(has_normals)
 1587     tess->triangulated_index.push_back(3*NI[i][3]);
 1588     if(textured)
 1589     tess->triangulated_index.push_back(2*TI[i][3]);
 1590     tess->triangulated_index.push_back(3*PI[i][3]);
 1591   }
 1592   tessFace->sizes_triangulated.push_back(2*nI);
 1593   if(triangle_color)
 1594   {
 1595     tessFace->line_attributes.reserve(2*nI);
 1596     for(uint32_t i=0; i<nI; i++)
 1597     {
 1598        tessFace->line_attributes.push_back(SI[i]);
 1599        tessFace->line_attributes.push_back(SI[i]);
 1600     }
 1601   }
 1602   else
 1603   {
 1604       tessFace->line_attributes.push_back(style_index);
 1605   }
 1606   if(vertex_color)
 1607   {
 1608     tessFace->is_rgba=false;
 1609     for(uint32_t i=0; i<nI; i++)
 1610       if(1.0 != C[CI[i][0]].A || 1.0 != C[CI[i][1]].A || 1.0 != C[CI[i][2]].A)
 1611       {
 1612          tessFace->is_rgba=true;
 1613          break;
 1614       }
 1615 
 1616     tessFace->rgba_vertices.reserve(2*(tessFace->is_rgba?4:3)*3*nI);
 1617     for(uint32_t i=0; i<nI; i++)
 1618     {
 1619        // first triangle
 1620        tessFace->rgba_vertices.push_back(byte(C[CI[i][0]].R));
 1621        tessFace->rgba_vertices.push_back(byte(C[CI[i][0]].G));
 1622        tessFace->rgba_vertices.push_back(byte(C[CI[i][0]].B));
 1623        if(tessFace->is_rgba)
 1624        tessFace->rgba_vertices.push_back(byte(C[CI[i][0]].A));
 1625        tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].R));
 1626        tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].G));
 1627        tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].B));
 1628        if(tessFace->is_rgba)
 1629        tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].A));
 1630        tessFace->rgba_vertices.push_back(byte(C[CI[i][3]].R));
 1631        tessFace->rgba_vertices.push_back(byte(C[CI[i][3]].G));
 1632        tessFace->rgba_vertices.push_back(byte(C[CI[i][3]].B));
 1633        if(tessFace->is_rgba)
 1634        tessFace->rgba_vertices.push_back(byte(C[CI[i][3]].A));
 1635        // second triangle
 1636        tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].R));
 1637        tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].G));
 1638        tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].B));
 1639        if(tessFace->is_rgba)
 1640        tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].A));
 1641        tessFace->rgba_vertices.push_back(byte(C[CI[i][2]].R));
 1642        tessFace->rgba_vertices.push_back(byte(C[CI[i][2]].G));
 1643        tessFace->rgba_vertices.push_back(byte(C[CI[i][2]].B));
 1644        if(tessFace->is_rgba)
 1645        tessFace->rgba_vertices.push_back(byte(C[CI[i][2]].A));
 1646        tessFace->rgba_vertices.push_back(byte(C[CI[i][3]].R));
 1647        tessFace->rgba_vertices.push_back(byte(C[CI[i][3]].G));
 1648        tessFace->rgba_vertices.push_back(byte(C[CI[i][3]].B));
 1649        if(tessFace->is_rgba)
 1650        tessFace->rgba_vertices.push_back(byte(C[CI[i][3]].A));
 1651     }
 1652   }
 1653   tess->addTessFace(tessFace);
 1654   const uint32_t tess_index = add3DTess(tess);
 1655   return tess_index;
 1656 }
 1657 
 1658 /*
 1659 void oPRCFile::addTriangle(const double P[][3], const double T[][2], uint32_t style_index)
 1660 {
 1661   PRCgroup &group = findGroup();
 1662 
 1663   group.triangles.push_back(PRCtesstriangle());
 1664   PRCtesstriangle &triangle = group.triangles.back();
 1665   for(size_t i = 0; i < 3; i++)
 1666   {
 1667     triangle.vertices[i].x = P[i][0];
 1668     triangle.vertices[i].y = P[i][1];
 1669     triangle.vertices[i].z = P[i][2];
 1670     triangle.texcoords[i].x = T[i][0];
 1671     triangle.texcoords[i].y = T[i][1];
 1672   }
 1673   triangle.style = style_index;
 1674 }
 1675 */
 1676 
 1677 void oPRCFile::addLines(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[],
 1678  const RGBAColour& c, double w,
 1679  bool segment_color, uint32_t nC, const RGBAColour C[], uint32_t nCI, const uint32_t CI[])
 1680 {
 1681   if(nP==0 || P==NULL || nI==0 || PI==NULL)
 1682     return;
 1683   const uint32_t tess_index = createLines(nP, P, nI, PI, segment_color, nC, C, nCI, CI);
 1684   useLines(tess_index, c, w);
 1685 }
 1686 
 1687 uint32_t oPRCFile::createLines(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[],
 1688  bool segment_color, uint32_t nC, const RGBAColour C[], uint32_t nCI, const uint32_t CI[])
 1689 {
 1690   if(nP==0 || P==NULL || nI==0 || PI==NULL)
 1691     return m1;
 1692 
 1693   const bool vertex_color  = (nC != 0 && C != NULL && CI != NULL);
 1694 
 1695   PRC3DWireTess *tess = new PRC3DWireTess();
 1696   tess->coordinates.reserve(3*nP);
 1697   for(uint32_t i=0; i<nP; i++)
 1698   {
 1699     tess->coordinates.push_back(P[i][0]);
 1700     tess->coordinates.push_back(P[i][1]);
 1701     tess->coordinates.push_back(P[i][2]);
 1702   }
 1703   tess->wire_indexes.reserve(nI);
 1704   for(uint32_t i=0; i<nI;)
 1705   {
 1706     tess->wire_indexes.push_back(PI[i]);
 1707     const uint32_t ni = i+PI[i]+1;
 1708     for(i++; i<ni; i++)
 1709       tess->wire_indexes.push_back(3*PI[i]);
 1710   }
 1711   if(vertex_color)
 1712   {
 1713     tess->is_segment_color = segment_color;
 1714     tess->is_rgba=false;
 1715     for(uint32_t i=0; i<nCI; i++)
 1716       if(1.0 != C[CI[i]].A)
 1717       {
 1718          tess->is_rgba=true;
 1719          break;
 1720       }
 1721     tess->rgba_vertices.reserve((tess->is_rgba?4:3)*nCI);
 1722     for(uint32_t i=0; i<nCI; i++)
 1723     {
 1724        tess->rgba_vertices.push_back(byte(C[CI[i]].R));
 1725        tess->rgba_vertices.push_back(byte(C[CI[i]].G));
 1726        tess->rgba_vertices.push_back(byte(C[CI[i]].B));
 1727        if(tess->is_rgba)
 1728        tess->rgba_vertices.push_back(byte(C[CI[i]].A));
 1729     }
 1730   }
 1731   const uint32_t tess_index = add3DWireTess(tess);
 1732   return tess_index;
 1733 }
 1734 
 1735 #define PRCFACETRANSFORM const double origin[3], const double x_axis[3], const double y_axis[3], double scale, const double* t
 1736 
 1737 void oPRCFile::addHemisphere(double radius, const PRCmaterial &m, PRCFACETRANSFORM)
 1738 {
 1739   ADDFACE(PRCSphere)
 1740   SETTRANSF
 1741   surface->uv_domain.min.x = 0;
 1742   surface->uv_domain.max.x = 2*pi;
 1743   surface->uv_domain.min.y = 0;
 1744   surface->uv_domain.max.y = 0.5*pi;
 1745   surface->radius = radius;
 1746 }
 1747 
 1748 void oPRCFile::addSphere(double radius, const PRCmaterial &m, PRCFACETRANSFORM)
 1749 {
 1750   ADDFACE(PRCSphere)
 1751   SETTRANSF
 1752   surface->uv_domain.min.x = 0;
 1753   surface->uv_domain.max.x = 2*pi;
 1754   surface->uv_domain.min.y =-0.5*pi;
 1755   surface->uv_domain.max.y = 0.5*pi;
 1756   surface->radius = radius;
 1757 }
 1758 
 1759 void oPRCFile::addDisk(double radius, const PRCmaterial &m, PRCFACETRANSFORM)
 1760 {
 1761   ADDFACE(PRCRuled)
 1762   SETTRANSF
 1763   PRCCircle *first_curve = new PRCCircle;
 1764   first_curve->radius = radius;
 1765   surface->first_curve = first_curve;
 1766   PRCCircle *second_curve = new PRCCircle;
 1767   second_curve->radius = 0;
 1768   surface->second_curve = second_curve;
 1769 
 1770   surface->uv_domain.min.x = 0;
 1771   surface->uv_domain.max.x = 1;
 1772   surface->uv_domain.min.y = 0;
 1773   surface->uv_domain.max.y = 2*pi;
 1774   surface->parameterization_on_v_coeff_a = -1;
 1775   surface->parameterization_on_v_coeff_b = 2*pi;
 1776 }
 1777 
 1778 void oPRCFile::addCylinder(double radius, double height, const PRCmaterial &m, PRCFACETRANSFORM)
 1779 {
 1780   ADDFACE(PRCCylinder)
 1781   SETTRANSF
 1782   surface->uv_domain.min.x = 0;
 1783   surface->uv_domain.max.x = 2*pi;
 1784   surface->uv_domain.min.y = (height>0)?0:height;
 1785   surface->uv_domain.max.y = (height>0)?height:0;
 1786   surface->radius = radius;
 1787 }
 1788 
 1789 void oPRCFile::addCone(double radius, double height, const PRCmaterial &m, PRCFACETRANSFORM)
 1790 {
 1791   ADDFACE(PRCCone)
 1792   SETTRANSF
 1793   surface->uv_domain.min.x = 0;
 1794   surface->uv_domain.max.x = 2*pi;
 1795   surface->uv_domain.min.y = (height>0)?0:height;
 1796   surface->uv_domain.max.y = (height>0)?height:0;
 1797   surface->bottom_radius = radius;
 1798   surface->semi_angle = -atan(radius/height);;
 1799 }
 1800 
 1801 void oPRCFile::addTorus(double major_radius, double minor_radius, double angle1, double angle2, const PRCmaterial &m, PRCFACETRANSFORM)
 1802 {
 1803   ADDFACE(PRCTorus)
 1804   SETTRANSF
 1805   surface->uv_domain.min.x = (angle1/180)*pi;
 1806   surface->uv_domain.max.x = (angle2/180)*pi;
 1807   surface->uv_domain.min.y = 0;
 1808   surface->uv_domain.max.y = 2*pi;
 1809   surface->major_radius = major_radius;
 1810   surface->minor_radius = minor_radius;
 1811 }
 1812 
 1813 #undef ADDWIRE
 1814 #undef SETTRANSF
 1815 
 1816 uint32_t PRCFileStructure::addMaterialGeneric(PRCMaterialGeneric*& pMaterialGeneric)
 1817 {
 1818   materials.push_back(pMaterialGeneric);
 1819   pMaterialGeneric = NULL;
 1820   return materials.size()-1;
 1821 }
 1822 
 1823 uint32_t PRCFileStructure::addTextureApplication(PRCTextureApplication*& pTextureApplication)
 1824 {
 1825   materials.push_back(pTextureApplication);
 1826   pTextureApplication = NULL;
 1827   return materials.size()-1;
 1828 }
 1829 
 1830 uint32_t PRCFileStructure::addStyle(PRCStyle*& pStyle)
 1831 {
 1832   styles.push_back(pStyle);
 1833   pStyle = NULL;
 1834   return styles.size()-1;
 1835 }
 1836 
 1837 uint32_t PRCFileStructure::addPartDefinition(PRCPartDefinition*& pPartDefinition)
 1838 {
 1839   part_definitions.push_back(pPartDefinition);
 1840   pPartDefinition = NULL;
 1841   return part_definitions.size()-1;
 1842 }
 1843 
 1844 uint32_t PRCFileStructure::addProductOccurrence(PRCProductOccurrence*& pProductOccurrence)
 1845 {
 1846   product_occurrences.push_back(pProductOccurrence);
 1847   pProductOccurrence = NULL;
 1848   return product_occurrences.size()-1;
 1849 }
 1850 
 1851 uint32_t PRCFileStructure::addTopoContext(PRCTopoContext*& pTopoContext)
 1852 {
 1853   contexts.push_back(pTopoContext);
 1854   pTopoContext = NULL;
 1855   return contexts.size()-1;
 1856 }
 1857 
 1858 uint32_t PRCFileStructure::getTopoContext(PRCTopoContext*& pTopoContext)
 1859 {
 1860   pTopoContext = new PRCTopoContext;
 1861   contexts.push_back(pTopoContext);
 1862   return contexts.size()-1;
 1863 }
 1864 
 1865 uint32_t PRCFileStructure::add3DTess(PRC3DTess*& p3DTess)
 1866 {
 1867   tessellations.push_back(p3DTess);
 1868   p3DTess = NULL;
 1869   return tessellations.size()-1;
 1870 }
 1871 
 1872 uint32_t PRCFileStructure::add3DWireTess(PRC3DWireTess*& p3DWireTess)
 1873 {
 1874   tessellations.push_back(p3DWireTess);
 1875   p3DWireTess = NULL;
 1876   return tessellations.size()-1;
 1877 }
 1878 /*
 1879 uint32_t PRCFileStructure::addMarkupTess(PRCMarkupTess*& pMarkupTess)
 1880 {
 1881   tessellations.push_back(pMarkupTess);
 1882   pMarkupTess = NULL;
 1883   return tessellations.size()-1;
 1884 }
 1885 
 1886 uint32_t PRCFileStructure::addMarkup(PRCMarkup*& pMarkup)
 1887 {
 1888   markups.push_back(pMarkup);
 1889   pMarkup = NULL;
 1890   return markups.size()-1;
 1891 }
 1892 
 1893 uint32_t PRCFileStructure::addAnnotationItem(PRCAnnotationItem*& pAnnotationItem)
 1894 {
 1895   annotation_entities.push_back(pAnnotationItem);
 1896   pAnnotationItem = NULL;
 1897   return annotation_entities.size()-1;
 1898 }
 1899 */
 1900 uint32_t PRCFileStructure::addCoordinateSystem(PRCCoordinateSystem*& pCoordinateSystem)
 1901 {
 1902   reference_coordinate_systems.push_back(pCoordinateSystem);
 1903   pCoordinateSystem = NULL;
 1904   return reference_coordinate_systems.size()-1;
 1905 }
 1906 
 1907 uint32_t PRCFileStructure::addCoordinateSystemUnique(PRCCoordinateSystem*& pCoordinateSystem)
 1908 {
 1909   for(uint32_t i = 0; i < reference_coordinate_systems.size(); ++i)
 1910   {
 1911     if(*(reference_coordinate_systems[i])==*pCoordinateSystem) {
 1912       pCoordinateSystem = NULL;
 1913       return i;
 1914     }
 1915   }
 1916   reference_coordinate_systems.push_back(pCoordinateSystem);
 1917   pCoordinateSystem = NULL;
 1918   return reference_coordinate_systems.size()-1;
 1919 }
 1920 
 1921 }