/**
 * Draw labelled ticks on a line. Ticks are spaced according to a
 * maximum density. Miror ticks are not labelled.
 *
 * @param aGal the GAL to draw on
 * @param aOrigin start of line to draw ticks on
 * @param aLine line vector
 * @param aMinorTickLen length of minor ticks in IU
 */
void drawTicksAlongLine( KIGFX::GAL& aGal, const VECTOR2D& aOrigin,
        const VECTOR2D& aLine, double aMinorTickLen )
{
    VECTOR2D tickLine = aLine.Rotate( -M_PI_2 );

    double tickSpace;
    TICK_FORMAT tickF = getTickFormatForScale( aGal.GetWorldScale(), tickSpace );

    // number of ticks in whole ruler
    int numTicks = (int) std::ceil( aLine.EuclideanNorm() / tickSpace );

    // work out which way up the tick labels go
    double labelAngle = -tickLine.Angle();

    if( aLine.Angle() > 0 )
    {
        aGal.SetHorizontalJustify( GR_TEXT_HJUSTIFY_LEFT );
    }
    else
    {
        aGal.SetHorizontalJustify( GR_TEXT_HJUSTIFY_RIGHT );
        labelAngle += M_PI;
    }

    // text and ticks are dimmed
    aGal.SetStrokeColor( PreviewOverlayDefaultColor().WithAlpha( PreviewOverlayDeemphAlpha( true ) ) );

    const auto labelOffset = tickLine.Resize( aMinorTickLen * ( majorTickLengthFactor + 1 ) );

    for( int i = 0; i < numTicks; ++i )
    {
        const auto tickPos = aOrigin + aLine.Resize( tickSpace * i );

        double length = aMinorTickLen;
        bool drawLabel = false;

        if( i % tickF.majorStep == 0)
        {
            drawLabel = true;
            length *= majorTickLengthFactor;
        }
        else if( tickF.midStep && i % tickF.midStep == 0 )
        {
            drawLabel = true;
            length *= midTickLengthFactor;
        }

        aGal.DrawLine( tickPos, tickPos + tickLine.Resize( length ) );

        if( drawLabel )
        {
            wxString label = DimensionLabel( "", tickSpace * i, g_UserUnit );

            // FIXME: spaces choke OpenGL lp:1668455
            label.erase( std::remove( label.begin(), label.end(), ' ' ), label.end() );

            aGal.BitmapText( label, tickPos + labelOffset, labelAngle );
        }
    }
}
Ejemplo n.º 2
0
void OPENGL_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList )
{
    if( aPointList.empty() )
        return;

    currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );

    std::deque<VECTOR2D>::const_iterator it = aPointList.begin();

    // Start from the second point
    for( ++it; it != aPointList.end(); ++it )
    {
        const VECTOR2D startEndVector = ( *it - *( it - 1 ) );
        double lineAngle = startEndVector.Angle();

        drawLineQuad( *( it - 1 ), *it );

        // There is no need to draw line caps on both ends of polyline's segments
        drawFilledSemiCircle( *( it - 1 ), lineWidth / 2, lineAngle + M_PI / 2 );
    }

    // ..and now - draw the ending cap
    const VECTOR2D startEndVector = ( *( it - 1 ) - *( it - 2 ) );
    double lineAngle = startEndVector.Angle();
    drawFilledSemiCircle( *( it - 1 ), lineWidth / 2, lineAngle - M_PI / 2 );
}
Ejemplo n.º 3
0
void OPENGL_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
{
    const VECTOR2D  startEndVector = aEndPoint - aStartPoint;
    double          lineAngle = startEndVector.Angle();

    currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );

    drawLineQuad( aStartPoint, aEndPoint );

    // Line caps
    if( lineWidth > 1.0 )
    {
        drawFilledSemiCircle( aStartPoint, lineWidth / 2, lineAngle + M_PI / 2 );
        drawFilledSemiCircle( aEndPoint,   lineWidth / 2, lineAngle - M_PI / 2 );
    }
}
Ejemplo n.º 4
0
void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
                              double aWidth )
{
    VECTOR2D startEndVector = aEndPoint - aStartPoint;
    double   lineAngle      = startEndVector.Angle();

    if( isFillEnabled )
    {
        // Filled tracks
        currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a );

        SetLineWidth( aWidth );
        drawLineQuad( aStartPoint, aEndPoint );

        // Draw line caps
        drawFilledSemiCircle( aStartPoint, aWidth / 2, lineAngle + M_PI / 2 );
        drawFilledSemiCircle( aEndPoint,   aWidth / 2, lineAngle - M_PI / 2 );
    }
    else
    {
        // Outlined tracks
        double lineLength = startEndVector.EuclideanNorm();

        currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );

        Save();

        currentManager->Translate( aStartPoint.x, aStartPoint.y, 0.0 );
        currentManager->Rotate( lineAngle, 0.0f, 0.0f, 1.0f );

        drawLineQuad( VECTOR2D( 0.0,         aWidth / 2.0 ),
                      VECTOR2D( lineLength,  aWidth / 2.0 ) );

        drawLineQuad( VECTOR2D( 0.0,        -aWidth / 2.0 ),
                      VECTOR2D( lineLength, -aWidth / 2.0 ) );

        // Draw line caps
        drawStrokedSemiCircle( VECTOR2D( 0.0, 0.0 ), aWidth / 2, M_PI / 2 );
        drawStrokedSemiCircle( VECTOR2D( lineLength, 0.0 ), aWidth / 2, -M_PI / 2 );

        Restore();
    }
}
static void drawCursorStrings( KIGFX::GAL& aGal, const VECTOR2D& aCursor,
    const VECTOR2D& aRulerVec )
{
    // draw the cursor labels
    std::vector<wxString> cursorStrings;

    cursorStrings.push_back( DimensionLabel( "r", aRulerVec.EuclideanNorm(), g_UserUnit ) );

    double degs = RAD2DECIDEG( -aRulerVec.Angle() );
    cursorStrings.push_back( DimensionLabel( "θ", degs, DEGREES ) );

    for( auto& str: cursorStrings )
    {
        // FIXME: remove spaces that choke OpenGL lp:1668455
        str.erase( std::remove( str.begin(), str.end(), ' ' ), str.end() );
    }

    auto temp = aRulerVec;
    DrawTextNextToCursor( aGal, aCursor, -temp, cursorStrings );
}
bool GERBER_DRAW_ITEM::HitTest( const wxPoint& aRefPos ) const
{
    // In case the item has a very tiny width defined, allow it to be selected
    const int MIN_HIT_TEST_RADIUS = Millimeter2iu( 0.01 );

    // calculate aRefPos in XY gerber axis:
    wxPoint ref_pos = GetXYPosition( aRefPos );

    SHAPE_POLY_SET poly;

    switch( m_Shape )
    {
    case GBR_POLYGON:
        poly = m_Polygon;
        return poly.Contains( VECTOR2I( ref_pos ), 0 );

    case GBR_SPOT_POLY:
        poly = GetDcodeDescr()->m_Polygon;
        poly.Move( m_Start );
        return poly.Contains( VECTOR2I( ref_pos ), 0 );

    case GBR_SPOT_RECT:
        return GetBoundingBox().Contains( aRefPos );

    case GBR_ARC:
        {
            double radius = GetLineLength( m_Start, m_ArcCentre );
            VECTOR2D test_radius = VECTOR2D( ref_pos ) - VECTOR2D( m_ArcCentre );

            int size = ( ( m_Size.x < MIN_HIT_TEST_RADIUS ) ? MIN_HIT_TEST_RADIUS
                                                            : m_Size.x );

            // Are we close enough to the radius?
            bool radius_hit = ( std::fabs( test_radius.EuclideanNorm() - radius) < size );

            if( radius_hit )
            {
                // Now check that we are within the arc angle

                VECTOR2D start = VECTOR2D( m_Start ) - VECTOR2D( m_ArcCentre );
                VECTOR2D end = VECTOR2D( m_End ) - VECTOR2D( m_ArcCentre );

                double start_angle = NormalizeAngleRadiansPos( start.Angle() );
                double end_angle = NormalizeAngleRadiansPos( end.Angle() );

                if( m_Start == m_End )
                {
                    start_angle = 0;
                    end_angle = 2 * M_PI;
                }
                else if( end_angle < start_angle )
                {
                    end_angle += 2 * M_PI;
                }

                double test_angle = NormalizeAngleRadiansPos( test_radius.Angle() );

                return ( test_angle > start_angle && test_angle < end_angle );
            }

            return false;
        }

    case GBR_SPOT_MACRO:
        // Aperture macro polygons are already in absolute coordinates
        auto p = GetDcodeDescr()->GetMacro()->GetApertureMacroShape( this, m_Start );
        for( int i = 0; i < p->OutlineCount(); ++i )
        {
            if( p->Contains( VECTOR2I( aRefPos ), i ) )
                return true;
        }
        return false;
    }

    // TODO: a better analyze of the shape (perhaps create a D_CODE::HitTest for flashed items)
    int radius = std::min( m_Size.x, m_Size.y ) >> 1;

    if( radius < MIN_HIT_TEST_RADIUS )
        radius = MIN_HIT_TEST_RADIUS;

    if( m_Flashed )
        return HitTestPoints( m_Start, ref_pos, radius );
    else
        return TestSegmentHit( ref_pos, m_Start, m_End, radius );
}
Ejemplo n.º 7
0
void POINT_EDITOR::updateItem() const
{
    EDA_ITEM* item = m_editPoints->GetParent();

    switch( item->Type() )
    {
    case PCB_LINE_T:
    case PCB_MODULE_EDGE_T:
    {
        DRAWSEGMENT* segment = static_cast<DRAWSEGMENT*>( item );
        switch( segment->GetShape() )
        {
        case S_SEGMENT:
            if( isModified( m_editPoints->Point( SEG_START ) ) )
                segment->SetStart( wxPoint( m_editPoints->Point( SEG_START ).GetPosition().x,
                                            m_editPoints->Point( SEG_START ).GetPosition().y ) );

            else if( isModified( m_editPoints->Point( SEG_END ) ) )
                segment->SetEnd( wxPoint( m_editPoints->Point( SEG_END ).GetPosition().x,
                                          m_editPoints->Point( SEG_END ).GetPosition().y ) );

            break;

        case S_ARC:
        {
            const VECTOR2I& center = m_editPoints->Point( ARC_CENTER ).GetPosition();
            const VECTOR2I& start = m_editPoints->Point( ARC_START ).GetPosition();
            const VECTOR2I& end = m_editPoints->Point( ARC_END ).GetPosition();

            if( center != segment->GetCenter() )
            {
                wxPoint moveVector = wxPoint( center.x, center.y ) - segment->GetCenter();
                segment->Move( moveVector );

                m_editPoints->Point( ARC_START ).SetPosition( segment->GetArcStart() );
                m_editPoints->Point( ARC_END ).SetPosition( segment->GetArcEnd() );
            }

            else
            {
                segment->SetArcStart( wxPoint( start.x, start.y ) );

                VECTOR2D startLine = start - center;
                VECTOR2I endLine = end - center;
                double newAngle = RAD2DECIDEG( endLine.Angle() - startLine.Angle() );

                // Adjust the new angle to (counter)clockwise setting
                bool clockwise = ( segment->GetAngle() > 0 );

                if( clockwise && newAngle < 0.0 )
                    newAngle += 3600.0;
                else if( !clockwise && newAngle > 0.0 )
                    newAngle -= 3600.0;

                segment->SetAngle( newAngle );
            }

            break;
        }

        case S_CIRCLE:
        {
            const VECTOR2I& center = m_editPoints->Point( CIRC_CENTER ).GetPosition();
            const VECTOR2I& end = m_editPoints->Point( CIRC_END ).GetPosition();

            if( isModified( m_editPoints->Point( CIRC_CENTER ) ) )
            {
                wxPoint moveVector = wxPoint( center.x, center.y ) - segment->GetCenter();
                segment->Move( moveVector );
            }
            else
            {
                segment->SetEnd( wxPoint( end.x, end.y ) );
            }

            break;
        }

        default:        // suppress warnings
            break;
        }

        // Update relative coordinates for module edges
        if( EDGE_MODULE* edge = dyn_cast<EDGE_MODULE*>( item ) )
            edge->SetLocalCoord();

        break;
    }

    case PCB_ZONE_AREA_T:
    {
        ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
        zone->ClearFilledPolysList();
        CPolyLine* outline = zone->Outline();

        for( int i = 0; i < outline->GetCornersCount(); ++i )
        {
            VECTOR2I point = m_editPoints->Point( i ).GetPosition();
            outline->SetX( i, point.x );
            outline->SetY( i, point.y );
        }

        break;
    }

    case PCB_DIMENSION_T:
    {
        DIMENSION* dimension = static_cast<DIMENSION*>( item );

        // Check which point is currently modified and updated dimension's points respectively
        if( isModified( m_editPoints->Point( DIM_CROSSBARO ) ) )
        {
            VECTOR2D featureLine( m_editedPoint->GetPosition() - dimension->GetOrigin() );
            VECTOR2D crossBar( dimension->GetEnd() - dimension->GetOrigin() );

            if( featureLine.Cross( crossBar ) > 0 )
                dimension->SetHeight( -featureLine.EuclideanNorm() );
            else
                dimension->SetHeight( featureLine.EuclideanNorm() );
        }

        else if( isModified( m_editPoints->Point( DIM_CROSSBARF ) ) )
        {
            VECTOR2D featureLine( m_editedPoint->GetPosition() - dimension->GetEnd() );
            VECTOR2D crossBar( dimension->GetEnd() - dimension->GetOrigin() );

            if( featureLine.Cross( crossBar ) > 0 )
                dimension->SetHeight( -featureLine.EuclideanNorm() );
            else
                dimension->SetHeight( featureLine.EuclideanNorm() );
        }

        else if( isModified( m_editPoints->Point( DIM_FEATUREGO ) ) )
        {
            dimension->SetOrigin( wxPoint( m_editedPoint->GetPosition().x, m_editedPoint->GetPosition().y ) );
            m_editPoints->Point( DIM_CROSSBARO ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARO ),
                                                                             m_editPoints->Point( DIM_FEATUREGO ) ) );
            m_editPoints->Point( DIM_CROSSBARF ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARF ),
                                                                             m_editPoints->Point( DIM_FEATUREDO ) ) );
        }

        else if( isModified( m_editPoints->Point( DIM_FEATUREDO ) ) )
        {
            dimension->SetEnd( wxPoint( m_editedPoint->GetPosition().x, m_editedPoint->GetPosition().y ) );
            m_editPoints->Point( DIM_CROSSBARO ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARO ),
                                                                             m_editPoints->Point( DIM_FEATUREGO ) ) );
            m_editPoints->Point( DIM_CROSSBARF ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARF ),
                                                                             m_editPoints->Point( DIM_FEATUREDO ) ) );
        }

        break;
    }

    default:
        break;
    }
}