IDFstepper
IDF to STEP converter
|
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