// The helper function for D_CODE::ConvertShapeToPolygon(). // Add a hole to a polygon static void addHoleToPolygon( SHAPE_POLY_SET* aPolygon, APERTURE_DEF_HOLETYPE aHoleShape, wxSize aSize, wxPoint aAnchorPos ) { wxPoint currpos; SHAPE_POLY_SET holeBuffer; if( aHoleShape == APT_DEF_ROUND_HOLE ) { TransformCircleToPolygon( holeBuffer, wxPoint( 0, 0 ), aSize.x / 2, SEGS_CNT ); } else if( aHoleShape == APT_DEF_RECT_HOLE ) { holeBuffer.NewOutline(); currpos.x = aSize.x / 2; currpos.y = aSize.y / 2; holeBuffer.Append( VECTOR2I( currpos ) ); // link to hole and begin hole currpos.x -= aSize.x; holeBuffer.Append( VECTOR2I( currpos ) ); currpos.y -= aSize.y; holeBuffer.Append( VECTOR2I( currpos ) ); currpos.x += aSize.x; holeBuffer.Append( VECTOR2I( currpos ) ); currpos.y += aSize.y; holeBuffer.Append( VECTOR2I( currpos ) ); // close hole } aPolygon->BooleanSubtract( holeBuffer, SHAPE_POLY_SET::PM_FAST ); // Needed for legacy canvas only aPolygon->Fracture( SHAPE_POLY_SET::PM_FAST ); }
bool SHAPE_RECT::Collide( const SEG& aSeg, int aClearance ) const { //VECTOR2I pmin = VECTOR2I( std::min( aSeg.a.x, aSeg.b.x ), std::min( aSeg.a.y, aSeg.b.y ) ); //VECTOR2I pmax = VECTOR2I( std::max( aSeg.a.x, aSeg.b.x ), std::max( aSeg.a.y, aSeg.b.y )); //BOX2I r( pmin, VECTOR2I( pmax.x - pmin.x, pmax.y - pmin.y ) ); //if( BBox( 0 ).SquaredDistance( r ) > aClearance * aClearance ) // return false; if( BBox( 0 ).Contains( aSeg.A ) || BBox( 0 ).Contains( aSeg.B ) ) return true; VECTOR2I vts[] = { VECTOR2I( m_p0.x, m_p0.y ), VECTOR2I( m_p0.x, m_p0.y + m_h ), VECTOR2I( m_p0.x + m_w, m_p0.y + m_h ), VECTOR2I( m_p0.x + m_w, m_p0.y ), VECTOR2I( m_p0.x, m_p0.y ) }; for( int i = 0; i < 4; i++ ) { SEG s( vts[i], vts[i + 1], i ); if( s.Distance( aSeg ) < aClearance ) return true; } return false; }
const SHAPE_LINE_CHAIN PNS_SOLID::Hull( int aClearance, int aWalkaroundThickness ) const { int cl = aClearance + aWalkaroundThickness / 2; switch( m_shape->Type() ) { case SH_RECT: { SHAPE_RECT* rect = static_cast<SHAPE_RECT*>( m_shape ); return OctagonalHull( rect->GetPosition(), rect->GetSize(), cl + 1, 0.2 * cl ); } case SH_CIRCLE: { SHAPE_CIRCLE* circle = static_cast<SHAPE_CIRCLE*>( m_shape ); int r = circle->GetRadius(); return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ), VECTOR2I( 2 * r, 2 * r ), cl + 1, 0.52 * ( r + cl ) ); } case SH_SEGMENT: { SHAPE_SEGMENT* seg = static_cast<SHAPE_SEGMENT*> ( m_shape ); return SegmentHull( *seg, aClearance, aWalkaroundThickness ); } default: break; } return SHAPE_LINE_CHAIN(); }
const BOX2I DIMENSION::ViewBBox() const { BOX2I dimBBox = BOX2I( VECTOR2I( GetBoundingBox().GetPosition() ), VECTOR2I( GetBoundingBox().GetSize() ) ); dimBBox.Merge( m_Text.ViewBBox() ); return dimBBox; }
static void drawGw( VECTOR2I p, int color ) { SHAPE_LINE_CHAIN l; l.Append( p - VECTOR2I( -50000, -50000 ) ); l.Append( p + VECTOR2I( -50000, -50000 ) ); l.Clear(); l.Append( p - VECTOR2I( 50000, -50000 ) ); l.Append( p + VECTOR2I( 50000, -50000 ) ); }
void SCH_VIEW::ShowSelectionArea( bool aShow ) { if( aShow ) { // Reset seleciton area so the previous one doesn't flash before the first // mouse move updates it m_selectionArea->SetOrigin( VECTOR2I() ); m_selectionArea->SetEnd( VECTOR2I() ); } SetVisible( m_selectionArea.get(), aShow ); }
VECTOR2I GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, BOARD_ITEM* aDraggedItem ) { double worldScale = m_frame->GetGalCanvas()->GetGAL()->GetWorldScale(); int snapRange = (int) ( 100.0 / worldScale ); BOX2I bb( VECTOR2I( aOrigin.x - snapRange / 2, aOrigin.y - snapRange / 2 ), VECTOR2I( snapRange, snapRange ) ); clearAnchors(); BOOST_FOREACH( BOARD_ITEM* item, queryVisible( bb ) ) { computeAnchors( item, aOrigin ); }
const BOX2I LIB_EDIT_FRAME::GetDocumentExtents() const { LIB_PART* part = GetCurPart(); if( !part ) { return BOX2I( VECTOR2I(-100, -100), VECTOR2I( 200, 200 ) ); } else { EDA_RECT boundingBox = part->GetUnitBoundingBox( m_unit, m_convert ); return BOX2I( boundingBox.GetOrigin(), VECTOR2I( boundingBox.GetWidth(), boundingBox.GetHeight() ) ); } }
const BOX2I D_PAD::ViewBBox() const { // Bounding box includes soldermask too int solderMaskMargin = GetSolderMaskMargin(); VECTOR2I solderPasteMargin = VECTOR2D( GetSolderPasteMargin() ); EDA_RECT bbox = GetBoundingBox(); // Look for the biggest possible bounding box int xMargin = std::max( solderMaskMargin, solderPasteMargin.x ); int yMargin = std::max( solderMaskMargin, solderPasteMargin.y ); return BOX2I( VECTOR2I( bbox.GetOrigin() ) - VECTOR2I( xMargin, yMargin ), VECTOR2I( bbox.GetSize() ) + VECTOR2I( 2 * xMargin, 2 * yMargin ) ); }
void AddDirections( VECTOR2D aP, int aMask, int aColor ) { BOX2I b( aP - VECTOR2I( 10000, 10000 ), VECTOR2I( 20000, 20000 ) ); AddBox( b, aColor ); for( int i = 0; i < 8; i++ ) { if( ( 1 << i ) & aMask ) { VECTOR2I v = DIRECTION_45( ( DIRECTION_45::Directions ) i ).ToVector() * 100000; AddSegment( SEG( aP, aP + v ), aColor ); } } }
void AddPoint( VECTOR2I aP, int aColor ) { SHAPE_LINE_CHAIN l; l.Append( aP - VECTOR2I( -50000, -50000 ) ); l.Append( aP + VECTOR2I( -50000, -50000 ) ); AddLine ( l, aColor, 10000 ); l.Clear(); l.Append( aP - VECTOR2I( 50000, -50000 ) ); l.Append( aP + VECTOR2I( 50000, -50000 ) ); AddLine( l, aColor, 10000 ); }
void DrawDebugPoint( VECTOR2I aP, int aColor ) { SHAPE_LINE_CHAIN l; l.Append( aP - VECTOR2I( -50000, -50000 ) ); l.Append( aP + VECTOR2I( -50000, -50000 ) ); ROUTER::GetInstance()->DisplayDebugLine ( l, aColor, 10000 ); l.Clear(); l.Append( aP - VECTOR2I( 50000, -50000 ) ); l.Append( aP + VECTOR2I( 50000, -50000 ) ); ROUTER::GetInstance()->DisplayDebugLine( l, aColor, 10000 ); }
void POINT_EDITOR::removeCorner( EDIT_POINT* aPoint ) { EDA_ITEM* item = m_editPoints->GetParent(); if( item->Type() == PCB_ZONE_AREA_T ) { const SELECTION& selection = m_selectionTool->GetSelection(); PCB_BASE_FRAME* frame = getEditFrame<PCB_BASE_FRAME>(); ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item ); CPolyLine* outline = zone->Outline(); for( int i = 0; i < outline->GetCornersCount(); ++i ) { if( VECTOR2I( outline->GetPos( i ) ) == aPoint->GetPosition() ) { frame->OnModify(); frame->SaveCopyInUndoList( selection.items, UR_CHANGED ); outline->DeleteCorner( i ); setEditedPoint( NULL ); break; } } } }
const BOX2I LIB_VIEW_FRAME::GetDocumentExtents() const { LIB_ALIAS* alias = getSelectedAlias(); LIB_PART* part = alias ? alias->GetPart() : nullptr; if( !part ) { return BOX2I( VECTOR2I(-200, -200), VECTOR2I( 400, 400 ) ); } else { EDA_RECT bbox = part->GetUnitBoundingBox( m_unit, m_convert ); return BOX2I( bbox.GetOrigin(), VECTOR2I( bbox.GetWidth(), bbox.GetHeight() ) ); } }
/** * Function TestLineChainEqualCPolyLine * tests the equality between a SHAPE_LINE_CHAIN polygon and a polygon inside a * CPolyLine object using Boost test suite. * @param lineChain is a SHAPE_LINE_CHAIN polygon object. * @param polyLine is a CPolyLine polygon object. * @param contourIdx is the index of the contour inside polyLine that has to be tested * against lineChain. */ void TestLineChainEqualCPolyLine(SHAPE_LINE_CHAIN& lineChain, CPolyLine& polyLine, int contourIdx = 0) { // Arrays to store the polygon points lexicographically ordered std::vector<VECTOR2I> chainPoints; std::vector<VECTOR2I> polyPoints; // Populate the array storing the new data with the lineChain corners for (int pointIdx = 0; pointIdx < lineChain.PointCount(); pointIdx++) { chainPoints.push_back(lineChain.Point(pointIdx)); } int start = polyLine.GetContourStart(contourIdx); int end = polyLine.GetContourEnd(contourIdx); // Populate the array storing the legacy data with the polyLine corners for (int pointIdx = start; pointIdx <= end; pointIdx++) { polyPoints.push_back( VECTOR2I(polyLine.GetX(pointIdx), polyLine.GetY(pointIdx)) ); } // Order the vectors in a lexicographic way std::sort(chainPoints.begin(), chainPoints.end(), lexicographicOrder); std::sort(polyPoints.begin(), polyPoints.end(), lexicographicOrder); // Compare every point coordinate to check the equality BOOST_CHECK_EQUAL_COLLECTIONS(chainPoints.begin(), chainPoints.end(), polyPoints.begin(), polyPoints.end()); }
VECTOR2I GRID_HELPER::GetGrid() const { PCB_SCREEN* screen = m_frame->GetScreen(); const wxRealPoint& size = screen->GetGridSize(); return VECTOR2I( KiROUND( size.x ), KiROUND( size.y ) ); }
void RectList::use() { if (INPUT->again(Qt::LeftButton)) { sf::IntRect rect = findRect(INPUT->getPixel() - VECTOR2I(LAYER->getPosition()), LAYER->getImage()); if (rect.width > 0) { layer = LAYER; findRectList(rect, LAYER->getImage()); } } }
static bool Rect2Circle( VECTOR2I rp0, VECTOR2I rsize, VECTOR2I cc, int cr, VECTOR2I& force ) { VECTOR2I vts[] = { VECTOR2I( rp0.x, rp0.y ), VECTOR2I( rp0.x, rp0.y + rsize.y ), VECTOR2I( rp0.x + rsize.x, rp0.y + rsize.y ), VECTOR2I( rp0.x + rsize.x, rp0.y ), VECTOR2I( rp0.x, rp0.y ) }; int dist = INT_MAX; VECTOR2I nearest; for( int i = 0; i < 4; i++ ) { SEG s( vts[i], vts[i + 1] ); VECTOR2I pn = s.NearestPoint( cc ); int d = (pn - cc).EuclideanNorm(); if( d < dist ) { nearest = pn; dist = d; } } bool inside = cc.x >= rp0.x && cc.x <= (rp0.x + rsize.x) && cc.y >= rp0.y && cc.y <= (rp0.y + rsize.y); VECTOR2I delta = cc - nearest; if( dist >= cr && !inside ) return false; if( inside ) force = -delta.Resize( abs( cr + dist ) + 1 ); else force = delta.Resize( abs( cr - dist ) + 1 ); return true; };
void SelectionController::sumSelection(const sf::IntRect& rect, const sf::Image* image, bool add) { float min_x = std::min(rect.left, cadre.left); float min_y = std::min(rect.top, cadre.top); sf::Texture texture = *sprite_selec.getTexture(); sf::Sprite spr(texture); sprite_selec.setPosition(min_x - 1, min_y - 1); renderTexture_selec.create(std::max(rect.left + rect.width, cadre.left + cadre.width) - min_x + 2, std::max(rect.top + rect.height, cadre.top + cadre.height) - min_y + 2); if (!inverted) renderTexture_selec.clear(ident_color); else renderTexture_selec.clear(blend_color); spr.setPosition(cadre.left - min_x, cadre.top - min_y); renderTexture_selec.draw(spr, sf::BlendNone); renderTexture_selec.display(); if (image == NULL) { sf::Image img; if (add) img.create(rect.width, rect.height, blend_color); else img.create(rect.width, rect.height, ident_color); texture.loadFromImage(img); spr.setTexture(texture, true); spr.setPosition(rect.left - min_x + 1, rect.top - min_y + 1); renderTexture_selec.draw(spr, sf::BlendNone); } else { if (add) RES->getShader(nRer::update).setParameter("mode", 1.f); //Add else RES->getShader(nRer::update).setParameter("mode", 2.f); //Sub RES->getShader(nRer::update).setParameter("offset", sprite_selec.getPosition()); RES->getShader(nRer::update).setParameter("texture", renderTexture_selec.getTexture()); texture.loadFromImage(*image, sf::IntRect(sf::Vector2i(rect.left, rect.top) - VECTOR2I(LAYER->getPosition()), sf::Vector2i(rect.width, rect.height))); sf::Vector2f vect = sf::Vector2f(rect.left, rect.top); spr.setTexture(texture, true); spr.setPosition(vect - sprite_selec.getPosition()); RES->getShader(nRer::update).setParameter("brosse", texture); RES->getShader(nRer::update).setParameter("pos_brosse", vect); renderTexture_selec.draw(spr, RES->getRender(nRer::update)); } renderTexture_selec.display(); sprite_selec.setTexture(renderTexture_selec.getTexture(), true); image_selec = new sf::Image(renderTexture_selec.getTexture().copyToImage()); }
bool PNS_MEANDER_SKEW_PLACER::Start( const VECTOR2I& aP, PNS_ITEM* aStartItem ) { VECTOR2I p; if( !aStartItem || !aStartItem->OfKind( PNS_ITEM::SEGMENT ) ) { Router()->SetFailureReason( _( "Please select a differential pair trace you want to tune." ) ); return false; } m_initialSegment = static_cast<PNS_SEGMENT*>( aStartItem ); p = m_initialSegment->Seg().NearestPoint( aP ); m_originLine = NULL; m_currentNode = NULL; m_currentStart = p; m_world = Router()->GetWorld( )->Branch(); m_originLine = m_world->AssembleLine( m_initialSegment ); PNS_TOPOLOGY topo( m_world ); m_tunedPath = topo.AssembleTrivialPath( m_initialSegment ); if( !topo.AssembleDiffPair ( m_initialSegment, m_originPair ) ) { Router()->SetFailureReason( _( "Unable to find complementary differential pair " "net for skew tuning. Make sure the names of the nets belonging " "to a differential pair end with either _N/_P or +/-." ) ); return false; } if( m_originPair.Gap() < 0 ) m_originPair.SetGap( Router()->Sizes().DiffPairGap() ); if( !m_originPair.PLine().SegmentCount() || !m_originPair.NLine().SegmentCount() ) return false; m_tunedPathP = topo.AssembleTrivialPath( m_originPair.PLine().GetLink( 0 ) ); m_tunedPathN = topo.AssembleTrivialPath( m_originPair.NLine().GetLink( 0 ) ); m_world->Remove( m_originLine ); m_currentWidth = m_originLine->Width( ); m_currentEnd = VECTOR2I( 0, 0 ); if ( m_originPair.PLine().Net () == m_originLine->Net() ) m_coupledLength = itemsetLength( m_tunedPathN ); else m_coupledLength = itemsetLength( m_tunedPathP ); return true; }
void DIALOG_CREATE_ARRAY::calculateCircularArrayProperties() { wxPoint centre; centre.x = DoubleValueFromString( g_UserUnit, m_entryCentreX->GetValue() ); centre.y = DoubleValueFromString( g_UserUnit, m_entryCentreY->GetValue() ); // Find the radius, etc of the circle centre -= m_originalItemPosition; const double radius = VECTOR2I(centre.x, centre.y).EuclideanNorm(); m_labelCircRadiusValue->SetLabelText( StringFromValue( g_UserUnit, int(radius), true ) ); }
bool PL_SELECTION_TOOL::selectionContains( const VECTOR2I& aPoint ) const { const unsigned GRIP_MARGIN = 20; VECTOR2I margin = getView()->ToWorld( VECTOR2I( GRIP_MARGIN, GRIP_MARGIN ), false ); // Check if the point is located within any of the currently selected items bounding boxes for( auto item : m_selection ) { BOX2I itemBox = item->ViewBBox(); itemBox.Inflate( margin.x, margin.y ); // Give some margin for gripping an item if( itemBox.Contains( aPoint ) ) return true; } return false; }
void ZONE_CONTAINER::Move( const wxPoint& offset ) { /* move outlines */ for( unsigned ii = 0; ii < m_Poly->m_CornersList.GetCornersCount(); ii++ ) { SetCornerPosition( ii, GetCornerPosition( ii ) + offset ); } m_Poly->Hatch(); m_FilledPolysList.Move( VECTOR2I( offset.x, offset.y ) ); for( unsigned ic = 0; ic < m_FillSegmList.size(); ic++ ) { m_FillSegmList[ic].m_Start += offset; m_FillSegmList[ic].m_End += offset; } }
void EDGE_MODULE::Move( const wxPoint& aMoveVector ) { // Move an edge of the footprint. // This is a footprint shape modification. m_Start0 += aMoveVector; m_End0 += aMoveVector; switch( GetShape() ) { default: break; case S_POLYGON: // polygon corners coordinates are always relative to the // footprint position, orientation 0 for( auto iter = m_Poly.Iterate(); iter; iter++ ) *iter += VECTOR2I( aMoveVector ); } SetDrawCoord(); }
bool SHAPE_LINE_CHAIN::Parse( std::stringstream& aStream ) { int n_pts; m_points.clear(); aStream >> n_pts; // Rough sanity check, just make sure the loop bounds aren't absolutely outlandish if( n_pts < 0 || n_pts > int( aStream.str().size() ) ) return false; aStream >> m_closed; for( int i = 0; i < n_pts; i++ ) { int x, y; aStream >> x; aStream >> y; m_points.push_back( VECTOR2I( x, y ) ); } return true; }
void SelectionController::createSelection(const sf::IntRect& rect, const sf::Image* image) { renderTexture_selec.create(rect.width + 2, rect.height + 2); renderTexture_selec.clear(ident_color); sprite_selec.setPosition(rect.left - 1, rect.top - 1); sf::Texture texture; if (image == NULL) { sf::Image img; img.create(rect.width, rect.height, blend_color); texture.loadFromImage(img); } else { texture.loadFromImage(*image, sf::IntRect(sf::Vector2i(rect.left, rect.top) - VECTOR2I(LAYER->getPosition()), sf::Vector2i(rect.width, rect.height))); } sf::Sprite spr(texture); spr.setPosition(1, 1); renderTexture_selec.draw(spr, sf::BlendNone); renderTexture_selec.display(); sprite_selec.setTexture(renderTexture_selec.getTexture(), true); image_selec = new sf::Image(renderTexture_selec.getTexture().copyToImage()); }
PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad ) { PNS_LAYERSET layers( 0, MAX_CU_LAYERS - 1 ); // ignore non-copper pads if ( (aPad->GetLayerSet() & LSET::AllCuMask()).none() ) return NULL; switch( aPad->GetAttribute() ) { case PAD_ATTRIB_STANDARD: break; case PAD_ATTRIB_SMD: case PAD_ATTRIB_HOLE_NOT_PLATED: case PAD_ATTRIB_CONN: { LSET lmsk = aPad->GetLayerSet(); bool is_copper = false; for( int i = 0; i < MAX_CU_LAYERS; i++ ) { if( lmsk[i] ) { is_copper = true; if( aPad->GetAttribute() != PAD_ATTRIB_HOLE_NOT_PLATED ) layers = PNS_LAYERSET( i ); break; } } if( !is_copper ) return NULL; } break; default: TRACE( 0, "unsupported pad type 0x%x", aPad->GetAttribute() ); return NULL; } PNS_SOLID* solid = new PNS_SOLID; solid->SetLayers( layers ); solid->SetNet( aPad->GetNetCode() ); solid->SetParent( aPad ); wxPoint wx_c = aPad->ShapePos(); wxSize wx_sz = aPad->GetSize(); wxPoint offset = aPad->GetOffset(); VECTOR2I c( wx_c.x, wx_c.y ); VECTOR2I sz( wx_sz.x, wx_sz.y ); RotatePoint( &offset, aPad->GetOrientation() ); solid->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) ); solid->SetOffset ( VECTOR2I ( offset.x, offset.y ) ); double orient = aPad->GetOrientation() / 10.0; if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) { solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) ); } else { if( orient == 0.0 || orient == 90.0 || orient == 180.0 || orient == 270.0 ) { if( orient == 90.0 || orient == 270.0 ) sz = VECTOR2I( sz.y, sz.x ); switch( aPad->GetShape() ) { case PAD_SHAPE_OVAL: if( sz.x == sz.y ) solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) ); else { VECTOR2I delta; if( sz.x > sz.y ) delta = VECTOR2I( ( sz.x - sz.y ) / 2, 0 ); else delta = VECTOR2I( 0, ( sz.y - sz.x ) / 2 ); SHAPE_SEGMENT* shape = new SHAPE_SEGMENT( c - delta, c + delta, std::min( sz.x, sz.y ) ); solid->SetShape( shape ); } break; case PAD_SHAPE_RECT: solid->SetShape( new SHAPE_RECT( c - sz / 2, sz.x, sz.y ) ); break; case PAD_SHAPE_TRAPEZOID: { wxPoint coords[4]; aPad->BuildPadPolygon( coords, wxSize( 0, 0 ), aPad->GetOrientation() ); SHAPE_CONVEX* shape = new SHAPE_CONVEX(); for( int ii = 0; ii < 4; ii++ ) { shape->Append( wx_c + coords[ii] ); } solid->SetShape( shape ); break; } default: TRACEn( 0, "unsupported pad shape" ); delete solid; return NULL; } } else { switch( aPad->GetShape() ) { // PAD_SHAPE_CIRCLE already handled above case PAD_SHAPE_OVAL: if( sz.x == sz.y ) solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) ); else { wxPoint start; wxPoint end; wxPoint corner; SHAPE_CONVEX* shape = new SHAPE_CONVEX(); int w = aPad->BuildSegmentFromOvalShape( start, end, 0.0, wxSize( 0, 0 ) ); if( start.y == 0 ) corner = wxPoint( start.x, -( w / 2 ) ); else corner = wxPoint( w / 2, start.y ); RotatePoint( &start, aPad->GetOrientation() ); RotatePoint( &corner, aPad->GetOrientation() ); shape->Append( wx_c + corner ); for( int rot = 100; rot <= 1800; rot += 100 ) { wxPoint p( corner ); RotatePoint( &p, start, rot ); shape->Append( wx_c + p ); } if( end.y == 0 ) corner = wxPoint( end.x, w / 2 ); else corner = wxPoint( -( w / 2 ), end.y ); RotatePoint( &end, aPad->GetOrientation() ); RotatePoint( &corner, aPad->GetOrientation() ); shape->Append( wx_c + corner ); for( int rot = 100; rot <= 1800; rot += 100 ) { wxPoint p( corner ); RotatePoint( &p, end, rot ); shape->Append( wx_c + p ); } solid->SetShape( shape ); } break; case PAD_SHAPE_RECT: case PAD_SHAPE_TRAPEZOID: { wxPoint coords[4]; aPad->BuildPadPolygon( coords, wxSize( 0, 0 ), aPad->GetOrientation() ); SHAPE_CONVEX* shape = new SHAPE_CONVEX(); for( int ii = 0; ii < 4; ii++ ) { shape->Append( wx_c + coords[ii] ); } solid->SetShape( shape ); break; } default: TRACEn( 0, "unsupported pad shape" ); delete solid; return NULL; } } } return solid; }
void D_CODE::ConvertShapeToPolygon() { wxPoint initialpos; wxPoint currpos; m_Polygon.RemoveAllContours(); switch( m_Shape ) { case APT_CIRCLE: // creates only a circle with rectangular hole TransformCircleToPolygon( m_Polygon, initialpos, m_Size.x >> 1, SEGS_CNT ); addHoleToPolygon( &m_Polygon, m_DrillShape, m_Drill, initialpos ); break; case APT_RECT: m_Polygon.NewOutline(); currpos.x = m_Size.x / 2; currpos.y = m_Size.y / 2; initialpos = currpos; m_Polygon.Append( VECTOR2I( currpos ) ); currpos.x -= m_Size.x; m_Polygon.Append( VECTOR2I( currpos ) ); currpos.y -= m_Size.y; m_Polygon.Append( VECTOR2I( currpos ) ); currpos.x += m_Size.x; m_Polygon.Append( VECTOR2I( currpos ) ); currpos.y += m_Size.y; m_Polygon.Append( VECTOR2I( currpos ) ); // close polygon m_Polygon.Append( VECTOR2I( initialpos ) ); addHoleToPolygon( &m_Polygon, m_DrillShape, m_Drill, initialpos ); break; case APT_OVAL: { m_Polygon.NewOutline(); int delta, radius; // we create an horizontal oval shape. then rotate if needed if( m_Size.x > m_Size.y ) // horizontal oval { delta = (m_Size.x - m_Size.y) / 2; radius = m_Size.y / 2; } else // vertical oval { delta = (m_Size.y - m_Size.x) / 2; radius = m_Size.x / 2; } currpos.y = radius; initialpos = currpos; m_Polygon.Append( VECTOR2I( currpos ) ); // build the right arc of the shape unsigned ii = 0; for( ; ii <= SEGS_CNT / 2; ii++ ) { currpos = initialpos; RotatePoint( &currpos, ii * 3600.0 / SEGS_CNT ); currpos.x += delta; m_Polygon.Append( VECTOR2I( currpos ) ); } // build the left arc of the shape for( ii = SEGS_CNT / 2; ii <= SEGS_CNT; ii++ ) { currpos = initialpos; RotatePoint( &currpos, ii * 3600.0 / SEGS_CNT ); currpos.x -= delta; m_Polygon.Append( VECTOR2I( currpos ) ); } m_Polygon.Append( VECTOR2I( initialpos ) ); // close outline if( m_Size.y > m_Size.x ) // vertical oval, rotate polygon. { for( auto it = m_Polygon.Iterate( 0 ); it; ++it ) it->Rotate( -M_PI / 2 ); } addHoleToPolygon( &m_Polygon, m_DrillShape, m_Drill, initialpos ); } break; case APT_POLYGON: m_Polygon.NewOutline(); currpos.x = m_Size.x >> 1; // first point is on X axis initialpos = currpos; // rs274x said: m_EdgesCount = 3 ... 12 if( m_EdgesCount < 3 ) m_EdgesCount = 3; if( m_EdgesCount > 12 ) m_EdgesCount = 12; for( int ii = 0; ii < m_EdgesCount; ii++ ) { currpos = initialpos; RotatePoint( &currpos, ii * 3600.0 / m_EdgesCount ); m_Polygon.Append( VECTOR2I( currpos ) ); } addHoleToPolygon( &m_Polygon, m_DrillShape, m_Drill, initialpos ); if( m_Rotation ) // vertical oval, rotate polygon. { int angle = KiROUND( m_Rotation * 10 ); for( auto it = m_Polygon.Iterate( 0 ); it; ++it ) it->Rotate( -angle ); } break; case APT_MACRO: // TODO break; } }
int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) { KIGFX::VIEW_CONTROLS* controls = getViewControls(); PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>(); VECTOR2I originalCursorPos = controls->GetCursorPosition(); const SELECTION& selection = m_selectionTool->GetSelection(); // Shall the selection be cleared at the end? bool unselect = selection.Empty(); // Be sure that there is at least one item that we can modify. If nothing was selected before, // try looking for the stuff under mouse cursor (i.e. Kicad old-style hover selection) if( !hoverSelection( selection ) ) return 0; Activate(); m_dragging = false; // Are selected items being dragged? bool restore = false; // Should items' state be restored when finishing the tool? bool lockOverride = false; // By default, modified items need to update their geometry m_updateFlag = KIGFX::VIEW_ITEM::GEOMETRY; controls->ShowCursor( true ); // cumulative translation wxPoint totalMovement( 0, 0 ); GRID_HELPER grid( editFrame ); OPT_TOOL_EVENT evt = aEvent; // Main loop: keep receiving events do { if( evt->IsCancel() ) { restore = true; // Cancelling the tool means that items have to be restored break; // Finish } else if( evt->Action() == TA_UNDO_REDO ) { unselect = true; break; } else if( evt->IsAction( &COMMON_ACTIONS::editActivate ) || evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) { BOARD_ITEM* item = selection.Item<BOARD_ITEM>( 0 ); if( m_dragging && evt->Category() == TC_MOUSE ) { m_cursor = grid.BestSnapAnchor( evt->Position(), item ); controls->ForceCursorPosition( true, m_cursor ); wxPoint movement = wxPoint( m_cursor.x, m_cursor.y ) - item->GetPosition(); totalMovement += movement; // Drag items to the current cursor position for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) selection.Item<BOARD_ITEM>( i )->Move( movement + m_offset ); updateRatsnest( true ); } else if( !m_dragging ) // Prepare to start dragging { if( !invokeInlineRouter() ) { m_selectionTool->SanitizeSelection(); if( selection.Empty() ) break; // deal with locked items (override lock or abort the operation) SELECTION_LOCK_FLAGS lockFlags = m_selectionTool->CheckLock(); if( lockFlags == SELECTION_LOCKED ) break; else if( lockFlags == SELECTION_LOCK_OVERRIDE ) lockOverride = true; // Save items, so changes can be undone if( !isUndoInhibited() ) { editFrame->OnModify(); editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); } m_cursor = controls->GetCursorPosition(); if( selection.Size() == 1 ) { // Set the current cursor position to the first dragged item origin, so the // movement vector could be computed later m_cursor = grid.BestDragOrigin( originalCursorPos, item ); grid.SetAuxAxes( true, m_cursor ); } else { m_cursor = grid.Align( m_cursor ); } controls->ForceCursorPosition( true, m_cursor ); controls->WarpCursor( m_cursor, true ); VECTOR2I o = VECTOR2I( item->GetPosition() ); m_offset.x = o.x - m_cursor.x; m_offset.y = o.y - m_cursor.y; controls->SetAutoPan( true ); m_dragging = true; incUndoInhibit(); } } selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate, true ); } // Dispatch TOOL_ACTIONs else if( evt->Category() == TC_COMMAND ) { if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { Rotate( aEvent ); } else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { Flip( aEvent ); // Flip causes change of layers enableUpdateFlag( KIGFX::VIEW_ITEM::LAYERS ); } else if( evt->IsAction( &COMMON_ACTIONS::remove ) ) { Remove( aEvent ); break; // exit the loop, as there is no further processing for removed items } else if( evt->IsAction( &COMMON_ACTIONS::duplicate ) ) { // On duplicate, stop moving this item // The duplicate tool should then select the new item and start // a new move procedure break; } else if( evt->IsAction( &COMMON_ACTIONS::moveExact ) ) { // Can't do this, because the selection will then contain // stale pointers and it will all go horribly wrong... //editFrame->RestoreCopyFromUndoList( dummy ); // // So, instead, reset the position manually for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) { BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i ); item->SetPosition( item->GetPosition() - totalMovement ); // And what about flipping and rotation? // for now, they won't be undone, but maybe that is how // it should be, so you can flip and move exact in the // same action? } // This causes a double event, so we will get the dialogue // correctly, somehow - why does Rotate not? //MoveExact( aEvent ); break; // exit the loop - we move exactly, so we have finished moving } } else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) { if( !lockOverride ) break; // Finish lockOverride = false; } } while( evt = Wait() ); if( m_dragging ) decUndoInhibit(); m_dragging = false; m_offset.x = 0; m_offset.y = 0; if( restore ) { // Modifications have to be rollbacked, so restore the previous state of items wxCommandEvent dummy; editFrame->RestoreCopyFromUndoList( dummy ); } else { // Changes are applied, so update the items selection.group->ItemsViewUpdate( m_updateFlag ); } if( unselect ) m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); ratsnest->ClearSimple(); ratsnest->Recalculate(); controls->ShowCursor( false ); controls->SetAutoPan( false ); return 0; }
const BOX2I MODULE::ViewBBox() const { EDA_RECT fpRect = GetFootprintRect(); return BOX2I( VECTOR2I( fpRect.GetOrigin() ), VECTOR2I( fpRect.GetSize() ) ); }