diff --git a/pcbnew/class_dimension.cpp b/pcbnew/class_dimension.cpp index 3a56797468..47cb98b4e4 100644 --- a/pcbnew/class_dimension.cpp +++ b/pcbnew/class_dimension.cpp @@ -47,13 +47,9 @@ DIMENSION::DIMENSION( BOARD_ITEM* aParent ) : BOARD_ITEM( aParent, PCB_DIMENSION_T ), - m_Text( this ) + m_Width( Millimeter2iu( 0.2 ) ), m_Unit( INCHES ), m_Value( 0 ), m_Height( 0 ), m_Text( this ) { m_Layer = DRAW_N; - m_Width = Millimeter2iu( 0.2 ); - m_Value = 0; - m_Shape = 0; - m_Unit = INCHES; } @@ -99,6 +95,7 @@ void DIMENSION::Copy( DIMENSION* source ) SetLayer( source->GetLayer() ); m_Width = source->m_Width; m_Shape = source->m_Shape; + m_Height = source->m_Height; m_Unit = source->m_Unit; SetTimeStamp( GetNewTimeStamp() ); m_Text.Copy( &source->m_Text ); @@ -195,7 +192,6 @@ void DIMENSION::Mirror( const wxPoint& axis_pos ) void DIMENSION::SetOrigin( const wxPoint& aOrigin ) { - m_crossBarO = aOrigin; m_featureLineGO = aOrigin; AdjustDimensionDetails(); @@ -204,29 +200,32 @@ void DIMENSION::SetOrigin( const wxPoint& aOrigin ) void DIMENSION::SetEnd( const wxPoint& aEnd ) { - m_crossBarF = aEnd; m_featureLineDO = aEnd; AdjustDimensionDetails(); } -void DIMENSION::SetHeight( double aHeight ) +void DIMENSION::SetHeight( int aHeight ) { - /* Calculating the direction of travel perpendicular to the selected axis. */ - double angle = GetAngle() + ( M_PI / 2 ); - - int dx = KiROUND( aHeight * cos( angle ) ); - int dy = KiROUND( aHeight * sin( angle ) ); - m_crossBarO.x = m_featureLineGO.x + dx; - m_crossBarO.y = m_featureLineGO.y + dy; - m_crossBarF.x = m_featureLineDO.x + dx; - m_crossBarF.y = m_featureLineDO.y + dy; + m_Height = aHeight; AdjustDimensionDetails(); } +void DIMENSION::UpdateHeight() +{ + VECTOR2D featureLine( m_crossBarO - m_featureLineGO ); + VECTOR2D crossBar( m_featureLineDO - m_featureLineGO ); + + if( featureLine.Cross( crossBar ) > 0 ) + m_Height = -featureLine.EuclideanNorm(); + else + m_Height = featureLine.EuclideanNorm(); +} + + void DIMENSION::AdjustDimensionDetails( bool aDoNotChangeText ) { const int arrowz = DMils2iu( 500 ); // size of arrows @@ -281,6 +280,13 @@ void DIMENSION::AdjustDimensionDetails( bool aDoNotChangeText ) arrow_dw_Y = wxRound( arrowz * sin( angle_f ) ); } + int dx = KiROUND( m_Height * cos( angle + M_PI / 2 ) ); + int dy = KiROUND( m_Height * sin( angle + M_PI / 2 ) ); + m_crossBarO.x = m_featureLineGO.x + dx; + m_crossBarO.y = m_featureLineGO.y + dy; + m_crossBarF.x = m_featureLineDO.x + dx; + m_crossBarF.y = m_featureLineDO.y + dy; + m_arrowG1F.x = m_crossBarO.x + arrow_up_X; m_arrowG1F.y = m_crossBarO.y + arrow_up_Y; diff --git a/pcbnew/class_dimension.h b/pcbnew/class_dimension.h index 2992991505..956c7e4480 100644 --- a/pcbnew/class_dimension.h +++ b/pcbnew/class_dimension.h @@ -61,14 +61,13 @@ class MSG_PANEL_ITEM; */ class DIMENSION : public BOARD_ITEM { - int m_Width; - int m_Shape; // / Currently always 0. - int m_Unit; // / 0 = inches, 1 = mm - int m_Value; // / value of PCB dimensions. - + int m_Width; ///< Line width + int m_Shape; ///< Currently always 0. + EDA_UNITS_T m_Unit; ///< 0 = inches, 1 = mm + int m_Value; ///< value of PCB dimensions. + int m_Height; ///< length of feature lines TEXTE_PCB m_Text; - public: // TODO private: These member should be private. they are public only due to legacy code wxPoint m_crossBarO, m_crossBarF; @@ -117,7 +116,7 @@ public: */ const wxPoint& GetOrigin() const { - return m_crossBarO; + return m_featureLineGO; } /** @@ -133,7 +132,7 @@ public: */ const wxPoint& GetEnd() { - return m_crossBarF; + return m_featureLineDO; } /** @@ -141,12 +140,27 @@ public: * Sets the length of feature lines. * @param aHeight is the new height. */ - void SetHeight( double aHeight ); + void SetHeight( int aHeight ); + + /** + * Function GetHeight + * Returns the length of feature lines. + */ + int GetHeight() const + { + return m_Height; + } + + /** + * Function UpdateHeight + * Updates stored height basing on points coordinates. + */ + void UpdateHeight(); /** * Function GetAngle * Returns angle of the crossbar. - * @return Angle of the crossbar line. + * @return Angle of the crossbar line expressed in radians. */ double GetAngle() const { diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index f82814311e..70e3295f17 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -1438,6 +1438,7 @@ DIMENSION* PCB_PARSER::parseDIMENSION() throw( IO_ERROR, PARSE_ERROR ) parseXY( &dimension->m_featureLineDO.x, &dimension->m_featureLineDO.y ); parseXY( &dimension->m_featureLineDF.x, &dimension->m_featureLineDF.y ); + dimension->UpdateHeight(); NeedRIGHT(); NeedRIGHT(); break; @@ -1451,6 +1452,7 @@ DIMENSION* PCB_PARSER::parseDIMENSION() throw( IO_ERROR, PARSE_ERROR ) parseXY( &dimension->m_featureLineGO.x, &dimension->m_featureLineGO.y ); parseXY( &dimension->m_featureLineGF.x, &dimension->m_featureLineGF.y ); + dimension->UpdateHeight(); NeedRIGHT(); NeedRIGHT(); break; @@ -1465,6 +1467,7 @@ DIMENSION* PCB_PARSER::parseDIMENSION() throw( IO_ERROR, PARSE_ERROR ) parseXY( &dimension->m_crossBarO.x, &dimension->m_crossBarO.y ); parseXY( &dimension->m_crossBarF.x, &dimension->m_crossBarF.y ); + dimension->UpdateHeight(); NeedRIGHT(); NeedRIGHT(); break; diff --git a/pcbnew/tools/edit_points.cpp b/pcbnew/tools/edit_points.cpp index 39102b470a..000da9cb83 100644 --- a/pcbnew/tools/edit_points.cpp +++ b/pcbnew/tools/edit_points.cpp @@ -31,7 +31,7 @@ bool EDIT_POINT::WithinPoint( const VECTOR2I& aPoint, unsigned int aSize ) const { - // Corners of the square + // Corners of the EDIT_POINT square VECTOR2I topLeft = GetPosition() - aSize; VECTOR2I bottomRight = GetPosition() + aSize; @@ -162,6 +162,42 @@ void EPC_45DEGREE::Apply() } +EPC_LINE::EPC_LINE( EDIT_POINT& aConstrained, EDIT_POINT& aConstrainer ) : + EDIT_POINT_CONSTRAINT( aConstrained ), m_constrainer( aConstrainer ) +{ + Update(); +} + + +void EPC_LINE::Apply() +{ + VECTOR2I position = m_constrained.GetPosition(); + + if( std::isfinite( m_coefA ) ) + { + if( abs( m_coefA ) < 1 ) + position.y = m_coefA * position.x + m_coefB; + else + position.x = ( position.y - m_coefB ) / m_coefA; + } + else // vertical line + { + position.x = m_constrainer.GetX(); + } + + m_constrained.SetPosition( position ); +} + + +void EPC_LINE::Update() +{ + // Compute line coefficients + VECTOR2D delta = m_constrainer.GetPosition() - m_constrained.GetPosition(); + m_coefA = delta.y / delta.x; + m_coefB = m_constrainer.GetY() - m_coefA * m_constrainer.GetX(); +} + + void EPC_CIRCLE::Apply() { VECTOR2I centerToEnd = m_end.GetPosition() - m_center.GetPosition(); diff --git a/pcbnew/tools/edit_points.h b/pcbnew/tools/edit_points.h index bdcf5ec55a..1dd0f17014 100644 --- a/pcbnew/tools/edit_points.h +++ b/pcbnew/tools/edit_points.h @@ -97,6 +97,26 @@ public: return m_position; } + /** + * Function GetX() + * + * Returns X coordinate of an EDIT_POINT. + */ + int GetX() const + { + return GetPosition().x; + } + + /** + * Function GetX() + * + * Returns Y coordinate of an EDIT_POINT. + */ + int GetY() const + { + return GetPosition().y; + } + /** * Function SetPosition() * @@ -132,6 +152,17 @@ public: m_constraint = aConstraint; } + /** + * Function GetConstraint() + * + * Returns the constraint imposed on an EDIT_POINT. If there are no constraints, NULL is + * returned. + */ + EDIT_POINT_CONSTRAINT* GetConstraint() const + { + return m_constraint; + } + /** * Function ClearConstraint() * @@ -468,6 +499,32 @@ private: }; +/** + * Class EPC_LINE + * + * EDIT_POINT_CONSTRAINT that imposes a constraint that a point has to lie on a line (determined + * by 2 points). + */ +class EPC_LINE : public EDIT_POINT_CONSTRAINT +{ +public: + EPC_LINE( EDIT_POINT& aConstrained, EDIT_POINT& aConstrainer ); + + ///> @copydoc EDIT_POINT_CONSTRAINT::Apply() + virtual void Apply(); + + /** + * Function Update() + * Updates line coefficients that make the constraining line. + */ + void Update(); + +private: + EDIT_POINT& m_constrainer; ///< Point that imposes the constraint. + double m_coefA, m_coefB; +}; + + /** * Class EPC_CIRCLE. * diff --git a/pcbnew/tools/point_editor.cpp b/pcbnew/tools/point_editor.cpp index 4415aae5a0..bd06e2306c 100644 --- a/pcbnew/tools/point_editor.cpp +++ b/pcbnew/tools/point_editor.cpp @@ -35,6 +35,7 @@ #include #include +#include #include /** @@ -60,8 +61,8 @@ public: switch( segment->GetShape() ) { case S_SEGMENT: - points->AddPoint( segment->GetStart() ); - points->AddPoint( segment->GetEnd() ); + points->AddPoint( segment->GetStart() ); // points[0] + points->AddPoint( segment->GetEnd() ); // points[1] break; case S_ARC: @@ -75,8 +76,8 @@ public: break; case S_CIRCLE: - points->AddPoint( segment->GetCenter() ); - points->AddPoint( segment->GetEnd() ); + points->AddPoint( segment->GetCenter() ); // points[0] + points->AddPoint( segment->GetEnd() ); // points[1] break; default: // suppress warnings @@ -98,8 +99,23 @@ public: for( int i = 0; i < cornersCount - 1; ++i ) points->AddLine( (*points)[i], (*points)[i + 1] ); - // The one missing line + // The last missing line, connecting the last and the first polygon point points->AddLine( (*points)[cornersCount - 1], (*points)[0] ); + break; + } + + case PCB_DIMENSION_T: + { + const DIMENSION* dimension = static_cast( aItem ); + + points->AddPoint( dimension->m_featureLineGO ); + points->AddPoint( dimension->m_featureLineDO ); + points->AddPoint( dimension->m_crossBarO ); + points->AddPoint( dimension->m_crossBarF ); + + // Dimension height setting - edit points should move only along the feature lines + (*points)[2].SetConstraint( new EPC_LINE( (*points)[2], (*points)[0] ) ); + (*points)[3].SetConstraint( new EPC_LINE( (*points)[3], (*points)[1] ) ); break; } @@ -118,7 +134,7 @@ private: POINT_EDITOR::POINT_EDITOR() : - TOOL_INTERACTIVE( "pcbnew.PointEditor" ), m_selectionTool( NULL ) + TOOL_INTERACTIVE( "pcbnew.PointEditor" ), m_selectionTool( NULL ), m_dragPoint( NULL ) { } @@ -159,6 +175,7 @@ int POINT_EDITOR::OnSelectionChange( TOOL_EVENT& aEvent ) PCB_EDIT_FRAME* editFrame = getEditFrame(); EDA_ITEM* item = selection.items.GetPickedItem( 0 ); EDIT_POINT constrainer( VECTOR2I( 0, 0 ) ); + bool degree45 = false; // 45 degree mode m_editPoints = EDIT_POINTS_FACTORY::Make( item ); if( !m_editPoints ) @@ -218,18 +235,20 @@ int POINT_EDITOR::OnSelectionChange( TOOL_EVENT& aEvent ) modified = true; } - if( evt->Modifier( MD_CTRL ) ) // 45 degrees mode + if( evt->Modifier( MD_CTRL ) != degree45 ) // 45 degrees mode { - if( !m_dragPoint->IsConstrained() ) + degree45 = evt->Modifier( MD_CTRL ); + + if( degree45 ) { // Find a proper constraining point for 45 degrees mode constrainer = get45DegConstrainer(); m_dragPoint->SetConstraint( new EPC_45DEGREE( *m_dragPoint, constrainer ) ); } - } - else - { - m_dragPoint->ClearConstraint(); + else + { + m_dragPoint->ClearConstraint(); + } } m_dragPoint->SetPosition( controls->GetCursorPosition() ); @@ -387,6 +406,47 @@ void POINT_EDITOR::updateItem() const break; } + case PCB_DIMENSION_T: + { + DIMENSION* dimension = static_cast( item ); + + // Check which point is currently modified and updated dimension's points respectively + if( isModified( (*m_editPoints)[0] ) ) + { + dimension->SetOrigin( wxPoint( m_dragPoint->GetPosition().x, m_dragPoint->GetPosition().y ) ); + static_cast( (*m_editPoints)[2].GetConstraint() )->Update(); + static_cast( (*m_editPoints)[3].GetConstraint() )->Update(); + } + else if( isModified( (*m_editPoints)[1] ) ) + { + dimension->SetEnd( wxPoint( m_dragPoint->GetPosition().x, m_dragPoint->GetPosition().y ) ); + static_cast( (*m_editPoints)[2].GetConstraint() )->Update(); + static_cast( (*m_editPoints)[3].GetConstraint() )->Update(); + } + else if( isModified( (*m_editPoints)[2] ) ) + { + VECTOR2D featureLine( m_dragPoint->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)[3] ) ) + { + VECTOR2D featureLine( m_dragPoint->GetPosition() - dimension->GetEnd() ); + VECTOR2D crossBar( dimension->GetEnd() - dimension->GetOrigin() ); + + if( featureLine.Cross( crossBar ) > 0 ) + dimension->SetHeight( -featureLine.EuclideanNorm() ); + else + dimension->SetHeight( featureLine.EuclideanNorm() ); + } + + break; + } + default: break; } @@ -454,6 +514,17 @@ void POINT_EDITOR::updatePoints() const break; } + case PCB_DIMENSION_T: + { + const DIMENSION* dimension = static_cast( item ); + + (*m_editPoints)[0].SetPosition( dimension->m_featureLineGO ); + (*m_editPoints)[1].SetPosition( dimension->m_featureLineDO ); + (*m_editPoints)[2].SetPosition( dimension->m_crossBarO ); + (*m_editPoints)[3].SetPosition( dimension->m_crossBarF ); + break; + } + default: break; } @@ -482,6 +553,14 @@ EDIT_POINT POINT_EDITOR::get45DegConstrainer() const } } } + else if( item->Type() == PCB_DIMENSION_T ) + { + // Constraint for crossbar + if( isModified( (*m_editPoints)[0] ) ) + return (*m_editPoints)[1]; + else if( isModified( (*m_editPoints)[1] ) ) + return (*m_editPoints)[0]; + } // In any other case we may align item to the current cursor position. return EDIT_POINT( getViewControls()->GetCursorPosition() );