IDFstepper
IDF to STEP converter
src/StepGenerator.cpp
Go to the documentation of this file.
00001 #include "../inc/StepGenerator.hpp"
00002 #include "../inc/IdfStructure.hpp"
00003 #include "../inc/OpenCascade.hpp"
00004 #include <boost/variant.hpp>
00005 #include <iostream>
00006 #include <vector>
00007 #include <cmath>
00008 
00009 namespace stepper {
00010   
00011   const double StepGenerator::EQUAL_PT_DIST = .001;
00012   
00013   bool StepGenerator::setConfigOption(
00014           const std::string& key, const config::Value& value) 
00015           throw (boost::bad_get)
00016   {
00017     if (key == "COMPONENT_OVERWRITE_POLICY") {
00018       const std::string& v(boost::get<std::string>(value));
00019       if (v == "ASK") { setComponentOverwritePolicy(ASK); }
00020       else if (v == "ALWAYS") { setComponentOverwritePolicy(ALWAYS); }
00021       else if (v == "NEVER") { setComponentOverwritePolicy(NEVER); }
00022       else {
00023         err("WARNING: Value of " << key << " is not ASK, ALWAYS or NEVER.\n");
00024       }
00025     
00026     } else if (key == "BOARD_OVERWRITE_POLICY") {
00027       const std::string& v(boost::get<std::string>(value));
00028       if (v == "ASK") { setBoardOverwritePolicy(ASK); }
00029       else if (v == "ALWAYS") { setBoardOverwritePolicy(ALWAYS); }
00030       else if (v == "NEVER") { setBoardOverwritePolicy(NEVER); }
00031       else {
00032         err("WARNING: Value of " << key << " is not ASK, ALWAYS or NEVER.\n");
00033       }
00034     
00035     } else if (key == "PANEL_OVERWRITE_POLICY") {
00036       const std::string& v(boost::get<std::string>(value));
00037       if (v == "ASK") { setPanelOverwritePolicy(ASK); }
00038       else if (v == "ALWAYS") { setPanelOverwritePolicy(ALWAYS); }
00039       else if (v == "NEVER") { setPanelOverwritePolicy(NEVER); }
00040       else {
00041         err("WARNING: Value of " << key << " is not ASK, ALWAYS or NEVER.\n");
00042       }
00043     
00044     } else if (key == "LIBRARY_PATH") {
00045       const std::string& v(boost::get<std::string>(value));
00046       setLibraryPath(v);
00047     
00048     } else if (key == "LIBRARY_NAME_PATTERN") {
00049       const std::string& v(boost::get<std::string>(value));
00050       setLibraryNamePattern(v);
00051     
00052     } else if (key == "BOARD_PATH") {
00053       const std::string& v(boost::get<std::string>(value));
00054       setBoardPath(v);
00055     
00056     } else if (key == "BOARD_NAME_PATTERN") {
00057       const std::string& v(boost::get<std::string>(value));
00058       setBoardNamePattern(v);
00059     
00060     } else if (key == "PANEL_PATH") {
00061       const std::string& v(boost::get<std::string>(value));
00062       setPanelPath(v);
00063     
00064     } else if (key == "PANEL_NAME_PATTERN") {
00065       const std::string& v(boost::get<std::string>(value));
00066       setPanelNamePattern(v);
00067     
00068     } else if (key == "MIN_SOLID_HEIGHT") {
00069       double v(boost::get<double>(value));
00070       setMinSolidHeight(v);
00071     
00072     } else if (key == "MIN_HOLE_DIAMETER") {
00073       double v(boost::get<double>(value));
00074       setMinHoleDiameter(v);
00075       
00076     } else {
00077       return false;
00078     }
00079     return true;
00080   }
00081 
00082   void StepGenerator::generateLibrary(const idf::LibraryStruct& lib) const {
00083     std::cout << "Generating library...\n";
00084     std::cout << "  IDF version: " << lib.idfVersion << std::endl;
00085     if (lib.idfVersion != 3.0) {
00086       err("WARNING: IDF version is not 3.0.\n");
00087     }
00088     std::cout << "  Source system ID: '" << lib.sourceSysId << "'\n";
00089     std::cout << "  Date: " << lib.date << std::endl;
00090     std::cout << "  Library version: " << lib.version << std::endl;
00091     
00092     std::set<std::string> processedFiles;
00093     std::vector<idf::Component>::const_iterator it = lib.components.begin();
00094     while (it != lib.components.end()) {
00095       generateComponent(*it++, processedFiles);
00096     }
00097   }
00098   
00099   void StepGenerator::generateBoard(const idf::BoardPanelStruct& board) const {
00100     std::cout << "Generating board...\n";
00101     std::cout << "  IDF version: " << board.idfVersion << std::endl;
00102     if (board.idfVersion != 3.0) {
00103       err("WARNING: IDF version is not 3.0.\n");
00104     }
00105     std::cout << "  Source system ID: '" << board.sourceSysId << "'\n";
00106     std::cout << "  Date: " << board.date << std::endl;
00107     std::cout << "  Board version: " << board.version << std::endl;
00108     std::cout << "  Board name: '" << board.name << "'\n";
00109     
00110     std::string fn = createBoardPanelFN(boardNamePattern, board.name);
00111     if (fn.empty()) return;
00112     fn = boardPath + fn;
00113     std::cout << "  Resulting file: '" << fn << "'\n";
00114     
00115     if (fexists(fn)) {
00116       OverwritePolicy op = boardOvW;
00117       if (op == ASK) op = askOvW(fn);
00118       if (op == NEVER) boardOvW = NEVER;
00119       if (op == ALWAYS) boardOvW = ALWAYS;
00120       
00121       if ((op == NO) || (op == NEVER)) return;
00122     }
00123     
00124     TopoDS_Shape brdShape = createBoardShape(board);
00125     if (brdShape.IsNull()) {
00126       return;
00127     } else {
00128       std::cout << "  Board shape created.\n";
00129     }
00130     
00131     TopoDS_Compound assembly;
00132     TopoDS_Builder mkTopo;
00133     mkTopo.MakeCompound(assembly);
00134     
00135     mkTopo.Add(assembly, brdShape);
00136     
00137     if (board.components) {    
00138       std::cout << "  Generating component placements...\n";
00139       
00140       int count = 0;
00141       std::vector<idf::ComponentPlacement>::const_iterator it
00142               = board.components->placements.begin();
00143       std::vector<idf::ComponentPlacement>::const_iterator end
00144               = board.components->placements.end();
00145       while (it != end) {
00146         try {
00147           if (it->status != idf::UNPLACED) {
00148             std::string fn = createCompFN(it->package, it->number);
00149             if (!fn.empty()) {
00150               fn = libraryPath + fn;
00151               std::cout << "    Reading component '" << it->refdes;
00152               std::cout << "' from file '" << fn << "'... (";
00153               std::cout << count + 1 << "/";
00154               std::cout << board.components->placements.size() << ")\n";
00155               TopoDS_Shape comp = readShape(fn);
00156               if (!comp.IsNull()) {
00157                 gp_Trsf transform;
00158                 gp_Trsf workTF;
00159                 transform.SetTranslation(gp_Vec(
00160                         measure(it->x, board.units),
00161                         measure(it->y, board.units),
00162                         0.0));
00163                 if (it->side == idf::BOTTOM_SIDE) {
00164                   workTF.SetMirror(gp::OY());
00165                   transform = transform * workTF;
00166                 }
00167                 workTF.SetRotation(gp::OZ(), it->angle*M_PI/180.0);
00168                 transform = transform * workTF;
00169                 double z = measure(
00170                         board.outline.thickness + it->offset, board.units);
00171                 if (it->side == idf::BOTTOM_SIDE) {
00172                   z = measure(it->offset, board.units);
00173                 }
00174                 workTF.SetTranslation(gp_Vec(0.0, 0.0, z));
00175                 transform = transform * workTF;
00176                 
00177                 BRepBuilderAPI_Transform brepTR(comp, transform);
00178                 comp = brepTR.ModifiedShape(comp);
00179                 
00180                 mkTopo.Add(assembly, comp);
00181                 ++count;
00182               }
00183             }
00184           }
00185         } catch (Standard_Failure ex) {
00186           err("WARNING: Failed to load component '" << it->refdes);
00187           err("': " << ex.GetMessageString() << ".\n");
00188         }
00189         
00190         ++it;
00191       }
00192       
00193       std::cout << "  Added " << count << "/";
00194       std::cout << board.components->placements.size() << " components.\n";
00195     }
00196     
00197     std::cout << "Storing assembly...\n";
00198     
00199     IFSelect_ReturnStatus stat;
00200     {
00201       Silence silence;
00202       STEPControl_Writer writer;
00203       stat = writer.Transfer(assembly, STEPControl_AsIs);
00204       if (stat != IFSelect_RetDone) {
00205         err("WARNING: Failed to transfer STEP data (");
00206         err(stat << ").\n");
00207         return;
00208       }
00209     
00210       APIHeaderSection_MakeHeader mkHeader(writer.Model());
00211       mkHeader.SetName(new TCollection_HAsciiString(board.name.c_str()));
00212       mkHeader.SetOriginatingSystem(new TCollection_HAsciiString("IDFstepper"));      
00213       stat = writer.Write(fn.c_str());
00214     }
00215     
00216     if (stat == IFSelect_RetDone) {
00217       std::cout << "Stored assembly in '" << fn << "'\n";
00218     } else {
00219       err("WARNING: Failed to store file '" << fn << "' (");
00220       err(stat << ").\n");
00221     }
00222   }
00223   
00224   void StepGenerator::generatePanel(const idf::BoardPanelStruct& panel) const {
00225     std::cout << "Generating panel...\n";
00226     std::cout << "  IDF version: " << panel.idfVersion << std::endl;
00227     if (panel.idfVersion != 3.0) {
00228       err("WARNING: IDF version is not 3.0.\n");
00229     }
00230     std::cout << "  Source system ID: '" << panel.sourceSysId << "'\n";
00231     std::cout << "  Date: " << panel.date << std::endl;
00232     std::cout << "  Panel version: " << panel.version << std::endl;
00233     std::cout << "  Panel name: '" << panel.name << "'\n";
00234     
00235     std::string fn = createBoardPanelFN(panelNamePattern, panel.name);
00236     if (fn.empty()) return;
00237     fn = panelPath + fn;
00238     std::cout << "  Resulting file: '" << fn << "'\n";
00239     
00240     if (fexists(fn)) {
00241       OverwritePolicy op = panelOvW;
00242       if (op == ASK) op = askOvW(fn);
00243       if (op == NEVER) panelOvW = NEVER;
00244       if (op == ALWAYS) panelOvW = ALWAYS;
00245       
00246       if ((op == NO) || (op == NEVER)) return;
00247     }
00248     
00249     TopoDS_Shape pnlShape = createBoardShape(panel);
00250     if (pnlShape.IsNull()) {
00251       return;
00252     } else {
00253       std::cout << "  Panel shape created.\n";
00254     }
00255     
00256     TopoDS_Compound assembly;
00257     TopoDS_Builder mkTopo;
00258     mkTopo.MakeCompound(assembly);
00259     
00260     mkTopo.Add(assembly, pnlShape);
00261     
00262     if (panel.components) {    
00263       std::cout << "  Generating board placements...\n";
00264       
00265       int count = 0;
00266       std::vector<idf::ComponentPlacement>::const_iterator it
00267               = panel.components->placements.begin();
00268       std::vector<idf::ComponentPlacement>::const_iterator end
00269               = panel.components->placements.end();
00270       while (it != end) {
00271         try {
00272           std::string fn = createBoardPanelFN(panelNamePattern, it->package);
00273           if (!fn.empty()) {
00274             fn = boardPath + fn;
00275             std::cout << "    Reading board from file '";
00276             std::cout << fn << "'... (" << count + 1 << "/";
00277             std::cout << panel.components->placements.size() << ")\n";
00278             TopoDS_Shape comp = readShape(fn);
00279             if (!comp.IsNull()) {
00280               gp_Trsf transform;
00281               gp_Trsf workTF;
00282               transform.SetTranslation(gp_Vec(
00283                       measure(it->x, panel.units),
00284                       measure(it->y, panel.units),
00285                       0.0));
00286               if (it->side == idf::BOTTOM_SIDE) {
00287                 workTF.SetMirror(gp::OY());
00288                 transform = transform * workTF;
00289               }
00290               workTF.SetRotation(gp::OZ(), it->angle*M_PI/180.0);
00291               transform = transform * workTF;
00292               double z = measure(it->offset, panel.units);
00293               if (it->side == idf::BOTTOM_SIDE) {
00294                 z = measure(-panel.outline.thickness
00295                         + it->offset, panel.units);
00296               }
00297               workTF.SetTranslation(gp_Vec(0.0, 0.0, z));
00298               transform = transform * workTF;
00299               
00300               BRepBuilderAPI_Transform brepTR(comp, transform);
00301               comp = brepTR.ModifiedShape(comp);
00302               
00303               mkTopo.Add(assembly, comp);
00304               ++count;
00305             }
00306           }
00307         } catch (Standard_Failure ex) {
00308           err("WARNING: Failed to load board '" << it->package);
00309           err("': " << ex.GetMessageString() << ".\n");
00310         }
00311         
00312         ++it;
00313       }
00314       
00315       std::cout << "  Added " << count << "/";
00316       std::cout << panel.components->placements.size() << " boards.\n";
00317     }
00318     
00319     std::cout << "Storing assembly...\n";
00320     
00321     IFSelect_ReturnStatus stat;
00322     {
00323       Silence silence;
00324       STEPControl_Writer writer;
00325       stat = writer.Transfer(assembly, STEPControl_AsIs);
00326       if (stat != IFSelect_RetDone) {
00327         err("WARNING: Failed to transfer STEP data (");
00328         err(stat << ").\n");
00329         return;
00330       }
00331     
00332       APIHeaderSection_MakeHeader mkHeader(writer.Model());
00333       mkHeader.SetName(new TCollection_HAsciiString(panel.name.c_str()));
00334       mkHeader.SetOriginatingSystem(new TCollection_HAsciiString("IDFstepper"));      
00335       stat = writer.Write(fn.c_str());
00336     }
00337     
00338     if (stat == IFSelect_RetDone) {
00339       std::cout << "Stored assembly in '" << fn << "'\n";
00340     } else {
00341       err("WARNING: Failed to store file '" << fn << "' (");
00342       err(stat << ").\n");
00343     }
00344   }
00345   
00346   
00347   void StepGenerator::generateComponent(
00348           const idf::Component& comp,
00349           std::set<std::string>& processedFiles) const
00350   {
00351     std::string fn = createCompFN(comp.name, comp.number);
00352     if (fn.empty()) return;
00353     fn = libraryPath + fn;
00354     if (processedFiles.find(fn) != processedFiles.end()) {
00355       // File has already been created in this run
00356       return;
00357     }
00358     std::cout << "  Generating component...\n";
00359     std::cout << "    Geometry name: '" << comp.name << "'\n";
00360     std::cout << "    Part number: '" << comp.number << "'\n";
00361     std::cout << "    Height: " << measure(comp.height, comp.units) << "mm\n";
00362     std::cout << "    Loop entries: " << comp.loops.size() << std::endl;
00363     std::cout << "    Resulting file: '" << fn << "'\n";
00364     
00365     if (fexists(fn)) {
00366       OverwritePolicy op = compOvW;
00367       if (op == ASK) op = askOvW(fn);
00368       if (op == NEVER) compOvW = NEVER;
00369       if (op == ALWAYS) compOvW = ALWAYS;
00370       
00371       if ((op == NO) || (op == NEVER)) return;
00372     }
00373     
00374     TopoDS_Shape solid = solidFromLoops(comp.loops, comp.height, comp.units);
00375     
00376     if (solid.IsNull()) {
00377       err("WARNING: Failed to create solid of component '");
00378       err(comp.name << "'.\n");
00379       return;
00380     }
00381     
00382     IFSelect_ReturnStatus stat;
00383     {
00384       Silence silence;
00385       STEPControl_Writer writer;
00386       stat = writer.Transfer(solid, STEPControl_AsIs);
00387       if (stat != IFSelect_RetDone) {
00388         err("WARNING: Failed to transfer STEP data (");
00389         err(stat << ").\n");
00390         return;
00391       }
00392       
00393       APIHeaderSection_MakeHeader mkHeader(writer.Model());
00394       mkHeader.SetName(new TCollection_HAsciiString(comp.name.c_str()));
00395       mkHeader.SetOriginatingSystem(new TCollection_HAsciiString("IDFstepper"));
00396       
00397       stat = writer.Write(fn.c_str());
00398     }
00399     
00400     if (stat == IFSelect_RetDone) {
00401       std::cout << "  Stored component.\n";
00402       processedFiles.insert(fn);
00403     } else {
00404       err("WARNING: Failed to store file '" << fn << "' (");
00405       err(stat << ").\n");
00406     }
00407   }
00408   
00409   TopoDS_Wire StepGenerator::wireFromLoops(
00410           std::vector<idf::Loop>::const_iterator& iter,
00411           std::vector<idf::Loop>::const_iterator end,
00412           idf::Unit u) const
00413   {
00414     // Generate a wire as long as all subsequent loop entries belong
00415     // to the same label.
00416     int label = iter->label;
00417     idf::Loop prev = *iter++;
00418     gp_Pnt first = pt(prev, u);
00419     
00420     try {
00421     
00422       BRepBuilderAPI_MakeWire mkWire;
00423       
00424       while ((iter != end) && (iter->label == label)) {
00425         gp_Pnt pt1 = pt(prev, u);
00426         gp_Pnt pt2 = pt(*iter, u);
00427         
00428         if (pt1.IsEqual(pt2, EQUAL_PT_DIST)) {
00429           err("WARNING: Found collapsing points in loop with label ");
00430           err(label << ".\n");
00431           return TopoDS_Wire();
00432         } else {
00433           if (iter->angle == 0.0) {
00434             // Straight line
00435             mkWire.Add(BRepBuilderAPI_MakeEdge(pt1, pt2));
00436             
00437           } else if (iter->angle == 360.0) {
00438             // Full circle
00439             double radius = pt1.Distance(pt2);
00440             Handle(Geom_Circle) circle =
00441                     GC_MakeCircle(pt1, gp_Dir(0.0, 0.0, 1.0), radius);
00442             mkWire.Add(BRepBuilderAPI_MakeEdge(circle));
00443             
00444           } else {
00445             // Arc
00446             gp_Pnt mid(
00447                     (pt1.X() + pt2.X()) / 2.0,
00448                     (pt1.Y() + pt2.Y()) / 2.0,
00449                     0.0);
00450             double a = pt1.Distance(pt2) / 2.0;
00451             gp_Dir ptDir((pt2.X()-mid.X())/a, (pt2.Y()-mid.Y())/a, 0.0);
00452             gp_Dir centDir(-ptDir.Y(), ptDir.X(), 0.0);
00453             if (iter->angle < 0.0) {
00454               centDir = gp_Dir(-centDir.X(), -centDir.Y(), 0.0);
00455             }
00456             gp_Pnt center;
00457             gp_Pnt pt3;
00458             double r;
00459             
00460             if ((iter->angle == 180.0) || (iter->angle == -180.0)) {
00461               center = mid;
00462               r = a;
00463               
00464             } else {
00465               // Calculate the arc's center based on the two endpoints
00466               // and the given angle (triangle geometry).
00467               double alpha = iter->angle * M_PI / 180.0;
00468               double c = a / std::sin(std::fabs(alpha) / 2.0);
00469               double b = std::sqrt(c*c - a*a);
00470               gp_Pnt offset(b*centDir.X(), b*centDir.Y(), 0.0);
00471               center = gp_Pnt(mid.X()+offset.X(), mid.Y()+offset.Y(), 0.0);
00472               r = c;
00473             }
00474             
00475             pt3 = gp_Pnt(
00476                     center.X()-r*centDir.X(),
00477                     center.Y()-r*centDir.Y(),
00478                     0.0);
00479             
00480             /*std::cout << "Center at [" << center.X() << " / " << center.Y() << "]\n";
00481             std::cout << "Pt1 at [" << pt1.X() << " / " << pt1.Y() << "]\n";
00482             std::cout << "Pt2 at [" << pt2.X() << " / " << pt2.Y() << "]\n";
00483             std::cout << "Pt3 at [" << pt3.X() << " / " << pt3.Y() << "]\n";*/
00484             Handle(Geom_TrimmedCurve) arc =
00485                     GC_MakeArcOfCircle(pt1, pt3, pt2);
00486             mkWire.Add(BRepBuilderAPI_MakeEdge(arc));
00487             
00488           }
00489         }
00490         
00491         prev = *iter++;
00492       }
00493       
00494       // Make sure that we have a closed curve
00495       if (!first.IsEqual(pt(prev, u), EQUAL_PT_DIST) && prev.angle != 360.0) {
00496         err("WARNING: Needed to close loop with label ");
00497         err(label << ".\n");
00498         mkWire.Add(BRepBuilderAPI_MakeEdge(pt(prev, u), first));
00499       }
00500     
00501       if (mkWire.IsDone()) {
00502         return mkWire.Wire();
00503       } else {
00504         err("WARNING: Wire creation failed for loop with label ");
00505         err(label << ".\n");
00506         return TopoDS_Wire();
00507       }
00508       
00509     } catch (Standard_Failure ex) {
00510       err("WARNING: Loop failed: ");
00511       err(ex.GetMessageString() << ".\n");
00512       return TopoDS_Wire();
00513     }
00514   }
00515 
00516   TopoDS_Shape StepGenerator::solidFromLoops(
00517           const std::vector<idf::Loop>& loops,
00518           double height,
00519           idf::Unit u) const
00520   {
00521     // At least two entries are necessary for all shapes
00522     if (loops.size() < 2) return TopoDS_Shape();
00523     
00524     try {
00525     
00526       BRepBuilderAPI_MakeFace mkFace;
00527       
00528       bool first = true;
00529       std::vector<idf::Loop>::const_iterator it = loops.begin();
00530       while (it != loops.end()) {
00531         TopoDS_Wire wire = wireFromLoops(it, loops.end(), u);
00532         if (!wire.IsNull()) {
00533           if (first) {
00534             mkFace = BRepBuilderAPI_MakeFace(wire);
00535             first = false;
00536           } else {
00537             mkFace.Add(wire);
00538           }
00539         }
00540       }
00541       
00542       if (mkFace.IsDone()) {
00543         TopoDS_Face face = mkFace.Face();
00544         double h = measure(height, u);
00545         if (h < minSolidHeight) h = minSolidHeight;
00546         return TopoDS_Shape(BRepPrimAPI_MakePrism(
00547                 face, gp_Vec(0.0, 0.0, h)));
00548       } else {
00549         err("WARNING: Face creation failed.\n");
00550         return TopoDS_Shape();
00551       }
00552               
00553     } catch (Standard_Failure ex) {
00554       err("WARNING: Solid failed: ");
00555       err(ex.GetMessageString() << ".\n");
00556       return TopoDS_Shape();
00557     }
00558   }
00559   
00560   TopoDS_Shape StepGenerator::readShape(const std::string& filename) const {
00561     Silence silence;
00562     STEPControl_Reader reader;
00563     IFSelect_ReturnStatus stat = reader.ReadFile(filename.c_str());
00564     
00565     if (stat != IFSelect_RetDone) {
00566       err("WARNING: Failed to read file '" << filename << "' (");
00567       err(stat << ").\n");
00568       return TopoDS_Shape();
00569     }
00570     
00571     int numRoots = reader.NbRootsForTransfer();
00572     int numTransferred = reader.TransferRoots();
00573     if (numTransferred < numRoots) {
00574       err("WARNING: Transferred only " << numTransferred);
00575       err("/" << numRoots << " roots.\n");
00576     }
00577     
00578     TopoDS_Shape ret = reader.OneShape();
00579     if (ret.IsNull()) {
00580       err("WARNING: Failed to load shape from file '");
00581       err(filename << "'.\n");
00582     }
00583     return ret;
00584   }
00585   
00586   TopoDS_Shape StepGenerator::createBoardShape(
00587           const idf::BoardPanelStruct& board) const
00588   {
00589     const std::vector<idf::Loop>& loops = board.outline.loops;
00590     
00591     // At least two entries are necessary for all shapes
00592     if (loops.size() < 2) {
00593       err("WARNING: Board outline has less than two loop entries.\n");
00594       return TopoDS_Shape();
00595     }
00596     
00597     idf::Unit u = board.units;
00598     BRepBuilderAPI_MakeFace mkFace;
00599     
00600     try {
00601       {
00602         if (board.fileType == idf::BOARD_FILE) {
00603           std::cout << "  Generating board outline from ";
00604         } else {
00605           std::cout << "  Generating panel outline from ";
00606         }
00607         std::cout << loops.size() << " loop entries...\n";
00608         
00609         // Create outline
00610         bool first = true;
00611         std::vector<idf::Loop>::const_iterator it = loops.begin();
00612         while (it != loops.end()) {
00613           TopoDS_Wire wire = wireFromLoops(it, loops.end(), u);
00614           if (!wire.IsNull()) {
00615             if (first) {
00616               mkFace = BRepBuilderAPI_MakeFace(wire);
00617               first = false;
00618             } else {
00619               mkFace.Add(wire);
00620             }
00621           }
00622         }
00623       }
00624       
00625       if (board.holes) {
00626         
00627         std::cout << "  Creating drilled holes with diameter >=";
00628         std::cout << minHoleDiameter << "mm...\n";
00629       
00630         // Drill holes
00631         int count = 0;
00632         std::vector<idf::DrilledHole>::const_iterator it
00633                 = board.holes->holes.begin();
00634         while (it != board.holes->holes.end()) {
00635           double dia = measure(it->diameter, u);
00636           if (dia >= minHoleDiameter) {
00637           
00638             gp_Pnt center(measure(it->x, u), measure(it->y, u), 0.0);
00639             Handle(Geom_Circle) circle =
00640                     GC_MakeCircle(center, gp_Dir(0.0, 0.0, 1.0), dia/2.0);
00641             TopoDS_Wire holeWire = BRepBuilderAPI_MakeWire(
00642                     BRepBuilderAPI_MakeEdge(circle));
00643             if (holeWire.IsNull()) {
00644               err("WARNING: Hole at (" << center.X() << " / ");
00645               err(center.Y() << ") failed.\n");
00646             } else {
00647               mkFace.Add(holeWire);
00648               ++count;
00649             }
00650           }
00651           ++it;
00652         }
00653         
00654         std::cout << "  Created " << count << "/";
00655         std::cout << board.holes->holes.size() << " holes.\n";
00656       }
00657       
00658       if (mkFace.IsDone()) {
00659         TopoDS_Face face = mkFace.Face();
00660         return TopoDS_Shape(BRepPrimAPI_MakePrism(
00661                 face, gp_Vec(0.0, 0.0, measure(board.outline.thickness, u))));
00662       } else {
00663         err("WARNING: Board face creation failed.\n");
00664         return TopoDS_Shape();
00665       }
00666     
00667     } catch (Standard_Failure ex) {
00668       err("WARNING: Board outline failed: ");
00669       err(ex.GetMessageString() << ".\n");
00670       return TopoDS_Shape();
00671     }
00672   }
00673 
00674 
00675 
00676 }
00677 
00678 
00679 
00680 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines