// brief Get a bounding box of a PBLOB. // TODO(mezhirov) delete this function and replace with blob->bounding_box() static TBOX pblob_get_bbox(PBLOB *blob) { OUTLINE_LIST *outlines = blob->out_list(); OUTLINE_IT it(outlines); TBOX result; for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) { OUTLINE *outline = it.data(); outline->compute_bb(); result.bounding_union(outline->bounding_box()); } return result; }
TBOX PBLOB::bounding_box() { //bounding box OUTLINE *outline; //current outline OUTLINE_IT it = &outlines; //outlines of blob TBOX box; //bounding box for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) { outline = it.data (); box += outline->bounding_box (); } return box; }
float PBLOB::area() { //area OUTLINE *outline; //current outline OUTLINE_IT it = &outlines; //outlines of blob float total; //total area total = 0.0f; for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) { outline = it.data (); total += outline->area (); } return total; }
TESSLINE *make_tess_outlines( //make tess outlines OUTLINE_LIST *outlinelist, //list to convert BOOL8 flatten //flatten outline structure ) { OUTLINE_IT it = outlinelist; //iterator OUTLINE *outline; //current outline TESSLINE *head; //output list TESSLINE *tail; //end of list TESSLINE *tessoutline; head = NULL; tail = NULL; for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) { outline = it.data (); tessoutline = newoutline (); tessoutline->compactloop = NULL; tessoutline->loop = make_tess_edgepts (outline->polypts (), tessoutline->topleft, tessoutline->botright); if (tessoutline->loop == NULL) { oldoutline(tessoutline); continue; } tessoutline->start = tessoutline->loop->pos; tessoutline->node = NULL; tessoutline->next = NULL; tessoutline->child = NULL; if (!outline->child ()->empty ()) { if (flatten) tessoutline->next = (struct olinestruct *) make_tess_outlines (outline->child (), flatten); else { tessoutline->next = NULL; tessoutline->child = (struct olinestruct *) make_tess_outlines (outline->child (), flatten); } } else tessoutline->next = NULL; if (head) tail->next = tessoutline; else head = tessoutline; while (tessoutline->next != NULL) tessoutline = tessoutline->next; tail = tessoutline; } return head; }
BOOL8 OUTLINE::operator< ( //winding number OUTLINE & other //other outline ) { inT16 count; //winding count POLYPT_IT it = &outline; //iterator if (!box.overlap (other.box)) return FALSE; //can't be contained do { count = other.winding_number (FCOORD (it.data ()->pos)); //get winding number if (count != INTERSECTING) return count != 0; it.forward (); } while (!it.at_first ()); //switch lists it.set_to_list (&other.outline); do { //try other way round count = winding_number (FCOORD (it.data ()->pos)); if (count != INTERSECTING) return count == 0; it.forward (); } while (!it.at_first ()); return TRUE; }
static void plot_outline_list( //draw outlines OUTLINE_LIST *list, //outline to draw ScrollView* window, //window to draw in ScrollView::Color colour, //colour to use ScrollView::Color child_colour //colour of children ) { OUTLINE *outline; //current outline OUTLINE_IT it = list; //iterator for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) { outline = it.data (); //draw it outline->plot (window, colour); if (!outline->child ()->empty ()) plot_outline_list (outline->child (), window, child_colour, child_colour); } }
// create the PCB (board only) model using the current outlines and drill holes bool PCBMODEL::CreatePCB() { if( m_hasPCB ) { if( m_pcb_label.IsNull() ) return false; return true; } if( m_curves.empty() || m_mincurve == m_curves.end() ) { m_hasPCB = true; std::ostringstream ostr; ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; ostr << " * no valid board outline\n"; wxLogMessage( "%s\n", ostr.str().c_str() ); return false; } m_hasPCB = true; // whether or not operations fail we note that CreatePCB has been invoked TopoDS_Shape board; OUTLINE oln; // loop to assemble (represents PCB outline and cutouts) oln.AddSegment( *m_mincurve ); m_curves.erase( m_mincurve ); while( !m_curves.empty() ) { if( oln.IsClosed() ) { if( board.IsNull() ) { if( !oln.MakeShape( board, m_thickness ) ) { std::ostringstream ostr; ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; ostr << " * could not create board extrusion\n"; wxLogMessage( "%s\n", ostr.str().c_str() ); return false; } } else { TopoDS_Shape hole; if( oln.MakeShape( hole, m_thickness ) ) { m_cutouts.push_back( hole ); } else { std::ostringstream ostr; ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; ostr << " * could not create board cutout\n"; wxLogMessage( "%s\n", ostr.str().c_str() ); } } oln.Clear(); if( !m_curves.empty() ) { oln.AddSegment( m_curves.front() ); m_curves.pop_front(); } continue; } std::list< KICADCURVE >::iterator sC = m_curves.begin(); std::list< KICADCURVE >::iterator eC = m_curves.end(); while( sC != eC ) { if( oln.AddSegment( *sC ) ) { m_curves.erase( sC ); break; } ++sC; } if( sC == eC && !oln.m_curves.empty() ) { std::ostringstream ostr; ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; ostr << " * could not close outline (dropping outline data with " << oln.m_curves.size() << " segments)\n"; wxLogMessage( "%s\n", ostr.str().c_str() ); oln.Clear(); if( !m_curves.empty() ) { oln.AddSegment( m_curves.front() ); m_curves.pop_front(); } } } if( oln.IsClosed() ) { if( board.IsNull() ) { if( !oln.MakeShape( board, m_thickness ) ) { std::ostringstream ostr; ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; ostr << " * could not create board extrusion\n"; wxLogMessage( "%s\n", ostr.str().c_str() ); return false; } } else { TopoDS_Shape hole; if( oln.MakeShape( hole, m_thickness ) ) { m_cutouts.push_back( hole ); } else { std::ostringstream ostr; ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; ostr << " * could not create board cutout\n"; wxLogMessage( "%s\n", ostr.str().c_str() ); } } } // subtract cutouts (if any) for( auto i : m_cutouts ) board = BRepAlgoAPI_Cut( board, i ); // push the board to the data structure m_pcb_label = m_assy->AddComponent( m_assy_label, board ); if( m_pcb_label.IsNull() ) return false; // color the PCB Handle(XCAFDoc_ColorTool) color = XCAFDoc_DocumentTool::ColorTool( m_doc->Main () ); Quantity_Color pcb_green( 0.06, 0.4, 0.06, Quantity_TOC_RGB ); color->SetColor( m_pcb_label, pcb_green, XCAFDoc_ColorSurf ); TopExp_Explorer topex; topex.Init( m_assy->GetShape( m_pcb_label ), TopAbs_SOLID ); while( topex.More() ) { color->SetColor( topex.Current(), pcb_green, XCAFDoc_ColorSurf ); topex.Next(); } return true; }
// add a pad hole or slot bool PCBMODEL::AddPadHole( KICADPAD* aPad ) { if( NULL == aPad || !aPad->IsThruHole() ) return false; if( !aPad->m_drill.oval ) { TopoDS_Shape s = BRepPrimAPI_MakeCylinder( aPad->m_drill.size.x * 0.5, m_thickness * 2.0 ).Shape(); gp_Trsf shift; shift.SetTranslation( gp_Vec( aPad->m_position.x, aPad->m_position.y, -m_thickness * 0.5 ) ); BRepBuilderAPI_Transform hole( s, shift ); m_cutouts.push_back( hole.Shape() ); return true; } // slotted hole double angle_offset = 0.0; double rad; // radius of the slot double hlen; // half length of the slot if( aPad->m_drill.size.x < aPad->m_drill.size.y ) { angle_offset = M_PI_2; rad = aPad->m_drill.size.x * 0.5; hlen = aPad->m_drill.size.y * 0.5 - rad; } else { rad = aPad->m_drill.size.y * 0.5; hlen = aPad->m_drill.size.x * 0.5 - rad; } DOUBLET c0( -hlen, 0.0 ); DOUBLET c1( hlen, 0.0 ); DOUBLET p0( -hlen, rad ); DOUBLET p1( -hlen, -rad ); DOUBLET p2( hlen, -rad ); DOUBLET p3( hlen, rad ); angle_offset += aPad->m_rotation; double dlim = (double)std::numeric_limits< float >::epsilon(); if( angle_offset < -dlim || angle_offset > dlim ) { double vsin = sin( angle_offset ); double vcos = cos( angle_offset ); double x = c0.x * vcos - c0.y * vsin; double y = c0.x * vsin + c0.y * vcos; c0.x = x; c0.y = y; x = c1.x * vcos - c1.y * vsin; y = c1.x * vsin + c1.y * vcos; c1.x = x; c1.y = y; x = p0.x * vcos - p0.y * vsin; y = p0.x * vsin + p0.y * vcos; p0.x = x; p0.y = y; x = p1.x * vcos - p1.y * vsin; y = p1.x * vsin + p1.y * vcos; p1.x = x; p1.y = y; x = p2.x * vcos - p2.y * vsin; y = p2.x * vsin + p2.y * vcos; p2.x = x; p2.y = y; x = p3.x * vcos - p3.y * vsin; y = p3.x * vsin + p3.y * vcos; p3.x = x; p3.y = y; } c0.x += aPad->m_position.x; c0.y += aPad->m_position.y; c1.x += aPad->m_position.x; c1.y += aPad->m_position.y; p0.x += aPad->m_position.x; p0.y += aPad->m_position.y; p1.x += aPad->m_position.x; p1.y += aPad->m_position.y; p2.x += aPad->m_position.x; p2.y += aPad->m_position.y; p3.x += aPad->m_position.x; p3.y += aPad->m_position.y; OUTLINE oln; KICADCURVE crv0, crv1, crv2, crv3; // crv0 = arc crv0.m_start = c0; crv0.m_end = p0; crv0.m_ep = p1; crv0.m_angle = M_PI; crv0.m_radius = rad; crv0.m_form = CURVE_ARC; // crv1 = line crv1.m_start = p1; crv1.m_end = p2; crv1.m_form = CURVE_LINE; // crv2 = arc crv2.m_start = c1; crv2.m_end = p2; crv2.m_ep = p3; crv2.m_angle = M_PI; crv2.m_radius = rad; crv2.m_form = CURVE_ARC; // crv3 = line crv3.m_start = p3; crv3.m_end = p0; crv3.m_form = CURVE_LINE; oln.AddSegment( crv0 ); oln.AddSegment( crv1 ); oln.AddSegment( crv2 ); oln.AddSegment( crv3 ); TopoDS_Shape slot; if( oln.MakeShape( slot, m_thickness ) ) { if( !slot.IsNull() ) m_cutouts.push_back( slot ); return true; } return false; }