From fc0864befa9eb0d7feef2178586ab80f6cf65135 Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Fri, 8 Oct 2010 16:40:57 -0400 Subject: [PATCH] Schematic component library object code cleaning and refactoring. * Break classes_body_item.cpp(.h) into more reasonable size bites. * Rename classes_body_item.cpp(.h) to lib_draw_item.cpp(.h) * Fix some unsatisfied header file dependencies. * Add stubs to component library draw item base classe to handle editing internally. * Lots of code cleaning. --- bitmap2component/bitmap2component.cpp | 2 +- eeschema/CMakeLists.txt | 7 +- eeschema/bus-wire-junction.cpp | 2 +- eeschema/class_BodyItem_Text.cpp | 2 +- eeschema/class_libentry.cpp | 12 +- eeschema/class_libentry.h | 2 +- eeschema/class_libentry_fields.h | 2 +- eeschema/class_pin.h | 2 +- eeschema/class_sch_component.cpp | 1 + eeschema/classes_body_items.cpp | 2072 ------------------------- eeschema/classes_body_items.h | 930 ----------- eeschema/controle.cpp | 2 +- eeschema/cross-probing.cpp | 2 +- eeschema/general.h | 10 + eeschema/lib_arc.cpp | 438 ++++++ eeschema/lib_arc.h | 96 ++ eeschema/lib_bezier.cpp | 379 +++++ eeschema/lib_bezier.h | 102 ++ eeschema/lib_circle.cpp | 269 ++++ eeschema/lib_circle.h | 92 ++ eeschema/lib_draw_item.cpp | 113 ++ eeschema/lib_draw_item.h | 446 ++++++ eeschema/lib_polyline.cpp | 392 +++++ eeschema/lib_polyline.h | 103 ++ eeschema/lib_rectangle.cpp | 298 ++++ eeschema/lib_rectangle.h | 96 ++ eeschema/libedit_onrightclick.cpp | 9 +- eeschema/protos.h | 57 +- eeschema/symbdraw.cpp | 63 +- include/bezier_curves.h | 3 + include/common.h | 1 + include/plot_common.h | 4 + 32 files changed, 2912 insertions(+), 3097 deletions(-) delete mode 100644 eeschema/classes_body_items.cpp delete mode 100644 eeschema/classes_body_items.h create mode 100644 eeschema/lib_arc.cpp create mode 100644 eeschema/lib_arc.h create mode 100644 eeschema/lib_bezier.cpp create mode 100644 eeschema/lib_bezier.h create mode 100644 eeschema/lib_circle.cpp create mode 100644 eeschema/lib_circle.h create mode 100644 eeschema/lib_draw_item.cpp create mode 100644 eeschema/lib_draw_item.h create mode 100644 eeschema/lib_polyline.cpp create mode 100644 eeschema/lib_polyline.h create mode 100644 eeschema/lib_rectangle.cpp create mode 100644 eeschema/lib_rectangle.h diff --git a/bitmap2component/bitmap2component.cpp b/bitmap2component/bitmap2component.cpp index f61f8348f6..07d3534aec 100644 --- a/bitmap2component/bitmap2component.cpp +++ b/bitmap2component/bitmap2component.cpp @@ -154,7 +154,7 @@ void ArmBoolEng( Bool_Engine* aBooleng, bool aConvertHoles ) * Another scaling with Grid is applied on top of it to create space in the integer number for * even smaller numbers. */ - int GRID = (int) 10000 / DGRID; // initial value = 10000 in kbool example + int GRID = (int) ( 10000 / DGRID ); // initial value = 10000 in kbool example // But we use 10000/DGRID because the scalling is made // by DGRID on integer pcbnew units and diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index beaed0001f..a719bb07d1 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -30,7 +30,6 @@ set(EESCHEMA_SRCS class_schematic_items.cpp class_sch_screen.cpp class_text-label.cpp - classes_body_items.cpp cleanup.cpp cmp_library_keywords.cpp cmp_library_lexer.cpp @@ -97,7 +96,13 @@ set(EESCHEMA_SRCS libedit_onrightclick.cpp libedit_plot_component.cpp libedit_undo_redo.cpp + lib_arc.cpp + lib_bezier.cpp + lib_circle.cpp + lib_draw_item.cpp lib_export.cpp + lib_polyline.cpp + lib_rectangle.cpp libfield.cpp load_one_schematic_file.cpp locate.cpp diff --git a/eeschema/bus-wire-junction.cpp b/eeschema/bus-wire-junction.cpp index 827085534e..da52cdea58 100644 --- a/eeschema/bus-wire-junction.cpp +++ b/eeschema/bus-wire-junction.cpp @@ -9,7 +9,7 @@ #include "confirm.h" #include "program.h" -#include "classes_body_items.h" +#include "lib_draw_item.h" #include "class_pin.h" #include "general.h" #include "protos.h" diff --git a/eeschema/class_BodyItem_Text.cpp b/eeschema/class_BodyItem_Text.cpp index f8cc4afd97..5e43533ce7 100644 --- a/eeschema/class_BodyItem_Text.cpp +++ b/eeschema/class_BodyItem_Text.cpp @@ -16,7 +16,7 @@ #include "trigo.h" #include "program.h" -#include "classes_body_items.h" +#include "lib_draw_item.h" #include "general.h" #include "protos.h" diff --git a/eeschema/class_libentry.cpp b/eeschema/class_libentry.cpp index c1b5eb6bae..171e0a379d 100644 --- a/eeschema/class_libentry.cpp +++ b/eeschema/class_libentry.cpp @@ -5,7 +5,6 @@ #include "fctsys.h" #include "common.h" #include "kicad_string.h" -#include "confirm.h" #include "class_drawpanel.h" #include "plot_common.h" #include "gr_basic.h" @@ -16,6 +15,11 @@ #include "class_library.h" #include "class_libentry.h" #include "class_pin.h" +#include "lib_arc.h" +#include "lib_bezier.h" +#include "lib_circle.h" +#include "lib_polyline.h" +#include "lib_rectangle.h" #include @@ -986,8 +990,7 @@ EDA_Rect LIB_COMPONENT::GetBoundaryBox( int aUnit, int aConvert ) if( item.m_Convert > 0 && ( ( aConvert > 0 ) && ( aConvert != item.m_Convert ) ) ) continue; - if ( ( item.Type() == COMPONENT_FIELD_DRAW_TYPE ) - && !( ( LIB_FIELD& ) item ).IsVisible() ) + if ( ( item.Type() == COMPONENT_FIELD_DRAW_TYPE ) && !( ( LIB_FIELD& ) item ).IsVisible() ) continue; bBox.Merge( item.GetBoundingBox() ); @@ -1198,8 +1201,7 @@ void LIB_COMPONENT::ClearStatus() } -int LIB_COMPONENT::SelectItems( EDA_Rect& aRect, int aUnit, int aConvert, - bool aEditPinByPin ) +int LIB_COMPONENT::SelectItems( EDA_Rect& aRect, int aUnit, int aConvert, bool aEditPinByPin ) { int itemCount = 0; diff --git a/eeschema/class_libentry.h b/eeschema/class_libentry.h index 609d6d1721..4d9b0266ec 100644 --- a/eeschema/class_libentry.h +++ b/eeschema/class_libentry.h @@ -5,7 +5,7 @@ #ifndef CLASS_LIBENTRY_H #define CLASS_LIBENTRY_H -#include "classes_body_items.h" +#include "lib_draw_item.h" #include "class_libentry_fields.h" #include diff --git a/eeschema/class_libentry_fields.h b/eeschema/class_libentry_fields.h index dfee2ff767..c25bcd6a0c 100644 --- a/eeschema/class_libentry_fields.h +++ b/eeschema/class_libentry_fields.h @@ -6,7 +6,7 @@ #define CLASS_LIBENTRY_FIELDS_H #include "program.h" -#include "classes_body_items.h" +#include "lib_draw_item.h" /** diff --git a/eeschema/class_pin.h b/eeschema/class_pin.h index 16c618a72d..92a3570408 100644 --- a/eeschema/class_pin.h +++ b/eeschema/class_pin.h @@ -7,7 +7,7 @@ #ifndef CLASS_PIN_H #define CLASS_PIN_H -#include "classes_body_items.h" +#include "lib_draw_item.h" #define TARGET_PIN_DIAM 12 /* Circle diameter drawn at the active end of * pins */ diff --git a/eeschema/class_sch_component.cpp b/eeschema/class_sch_component.cpp index 8a7ee36f76..4df8d1407d 100644 --- a/eeschema/class_sch_component.cpp +++ b/eeschema/class_sch_component.cpp @@ -15,6 +15,7 @@ #include "protos.h" #include "class_library.h" #include "dialog_schematic_find.h" +#include "lib_rectangle.h" #include diff --git a/eeschema/classes_body_items.cpp b/eeschema/classes_body_items.cpp deleted file mode 100644 index f9e3fbfd7c..0000000000 --- a/eeschema/classes_body_items.cpp +++ /dev/null @@ -1,2072 +0,0 @@ -/************************/ -/* class_body_items.cpp */ -/************************/ - -#include "fctsys.h" -#include "gr_basic.h" -#include "common.h" -#include "class_drawpanel.h" -#include "plot_common.h" -#include "drawtxt.h" -#include "trigo.h" -#include "bezier_curves.h" -#include "confirm.h" - -#include "program.h" -#include "general.h" -#include "protos.h" -#include "classes_body_items.h" - -static int fill_tab[3] = { 'N', 'F', 'f' }; - -//#define DRAW_ARC_WITH_ANGLE // Used to draw arcs - - -/* Base class (abstract) for components bodies items */ -LIB_DRAW_ITEM::LIB_DRAW_ITEM( KICAD_T aType, LIB_COMPONENT* aParent ) : - EDA_BaseStruct( aType ) -{ - m_Unit = 0; /* Unit identification (for multi part per package) - * 0 if the item is common to all units */ - m_Convert = 0; /* Shape identification (for parts which have a convert - * shape) 0 if the item is common to all shapes */ - m_Fill = NO_FILL; - m_Parent = (EDA_BaseStruct*) aParent; - m_typeName = _( "Undefined" ); - m_isFillable = false; -} - - -LIB_DRAW_ITEM::LIB_DRAW_ITEM( const LIB_DRAW_ITEM& aItem ) : - EDA_BaseStruct( aItem ) -{ - m_Unit = aItem.m_Unit; - m_Convert = aItem.m_Convert; - m_Fill = aItem.m_Fill; - m_Parent = aItem.m_Parent; - m_typeName = aItem.m_typeName; - m_isFillable = aItem.m_isFillable; -} - - -/** - * Update the message panel information with the drawing information. - * - * This base function is used to display the information common to the - * all library items. Call the base class from the derived class or the - * common information will not be updated in the message panel. - */ -void LIB_DRAW_ITEM::DisplayInfo( WinEDA_DrawFrame* aFrame ) -{ - wxString msg; - - aFrame->ClearMsgPanel(); - aFrame->AppendMsgPanel( _( "Type" ), m_typeName, CYAN ); - - if( m_Unit == 0 ) - msg = _( "All" ); - else - msg.Printf( wxT( "%d" ), m_Unit ); - aFrame->AppendMsgPanel( _( "Unit" ), msg, BROWN ); - - if( m_Convert == 0 ) - msg = _( "All" ); - else if( m_Convert == 1 ) - msg = _( "no" ); - else if( m_Convert == 2 ) - msg = _( "yes" ); - else - msg = wxT( "?" ); - aFrame->AppendMsgPanel( _( "Convert" ), msg, BROWN ); -} - - -bool LIB_DRAW_ITEM::operator==( const LIB_DRAW_ITEM& aOther ) const -{ - return ( ( Type() == aOther.Type() ) - && ( m_Unit == aOther.m_Unit ) - && ( m_Convert == aOther.m_Convert ) - && DoCompare( aOther ) == 0 ); -} - - -bool LIB_DRAW_ITEM::operator<( const LIB_DRAW_ITEM& aOther ) const -{ - int result = m_Convert - aOther.m_Convert; - - if( result != 0 ) - return result < 0; - - result = m_Unit - aOther.m_Unit; - - if( result != 0 ) - return result < 0; - - result = Type() - aOther.Type(); - - if( result != 0 ) - return result < 0; - - return ( DoCompare( aOther ) < 0 ); -} - - -/**********************/ -/** class LIB_ARC **/ -/**********************/ - -LIB_ARC::LIB_ARC( LIB_COMPONENT* aParent ) : - LIB_DRAW_ITEM( COMPONENT_ARC_DRAW_TYPE, aParent ) -{ - m_Radius = 0; - m_t1 = 0; - m_t2 = 0; - m_Width = 0; - m_Fill = NO_FILL; - m_isFillable = true; - m_typeName = _( "Arc" ); -} - - -LIB_ARC::LIB_ARC( const LIB_ARC& aArc ) : LIB_DRAW_ITEM( aArc ) -{ - m_Radius = aArc.m_Radius; - m_t1 = aArc.m_t1; - m_t2 = aArc.m_t2; - m_Width = aArc.m_Width; - m_Fill = aArc.m_Fill; - m_Pos = aArc.m_Pos; - m_ArcStart = aArc.m_ArcStart; - m_ArcEnd = aArc.m_ArcEnd; -} - - -/** - * format: - * A centre_posx centre_posy rayon start_angle end_angle unit convert - * fill('N', 'F' ou 'f') startx starty endx endy - */ -bool LIB_ARC::Save( FILE* aFile ) -{ - int x1 = m_t1; - - if( x1 > 1800 ) - x1 -= 3600; - - int x2 = m_t2; - - if( x2 > 1800 ) - x2 -= 3600; - - if( fprintf( aFile, "A %d %d %d %d %d %d %d %d %c %d %d %d %d\n", - m_Pos.x, m_Pos.y, m_Radius, x1, x2, m_Unit, m_Convert, m_Width, - fill_tab[m_Fill], m_ArcStart.x, m_ArcStart.y, m_ArcEnd.x, - m_ArcEnd.y ) < 0 ) - return false; - - return true; -} - - -bool LIB_ARC::Load( char* aLine, wxString& aErrorMsg ) -{ - int startx, starty, endx, endy, cnt; - char tmp[256]; - - cnt = sscanf( &aLine[2], "%d %d %d %d %d %d %d %d %s %d %d %d %d", - &m_Pos.x, &m_Pos.y, &m_Radius, &m_t1, &m_t2, &m_Unit, - &m_Convert, &m_Width, tmp, &startx, &starty, &endx, &endy ); - if( cnt < 8 ) - { - aErrorMsg.Printf( _( "arc only had %d parameters of the required 8" ), - cnt ); - return false; - } - - if( tmp[0] == 'F' ) - m_Fill = FILLED_SHAPE; - if( tmp[0] == 'f' ) - m_Fill = FILLED_WITH_BG_BODYCOLOR; - - NORMALIZE_ANGLE( m_t1 ); - NORMALIZE_ANGLE( m_t2 ); - - // Actual Coordinates of arc ends are read from file - if( cnt >= 13 ) - { - m_ArcStart.x = startx; - m_ArcStart.y = starty; - m_ArcEnd.x = endx; - m_ArcEnd.y = endy; - } - else - { - // Actual Coordinates of arc ends are not read from file - // (old library), calculate them - m_ArcStart.x = m_Radius; - m_ArcStart.y = 0; - m_ArcEnd.x = m_Radius; - m_ArcEnd.y = 0; - RotatePoint( &m_ArcStart.x, &m_ArcStart.y, -m_t1 ); - m_ArcStart.x += m_Pos.x; - m_ArcStart.y += m_Pos.y; - RotatePoint( &m_ArcEnd.x, &m_ArcEnd.y, -m_t2 ); - m_ArcEnd.x += m_Pos.x; - m_ArcEnd.y += m_Pos.y; - } - - return true; -} - - -/** - * Function HitTest - * tests if the given wxPoint is within the bounds of this object. - * @param aRefPoint A wxPoint to test in eeschema space - * @return bool - true if a hit, else false - */ -bool LIB_ARC::HitTest( const wxPoint& aRefPoint ) -{ - int mindist = m_Width ? m_Width / 2 : g_DrawDefaultLineThickness / 2; - - // Have a minimal tolerance for hit test - if( mindist < MINIMUM_SELECTION_DISTANCE ) - mindist = MINIMUM_SELECTION_DISTANCE; - - return HitTest( aRefPoint, mindist, DefaultTransformMatrix ); -} - -/** Function HitTest - * @return true if the point aPosRef is near this object - * @param aRefPoint = a wxPoint to test - * @param aThreshold = max distance to this object (usually the half thickness - * of a line) - * @param aTransMat = the transform matrix - */ -bool LIB_ARC::HitTest( wxPoint aReferencePoint, int aThreshold, - const int aTransformationMatrix[2][2] ) -{ - - // TODO: use aTransMat to calculmates parameters - wxPoint relativePosition = aReferencePoint; - - NEGATE( relativePosition.y ); // reverse Y axis - - int distance = wxRound( EuclideanNorm(TwoPointVector(m_Pos, relativePosition) ) ); - - if( abs( distance - m_Radius ) > aThreshold ) - return false; - - // We are on the circle, ensure we are only on the arc, i.e. between - // m_ArcStart and m_ArcEnd - - wxPoint startEndVector = TwoPointVector( m_ArcStart, m_ArcEnd); - wxPoint startRelativePositionVector = TwoPointVector( m_ArcStart, relativePosition); - - wxPoint centerStartVector = TwoPointVector( m_Pos, m_ArcStart); - wxPoint centerEndVector = TwoPointVector( m_Pos, m_ArcEnd); - wxPoint centerRelativePositionVector = TwoPointVector( m_Pos, relativePosition); - - // Compute the cross product to check if the point is in the sector - int crossProductStart = CrossProduct(centerStartVector, centerRelativePositionVector); - int crossProductEnd = CrossProduct(centerEndVector, centerRelativePositionVector); - - // The cross products need to be exchanged, depending on which side the center point - // relative to the start point to end point vector lies - if (CrossProduct(startEndVector, startRelativePositionVector) < 0 ){ - EXCHG(crossProductStart, crossProductEnd); - } - - // When the cross products have a different sign, the point lies in sector - // also check, if the reference is near start or end point - return HitTestPoints(m_ArcStart, relativePosition, MINIMUM_SELECTION_DISTANCE) || - HitTestPoints(m_ArcEnd, relativePosition, MINIMUM_SELECTION_DISTANCE) || - (crossProductStart <= 0 && crossProductEnd >= 0); -} - - -LIB_DRAW_ITEM* LIB_ARC::DoGenCopy() -{ - LIB_ARC* newitem = new LIB_ARC( GetParent() ); - - newitem->m_Pos = m_Pos; - newitem->m_ArcStart = m_ArcStart; - newitem->m_ArcEnd = m_ArcEnd; - newitem->m_Radius = m_Radius; - newitem->m_t1 = m_t1; - newitem->m_t2 = m_t2; - newitem->m_Width = m_Width; - newitem->m_Unit = m_Unit; - newitem->m_Convert = m_Convert; - newitem->m_Flags = m_Flags; - newitem->m_Fill = m_Fill; - - return (LIB_DRAW_ITEM*) newitem; -} - - -int LIB_ARC::DoCompare( const LIB_DRAW_ITEM& aOther ) const -{ - wxASSERT( aOther.Type() == COMPONENT_ARC_DRAW_TYPE ); - - const LIB_ARC* tmp = ( LIB_ARC* ) &aOther; - - if( m_Pos.x != tmp->m_Pos.x ) - return m_Pos.x - tmp->m_Pos.x; - - if( m_Pos.y != tmp->m_Pos.y ) - return m_Pos.y - tmp->m_Pos.y; - - if( m_t1 != tmp->m_t1 ) - return m_t1 - tmp->m_t1; - - if( m_t2 != tmp->m_t2 ) - return m_t2 - tmp->m_t2; - - return 0; -} - - -void LIB_ARC::DoOffset( const wxPoint& aOffset ) -{ - m_Pos += aOffset; - m_ArcStart += aOffset; - m_ArcEnd += aOffset; -} - - -bool LIB_ARC::DoTestInside( EDA_Rect& aRect ) -{ - return aRect.Inside( m_ArcStart.x, -m_ArcStart.y ) - || aRect.Inside( m_ArcEnd.x, -m_ArcEnd.y ); -} - - -void LIB_ARC::DoMove( const wxPoint& aPosition ) -{ - wxPoint offset = aPosition - m_Pos; - m_Pos = aPosition; - m_ArcStart += offset; - m_ArcEnd += offset; -} - - -void LIB_ARC::DoMirrorHorizontal( const wxPoint& aCenter ) -{ - m_Pos.x -= aCenter.x; - m_Pos.x *= -1; - m_Pos.x += aCenter.x; - m_ArcStart.x -= aCenter.x; - m_ArcStart.x *= -1; - m_ArcStart.x += aCenter.x; - m_ArcEnd.x -= aCenter.x; - m_ArcEnd.x *= -1; - m_ArcEnd.x += aCenter.x; - EXCHG( m_ArcStart, m_ArcEnd ); -} - - -void LIB_ARC::DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, - const int aTransform[2][2] ) -{ - wxASSERT( aPlotter != NULL ); - - int t1 = m_t1; - int t2 = m_t2; - wxPoint pos = TransformCoordinate( aTransform, m_Pos ) + aOffset; - - MapAngles( &t1, &t2, aTransform ); - - if( aFill && m_Fill == FILLED_WITH_BG_BODYCOLOR ) - { - aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); - aPlotter->arc( pos, -t2, -t1, m_Radius, FILLED_SHAPE, 0 ); - } - - aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE ) ); - aPlotter->arc( pos, -t2, -t1, m_Radius, m_Fill, GetPenSize() ); -} - - -/** Function GetPenSize - * @return the size of the "pen" that be used to draw or plot this item - */ -int LIB_ARC::GetPenSize() -{ - return ( m_Width == 0 ) ? g_DrawDefaultLineThickness : m_Width; -} - - -void LIB_ARC::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, - const wxPoint& aOffset, int aColor, int aDrawMode, - void* aData, const int aTransformMatrix[2][2] ) -{ - wxPoint pos1, pos2, posc; - - int color = ReturnLayerColor( LAYER_DEVICE ); - - if( aColor < 0 ) // Used normal color or selected color - { - if( ( m_Selected & IS_SELECTED ) ) - color = g_ItemSelectetColor; - } - else - color = aColor; - - pos1 = TransformCoordinate( aTransformMatrix, m_ArcEnd ) + aOffset; - pos2 = TransformCoordinate( aTransformMatrix, m_ArcStart ) + aOffset; - posc = TransformCoordinate( aTransformMatrix, m_Pos ) + aOffset; - int pt1 = m_t1; - int pt2 = m_t2; - bool swap = MapAngles( &pt1, &pt2, aTransformMatrix ); - if( swap ) - { - EXCHG( pos1.x, pos2.x ); - EXCHG( pos1.y, pos2.y ); - } - - GRSetDrawMode( aDC, aDrawMode ); - - FILL_T fill = aData ? NO_FILL : m_Fill; - if( aColor >= 0 ) - fill = NO_FILL; - - if( fill == FILLED_WITH_BG_BODYCOLOR ) - GRFilledArc( &aPanel->m_ClipBox, aDC, posc.x, posc.y, pt1, pt2, - m_Radius, GetPenSize( ), - (m_Flags & IS_MOVED) ? color : ReturnLayerColor( LAYER_DEVICE_BACKGROUND ), - ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); - else if( fill == FILLED_SHAPE && !aData ) - GRFilledArc( &aPanel->m_ClipBox, aDC, posc.x, posc.y, pt1, pt2, - m_Radius, color, color ); - else - { -#ifdef DRAW_ARC_WITH_ANGLE - - GRArc( &aPanel->m_ClipBox, aDC, posc.x, posc.y, pt1, pt2, - m_Radius, GetPenSize( ), color ); -#else - - GRArc1( &aPanel->m_ClipBox, aDC, pos1.x, pos1.y, pos2.x, pos2.y, - posc.x, posc.y, GetPenSize( ), color ); -#endif - } - - /* Set to one (1) to draw bounding box around arc to validate bounding box - * calculation. */ -#if 0 - EDA_Rect bBox = GetBoundingBox(); - GRRect( &aPanel->m_ClipBox, aDC, bBox.GetOrigin().x, bBox.GetOrigin().y, - bBox.GetEnd().x, bBox.GetEnd().y, 0, LIGHTMAGENTA ); -#endif -} - - -EDA_Rect LIB_ARC::GetBoundingBox() -{ - int minX, minY, maxX, maxY, angleStart, angleEnd; - EDA_Rect rect; - wxPoint nullPoint, startPos, endPos, centerPos; - wxPoint normStart = m_ArcStart - m_Pos; - wxPoint normEnd = m_ArcEnd - m_Pos; - - if( ( normStart == nullPoint ) || ( normEnd == nullPoint ) - || ( m_Radius == 0 ) ) - { - wxLogDebug( wxT("Invalid arc drawing definition, center(%d, %d) \ -start(%d, %d), end(%d, %d), radius %d" ), - m_Pos.x, m_Pos.y, m_ArcStart.x, m_ArcStart.y, m_ArcEnd.x, - m_ArcEnd.y, m_Radius ); - return rect; - } - - endPos = TransformCoordinate( DefaultTransformMatrix, m_ArcEnd ); - startPos = TransformCoordinate( DefaultTransformMatrix, m_ArcStart ); - centerPos = TransformCoordinate( DefaultTransformMatrix, m_Pos ); - angleStart = m_t1; - angleEnd = m_t2; - - if( MapAngles( &angleStart, &angleEnd, DefaultTransformMatrix ) ) - { - EXCHG( endPos.x, startPos.x ); - EXCHG( endPos.y, startPos.y ); - } - - /* Start with the start and end point of the arc. */ - minX = MIN( startPos.x, endPos.x ); - minY = MIN( startPos.y, endPos.y ); - maxX = MAX( startPos.x, endPos.x ); - maxY = MAX( startPos.y, endPos.y ); - - /* Zero degrees is a special case. */ - if( angleStart == 0 ) - maxX = centerPos.x + m_Radius; - - /* Arc end angle wrapped passed 360. */ - if( angleStart > angleEnd ) - angleEnd += 3600; - - if( angleStart <= 900 && angleEnd >= 900 ) /* 90 deg */ - maxY = centerPos.y + m_Radius; - if( angleStart <= 1800 && angleEnd >= 1800 ) /* 180 deg */ - minX = centerPos.x - m_Radius; - if( angleStart <= 2700 && angleEnd >= 2700 ) /* 270 deg */ - minY = centerPos.y - m_Radius; - if( angleStart <= 3600 && angleEnd >= 3600 ) /* 0 deg */ - maxX = centerPos.x + m_Radius; - - rect.SetOrigin( minX, minY ); - rect.SetEnd( maxX, maxY ); - rect.Inflate( m_Width / 2, m_Width / 2 ); - - return rect; -} - - -void LIB_ARC::DisplayInfo( WinEDA_DrawFrame* aFrame ) -{ - wxString msg; - EDA_Rect bBox = GetBoundingBox(); - - LIB_DRAW_ITEM::DisplayInfo( aFrame ); - - msg = ReturnStringFromValue( g_UserUnit, m_Width, - EESCHEMA_INTERNAL_UNIT, true ); - - aFrame->AppendMsgPanel( _( "Line width" ), msg, BLUE ); - - msg.Printf( wxT( "(%d, %d, %d, %d)" ), bBox.GetOrigin().x, - bBox.GetOrigin().y, bBox.GetEnd().x, bBox.GetEnd().y ); - - aFrame->AppendMsgPanel( _( "Bounding box" ), msg, BROWN ); -} - - -/*************************/ -/** class LIB_CIRCLE **/ -/*************************/ - -LIB_CIRCLE::LIB_CIRCLE( LIB_COMPONENT* aParent ) : - LIB_DRAW_ITEM( COMPONENT_CIRCLE_DRAW_TYPE, aParent ) -{ - m_Radius = 0; - m_Fill = NO_FILL; - m_isFillable = true; - m_typeName = _( "Circle" ); -} - - -LIB_CIRCLE::LIB_CIRCLE( const LIB_CIRCLE& aCircle ) : - LIB_DRAW_ITEM( aCircle ) -{ - m_Pos = aCircle.m_Pos; - m_Radius = aCircle.m_Radius; - m_Fill = aCircle.m_Fill; -} - - -bool LIB_CIRCLE::Save( FILE* aFile ) -{ - if( fprintf( aFile, "C %d %d %d %d %d %d %c\n", m_Pos.x, m_Pos.y, - m_Radius, m_Unit, m_Convert, m_Width, fill_tab[m_Fill] ) < 0 ) - return false; - - return true; -} - - -bool LIB_CIRCLE::Load( char* aLine, wxString& aErrorMsg ) -{ - char tmp[256]; - - int cnt = sscanf( &aLine[2], "%d %d %d %d %d %d %s", &m_Pos.x, &m_Pos.y, - &m_Radius, &m_Unit, &m_Convert, &m_Width, tmp ); - - if( cnt < 6 ) - { - aErrorMsg.Printf( _( "circle only had %d parameters of the required 6" ), - cnt ); - return false; - } - - if( tmp[0] == 'F' ) - m_Fill = FILLED_SHAPE; - if( tmp[0] == 'f' ) - m_Fill = FILLED_WITH_BG_BODYCOLOR; - - return true; -} - - -/** - * Function HitTest - * tests if the given wxPoint is within the bounds of this object. - * @param aRefPos A wxPoint to test in eeschema space - * @return - true if a hit, else false - */ -bool LIB_CIRCLE::HitTest( const wxPoint& aPosRef ) -{ - int mindist = m_Width ? m_Width / 2 : g_DrawDefaultLineThickness / 2; - - // Have a minimal tolerance for hit test - if( mindist < MINIMUM_SELECTION_DISTANCE ) - mindist = MINIMUM_SELECTION_DISTANCE; - - return HitTest( aPosRef, mindist, DefaultTransformMatrix ); -} - - -/** Function HitTest - * @return true if the point aPosRef is near this object - * @param aPosRef = a wxPoint to test - * @param aThreshold = max distance to this object (usually the half - * thickness of a line) - * @param aTransMat = the transform matrix - */ -bool LIB_CIRCLE::HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] ) -{ - wxPoint relpos = aPosRef - TransformCoordinate( aTransMat, m_Pos ); - - int dist = - wxRound( sqrt( ( (double) relpos.x * relpos.x ) + - ( (double) relpos.y * relpos.y ) ) ); - - if( abs( dist - m_Radius ) <= aThreshold ) - return true; - return false; -} - - -LIB_DRAW_ITEM* LIB_CIRCLE::DoGenCopy() -{ - LIB_CIRCLE* newitem = new LIB_CIRCLE( GetParent() ); - - newitem->m_Pos = m_Pos; - newitem->m_Radius = m_Radius; - newitem->m_Width = m_Width; - newitem->m_Unit = m_Unit; - newitem->m_Convert = m_Convert; - newitem->m_Flags = m_Flags; - newitem->m_Fill = m_Fill; - - return (LIB_DRAW_ITEM*) newitem; -} - - -int LIB_CIRCLE::DoCompare( const LIB_DRAW_ITEM& aOther ) const -{ - wxASSERT( aOther.Type() == COMPONENT_CIRCLE_DRAW_TYPE ); - - const LIB_CIRCLE* tmp = ( LIB_CIRCLE* ) &aOther; - - if( m_Pos.x != tmp->m_Pos.x ) - return m_Pos.x - tmp->m_Pos.x; - - if( m_Pos.y != tmp->m_Pos.y ) - return m_Pos.y - tmp->m_Pos.y; - - if( m_Radius != tmp->m_Radius ) - return m_Radius - tmp->m_Radius; - - return 0; -} - - -void LIB_CIRCLE::DoOffset( const wxPoint& aOffset ) -{ - m_Pos += aOffset; -} - - -bool LIB_CIRCLE::DoTestInside( EDA_Rect& aRect ) -{ - /* - * FIXME: This fails to take into acount the radius around the center - * point. - */ - return aRect.Inside( m_Pos.x, -m_Pos.y ); -} - - -void LIB_CIRCLE::DoMove( const wxPoint& aPosition ) -{ - m_Pos = aPosition; -} - - -void LIB_CIRCLE::DoMirrorHorizontal( const wxPoint& aCenter ) -{ - m_Pos.x -= aCenter.x; - m_Pos.x *= -1; - m_Pos.x += aCenter.x; -} - - -void LIB_CIRCLE::DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, - const int aTransform[2][2] ) -{ - wxPoint pos = TransformCoordinate( aTransform, m_Pos ) + aOffset; - - if( aFill && m_Fill == FILLED_WITH_BG_BODYCOLOR ) - { - aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); - aPlotter->circle( pos, m_Radius * 2, FILLED_SHAPE, 0 ); - } - - aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE ) ); - aPlotter->circle( pos, m_Radius * 2, m_Fill, GetPenSize() ); -} - - -/** Function GetPenSize - * @return the size of the "pen" that be used to draw or plot this item - */ -int LIB_CIRCLE::GetPenSize() -{ - return ( m_Width == 0 ) ? g_DrawDefaultLineThickness : m_Width; -} - - -void LIB_CIRCLE::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, - const wxPoint& aOffset, int aColor, int aDrawMode, - void* aData, const int aTransformMatrix[2][2] ) -{ - wxPoint pos1; - - int color = ReturnLayerColor( LAYER_DEVICE ); - - if( aColor < 0 ) // Used normal color or selected color - { - if( ( m_Selected & IS_SELECTED ) ) - color = g_ItemSelectetColor; - } - else - color = aColor; - - pos1 = TransformCoordinate( aTransformMatrix, m_Pos ) + aOffset; - GRSetDrawMode( aDC, aDrawMode ); - - FILL_T fill = aData ? NO_FILL : m_Fill; - if( aColor >= 0 ) - fill = NO_FILL; - - if( fill == FILLED_WITH_BG_BODYCOLOR ) - GRFilledCircle( &aPanel->m_ClipBox, aDC, pos1.x, pos1.y, - m_Radius, GetPenSize( ), - (m_Flags & IS_MOVED) ? color : ReturnLayerColor( LAYER_DEVICE_BACKGROUND ), - ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); - else if( fill == FILLED_SHAPE ) - GRFilledCircle( &aPanel->m_ClipBox, aDC, pos1.x, pos1.y, - m_Radius, 0, color, color ); - else - GRCircle( &aPanel->m_ClipBox, aDC, pos1.x, pos1.y, - m_Radius, GetPenSize( ), color ); - - /* Set to one (1) to draw bounding box around circle to validate bounding - * box calculation. */ -#if 0 - EDA_Rect bBox = GetBoundingBox(); - GRRect( &aPanel->m_ClipBox, aDC, bBox.GetOrigin().x, bBox.GetOrigin().y, - bBox.GetEnd().x, bBox.GetEnd().y, 0, LIGHTMAGENTA ); -#endif -} - - -EDA_Rect LIB_CIRCLE::GetBoundingBox() -{ - EDA_Rect rect; - - rect.SetOrigin( m_Pos.x - m_Radius, ( m_Pos.y - m_Radius ) * -1 ); - rect.SetEnd( m_Pos.x + m_Radius, ( m_Pos.y + m_Radius ) * -1 ); - rect.Inflate( m_Width / 2, m_Width / 2 ); - - return rect; -} - - -void LIB_CIRCLE::DisplayInfo( WinEDA_DrawFrame* aFrame ) -{ - wxString msg; - EDA_Rect bBox = GetBoundingBox(); - - LIB_DRAW_ITEM::DisplayInfo( aFrame ); - - msg = ReturnStringFromValue( g_UserUnit, m_Width, - EESCHEMA_INTERNAL_UNIT, true ); - - aFrame->AppendMsgPanel( _( "Line width" ), msg, BLUE ); - - msg = ReturnStringFromValue( g_UserUnit, m_Radius, - EESCHEMA_INTERNAL_UNIT, true ); - aFrame->AppendMsgPanel( _( "Radius" ), msg, RED ); - - msg.Printf( wxT( "(%d, %d, %d, %d)" ), bBox.GetOrigin().x, - bBox.GetOrigin().y, bBox.GetEnd().x, bBox.GetEnd().y ); - - aFrame->AppendMsgPanel( _( "Bounding box" ), msg, BROWN ); -} - - -/*************************/ -/** class LIB_RECTANGLE **/ -/*************************/ - -LIB_RECTANGLE::LIB_RECTANGLE( LIB_COMPONENT* aParent ) : - LIB_DRAW_ITEM( COMPONENT_RECT_DRAW_TYPE, aParent ) -{ - m_Width = 0; - m_Fill = NO_FILL; - m_isFillable = true; - m_typeName = _( "Rectangle" ); - m_isHeightLocked = false; - m_isWidthLocked = false; - m_isStartPointSelected = false; -} - - -LIB_RECTANGLE::LIB_RECTANGLE( const LIB_RECTANGLE& aRect ) : - LIB_DRAW_ITEM( aRect ) -{ - m_Pos = aRect.m_Pos; - m_End = aRect.m_End; - m_Width = aRect.m_Width; - m_Fill = aRect.m_Fill; -} - - -bool LIB_RECTANGLE::Save( FILE* aFile ) -{ - if( fprintf( aFile, "S %d %d %d %d %d %d %d %c\n", m_Pos.x, m_Pos.y, - m_End.x, m_End.y, m_Unit, m_Convert, m_Width, - fill_tab[m_Fill] ) < 0 ) - return false; - - return true; -} - - -bool LIB_RECTANGLE::Load( char* aLine, wxString& aErrorMsg ) -{ - int cnt; - char tmp[256]; - - cnt = sscanf( &aLine[2], "%d %d %d %d %d %d %d %s", &m_Pos.x, &m_Pos.y, - &m_End.x, &m_End.y, &m_Unit, &m_Convert, &m_Width, tmp ); - - if( cnt < 7 ) - { - aErrorMsg.Printf( _( "rectangle only had %d parameters of the required 7" ), - cnt ); - return false; - } - - if( tmp[0] == 'F' ) - m_Fill = FILLED_SHAPE; - if( tmp[0] == 'f' ) - m_Fill = FILLED_WITH_BG_BODYCOLOR; - - return true; -} - - -LIB_DRAW_ITEM* LIB_RECTANGLE::DoGenCopy() -{ - LIB_RECTANGLE* newitem = new LIB_RECTANGLE( GetParent() ); - - newitem->m_Pos = m_Pos; - newitem->m_End = m_End; - newitem->m_Width = m_Width; - newitem->m_Unit = m_Unit; - newitem->m_Convert = m_Convert; - newitem->m_Flags = m_Flags; - newitem->m_Fill = m_Fill; - - return (LIB_DRAW_ITEM*) newitem; -} - - -int LIB_RECTANGLE::DoCompare( const LIB_DRAW_ITEM& aOther ) const -{ - wxASSERT( aOther.Type() == COMPONENT_RECT_DRAW_TYPE ); - - const LIB_RECTANGLE* tmp = ( LIB_RECTANGLE* ) &aOther; - - if( m_Pos.x != tmp->m_Pos.x ) - return m_Pos.x - tmp->m_Pos.x; - - if( m_Pos.y != tmp->m_Pos.y ) - return m_Pos.y - tmp->m_Pos.y; - - if( m_End.x != tmp->m_End.x ) - return m_End.x - tmp->m_End.x; - - if( m_End.y != tmp->m_End.y ) - return m_End.y - tmp->m_End.y; - - return 0; -} - - -void LIB_RECTANGLE::DoOffset( const wxPoint& aOffset ) -{ - m_Pos += aOffset; - m_End += aOffset; -} - - -bool LIB_RECTANGLE::DoTestInside( EDA_Rect& aRect ) -{ - return aRect.Inside( m_Pos.x, -m_Pos.y ) || aRect.Inside( m_End.x, -m_End.y ); -} - - -void LIB_RECTANGLE::DoMove( const wxPoint& aPosition ) -{ - wxPoint size = m_End - m_Pos; - m_Pos = aPosition; - m_End = aPosition + size; -} - - -void LIB_RECTANGLE::DoMirrorHorizontal( const wxPoint& aCenter ) -{ - m_Pos.x -= aCenter.x; - m_Pos.x *= -1; - m_Pos.x += aCenter.x; - m_End.x -= aCenter.x; - m_End.x *= -1; - m_End.x += aCenter.x; -} - - -void LIB_RECTANGLE::DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, - const int aTransform[2][2] ) -{ - wxASSERT( aPlotter != NULL ); - - wxPoint pos = TransformCoordinate( aTransform, m_Pos ) + aOffset; - wxPoint end = TransformCoordinate( aTransform, m_End ) + aOffset; - - if( aFill && m_Fill == FILLED_WITH_BG_BODYCOLOR ) - { - aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); - aPlotter->rect( pos, end, FILLED_WITH_BG_BODYCOLOR, 0 ); - } - - aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE ) ); - aPlotter->rect( pos, end, m_Fill, GetPenSize() ); -} - - -/** Function GetPenSize - * @return the size of the "pen" that be used to draw or plot this item - */ -int LIB_RECTANGLE::GetPenSize() -{ - return ( m_Width == 0 ) ? g_DrawDefaultLineThickness : m_Width; -} - -void LIB_RECTANGLE::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, - const wxPoint& aOffset, int aColor, int aDrawMode, - void* aData, const int aTransformMatrix[2][2] ) -{ - wxPoint pos1, pos2; - - int color = ReturnLayerColor( LAYER_DEVICE ); - - if( aColor < 0 ) // Used normal color or selected color - { - if( m_Selected & IS_SELECTED ) - color = g_ItemSelectetColor; - } - else - color = aColor; - - pos1 = TransformCoordinate( aTransformMatrix, m_Pos ) + aOffset; - pos2 = TransformCoordinate( aTransformMatrix, m_End ) + aOffset; - - FILL_T fill = aData ? NO_FILL : m_Fill; - if( aColor >= 0 ) - fill = NO_FILL; - - GRSetDrawMode( aDC, aDrawMode ); - - if( fill == FILLED_WITH_BG_BODYCOLOR && !aData ) - GRFilledRect( &aPanel->m_ClipBox, aDC, pos1.x, pos1.y, pos2.x, pos2.y, - GetPenSize( ), - (m_Flags & IS_MOVED) ? color : ReturnLayerColor( LAYER_DEVICE_BACKGROUND ), - ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); - else if( m_Fill == FILLED_SHAPE && !aData ) - GRFilledRect( &aPanel->m_ClipBox, aDC, pos1.x, pos1.y, pos2.x, pos2.y, - GetPenSize( ), color, color ); - else - GRRect( &aPanel->m_ClipBox, aDC, pos1.x, pos1.y, pos2.x, pos2.y, - GetPenSize( ), color ); - - /* Set to one (1) to draw bounding box around rectangle to validate - * bounding box calculation. */ -#if 0 - EDA_Rect bBox = GetBoundingBox(); - bBox.Inflate( m_Width + 1, m_Width + 1 ); - GRRect( &aPanel->m_ClipBox, aDC, bBox.GetOrigin().x, bBox.GetOrigin().y, - bBox.GetEnd().x, bBox.GetEnd().y, 0, LIGHTMAGENTA ); -#endif -} - - -void LIB_RECTANGLE::DisplayInfo( WinEDA_DrawFrame* aFrame ) -{ - wxString msg; - - LIB_DRAW_ITEM::DisplayInfo( aFrame ); - - msg = ReturnStringFromValue( g_UserUnit, m_Width, EESCHEMA_INTERNAL_UNIT, true ); - - aFrame->AppendMsgPanel( _( "Line width" ), msg, BLUE ); -} - - -EDA_Rect LIB_RECTANGLE::GetBoundingBox() -{ - EDA_Rect rect; - - rect.SetOrigin( m_Pos.x, m_Pos.y * -1 ); - rect.SetEnd( m_End.x, m_End.y * -1 ); - rect.Inflate( m_Width / 2, m_Width / 2 ); - return rect; -} - - -/** - * Function HitTest - * tests if the given wxPoint is within the bounds of this object. - * @param aRefPoint A wxPoint to test in eeschema space - * @return true if a hit, else false - */ -bool LIB_RECTANGLE::HitTest( const wxPoint& aRefPoint ) -{ - int mindist = (m_Width ? m_Width / 2 : g_DrawDefaultLineThickness / 2) + 1; - - // Have a minimal tolerance for hit test - if( mindist < MINIMUM_SELECTION_DISTANCE ) - mindist = MINIMUM_SELECTION_DISTANCE; - - return HitTest( aRefPoint, mindist, DefaultTransformMatrix ); -} - - -/** Function HitTest - * @return true if the point aPosRef is near this object - * @param aRefPoint = a wxPoint to test - * @param aThreshold = max distance to this object (usually the half thickness - * of a line) - * @param aTransMat = the transform matrix - */ -bool LIB_RECTANGLE::HitTest( wxPoint aRefPoint, int aThreshold, - const int aTransMat[2][2] ) -{ - wxPoint actualStart = TransformCoordinate( aTransMat, m_Pos ); - wxPoint actualEnd = TransformCoordinate( aTransMat, m_End ); - - // locate lower segment - wxPoint start, end; - - start = actualStart; - end.x = actualEnd.x; - end.y = actualStart.y; - if( TestSegmentHit( aRefPoint, start, end, aThreshold ) ) - return true; - - // locate right segment - start.x = actualEnd.x; - end.y = actualEnd.y; - if( TestSegmentHit( aRefPoint, start, end, aThreshold ) ) - return true; - - // locate upper segment - start.y = actualEnd.y; - end.x = actualStart.x; - if( TestSegmentHit( aRefPoint, start, end, aThreshold ) ) - return true; - - // locate left segment - start = actualStart; - end.x = actualStart.x; - end.y = actualEnd.y; - if( TestSegmentHit( aRefPoint, start, end, aThreshold ) ) - return true; - - return false; -} - - -/**************************/ -/** class LIB_SEGMENT **/ -/**************************/ -LIB_SEGMENT::LIB_SEGMENT( LIB_COMPONENT* aParent ) : - LIB_DRAW_ITEM( COMPONENT_LINE_DRAW_TYPE, aParent ) -{ - m_Width = 0; - m_typeName = _( "Segment" ); -} - - -LIB_SEGMENT::LIB_SEGMENT( const LIB_SEGMENT& aSegment ) : - LIB_DRAW_ITEM( aSegment ) -{ - m_Pos = aSegment.m_Pos; - m_End = aSegment.m_End; - m_Width = aSegment.m_Width; -} - - -bool LIB_SEGMENT::Save( FILE* aFile ) -{ - if( fprintf( aFile, "L %d %d %d", m_Unit, m_Convert, m_Width ) ) - return false; - - return true; -} - - -bool LIB_SEGMENT::Load( char* aLine, wxString& aErrorMsg ) -{ - return true; -} - - -LIB_DRAW_ITEM* LIB_SEGMENT::DoGenCopy() -{ - LIB_SEGMENT* newitem = new LIB_SEGMENT( GetParent() ); - - newitem->m_Pos = m_Pos; - newitem->m_End = m_End; - newitem->m_Width = m_Width; - newitem->m_Unit = m_Unit; - newitem->m_Convert = m_Convert; - newitem->m_Flags = m_Flags; - - return (LIB_DRAW_ITEM*) newitem; -} - - -int LIB_SEGMENT::DoCompare( const LIB_DRAW_ITEM& aOther ) const -{ - wxASSERT( aOther.Type() == COMPONENT_LINE_DRAW_TYPE ); - - const LIB_SEGMENT* tmp = ( LIB_SEGMENT* ) &aOther; - - if( m_Pos.x != tmp->m_Pos.x ) - return m_Pos.x - tmp->m_Pos.x; - - if( m_Pos.y != tmp->m_Pos.y ) - return m_Pos.y - tmp->m_Pos.y; - - if( m_End.x != tmp->m_End.x ) - return m_End.x - tmp->m_End.x; - - if( m_End.y != tmp->m_End.y ) - return m_End.y - tmp->m_End.y; - - return 0; -} - - -void LIB_SEGMENT::DoOffset( const wxPoint& aOffset ) -{ - m_Pos += aOffset; - m_End += aOffset; -} - - -bool LIB_SEGMENT::DoTestInside( EDA_Rect& aRect ) -{ - return aRect.Inside( m_Pos.x, -m_Pos.y ) || aRect.Inside( m_End.x, -m_End.y ); -} - - -void LIB_SEGMENT::DoMove( const wxPoint& aPosition ) -{ - wxPoint offset = aPosition - m_Pos; - m_Pos += offset; - m_End += offset; -} - - -void LIB_SEGMENT::DoMirrorHorizontal( const wxPoint& aCenter ) -{ - m_Pos.x -= aCenter.x; - m_Pos.x *= -1; - m_Pos.x += aCenter.x; - m_End.x -= aCenter.x; - m_End.x *= -1; - m_End.x += aCenter.x; -} - - -void LIB_SEGMENT::DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, - const int aTransform[2][2] ) -{ - wxASSERT( aPlotter != NULL ); - - int points[4]; - wxPoint pos = TransformCoordinate( aTransform, m_Pos ) + aOffset; - wxPoint end = TransformCoordinate( aTransform, m_End ) + aOffset; - points[0] = pos.x; - points[1] = pos.y; - points[2] = end.x; - points[3] = end.y; - aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE ) ); - aPlotter->poly( 2, points, m_Fill, GetPenSize() ); -} - - -/** Function GetPenSize - * @return the size of the "pen" that be used to draw or plot this item - */ -int LIB_SEGMENT::GetPenSize() -{ - return ( m_Width == 0 ) ? g_DrawDefaultLineThickness : m_Width; -} - -void LIB_SEGMENT::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, - const wxPoint& aOffset, int aColor, int aDrawMode, - void* aData, const int aTransformMatrix[2][2] ) -{ - wxPoint pos1, pos2; - - int color = ReturnLayerColor( LAYER_DEVICE ); - - if( aColor < 0 ) // Used normal color or selected color - { - if( m_Selected & IS_SELECTED ) - color = g_ItemSelectetColor; - } - else - color = aColor; - - pos1 = TransformCoordinate( aTransformMatrix, m_Pos ) + aOffset; - pos2 = TransformCoordinate( aTransformMatrix, m_End ) + aOffset; - - GRSetDrawMode( aDC, aDrawMode ); - - GRLine( &aPanel->m_ClipBox, aDC, pos1.x, pos1.y, pos2.x, pos2.y, - GetPenSize( ), color ); - - /* Set to one (1) to draw bounding box around line segment to validate - * bounding box calculation. */ -#if 0 - EDA_Rect bBox = GetBoundingBox(); - bBox.Inflate( m_Width + 2 ); - GRRect( &aPanel->m_ClipBox, aDC, bBox.GetOrigin().x, bBox.GetOrigin().y, - bBox.GetEnd().x, bBox.GetEnd().y, 0, LIGHTMAGENTA ); -#endif -} - - -void LIB_SEGMENT::DisplayInfo( WinEDA_DrawFrame* aFrame ) -{ - wxString msg; - EDA_Rect bBox = GetBoundingBox(); - - LIB_DRAW_ITEM::DisplayInfo( aFrame ); - - msg = ReturnStringFromValue( g_UserUnit, m_Width, - EESCHEMA_INTERNAL_UNIT, true ); - - aFrame->AppendMsgPanel( _( "Line width" ), msg, BLUE ); - - msg.Printf( wxT( "(%d, %d, %d, %d)" ), bBox.GetOrigin().x, - bBox.GetOrigin().y, bBox.GetEnd().x, bBox.GetEnd().y ); - - aFrame->AppendMsgPanel( _( "Bounding box" ), msg, BROWN ); -} - - -/** - * Function HitTest - * tests if the given wxPoint is within the bounds of this object. - * @param aRefPos A wxPoint to test - * @return - true if a hit, else false - */ -bool LIB_SEGMENT::HitTest( const wxPoint& aPosRef ) -{ - int mindist = m_Width ? m_Width / 2 : g_DrawDefaultLineThickness / 2; - - // Have a minimal tolerance for hit test - if( mindist < MINIMUM_SELECTION_DISTANCE ) - mindist = MINIMUM_SELECTION_DISTANCE; - - return HitTest( aPosRef, mindist, DefaultTransformMatrix ); -} - - -/** Function HitTest - * @return true if the point aPosRef is near this object - * @param aPosRef = a wxPoint to test - * @param aThreshold = max distance to this object (usually the half - * thickness of a line) - * @param aTransMat = the transform matrix - */ -bool LIB_SEGMENT::HitTest( wxPoint aPosRef, int aThreshold, - const int aTransMat[2][2] ) -{ - wxPoint start = TransformCoordinate( aTransMat, m_Pos ); - wxPoint end = TransformCoordinate( aTransMat, m_End ); - - return TestSegmentHit( aPosRef, start, end, aThreshold ); -} - - -/***************************/ -/** class LIB_POLYLINE **/ -/***************************/ -LIB_POLYLINE::LIB_POLYLINE( LIB_COMPONENT* aParent ) : - LIB_DRAW_ITEM( COMPONENT_POLYLINE_DRAW_TYPE, aParent ) -{ - m_Fill = NO_FILL; - m_Width = 0; - m_isFillable = true; - m_typeName = _( "PolyLine" ); -} - - -LIB_POLYLINE::LIB_POLYLINE( const LIB_POLYLINE& polyline ) : - LIB_DRAW_ITEM( polyline ) -{ - m_PolyPoints = polyline.m_PolyPoints; // Vector copy - m_Width = polyline.m_Width; - m_Fill = polyline.m_Fill; -} - - -bool LIB_POLYLINE::Save( FILE* aFile ) -{ - int ccount = GetCornerCount(); - - if( fprintf( aFile, "P %d %d %d %d", ccount, m_Unit, m_Convert, m_Width ) < 0 ) - return false; - - for( unsigned i = 0; i < GetCornerCount(); i++ ) - { - if( fprintf( aFile, " %d %d", m_PolyPoints[i].x, m_PolyPoints[i].y ) < 0 ) - return false; - } - - if( fprintf( aFile, " %c\n", fill_tab[m_Fill] ) < 0 ) - return false; - - return true; -} - - -bool LIB_POLYLINE::Load( char* aLine, wxString& aErrorMsg ) -{ - char* p; - int i, ccount = 0; - wxPoint pt; - - i = sscanf( &aLine[2], "%d %d %d %d", &ccount, &m_Unit, &m_Convert, - &m_Width ); - - m_Fill = NO_FILL; - - if( i < 4 ) - { - aErrorMsg.Printf( _( "polyline only had %d parameters of the required 4" ), i ); - return false; - } - if( ccount <= 0 ) - { - aErrorMsg.Printf( _( "polyline count parameter %d is invalid" ), ccount ); - return false; - } - - p = strtok( &aLine[2], " \t\n" ); - p = strtok( NULL, " \t\n" ); - p = strtok( NULL, " \t\n" ); - p = strtok( NULL, " \t\n" ); - - for( i = 0; i < ccount; i++ ) - { - wxPoint point; - p = strtok( NULL, " \t\n" ); - if( p == NULL || sscanf( p, "%d", &pt.x ) != 1 ) - { - aErrorMsg.Printf( _( "polyline point %d X position not defined" ), i ); - return false; - } - p = strtok( NULL, " \t\n" ); - if( p == NULL || sscanf( p, "%d", &pt.y ) != 1 ) - { - aErrorMsg.Printf( _( "polyline point %d Y position not defined" ), i ); - return false; - } - AddPoint( pt ); - } - - if( ( p = strtok( NULL, " \t\n" ) ) != NULL ) - { - if( p[0] == 'F' ) - m_Fill = FILLED_SHAPE; - if( p[0] == 'f' ) - m_Fill = FILLED_WITH_BG_BODYCOLOR; - } - - return true; -} - - -LIB_DRAW_ITEM* LIB_POLYLINE::DoGenCopy() -{ - LIB_POLYLINE* newitem = new LIB_POLYLINE( GetParent() ); - - newitem->m_PolyPoints = m_PolyPoints; // Vector copy - newitem->m_Width = m_Width; - newitem->m_Unit = m_Unit; - newitem->m_Convert = m_Convert; - newitem->m_Flags = m_Flags; - newitem->m_Fill = m_Fill; - - return (LIB_DRAW_ITEM*) newitem; -} - - -int LIB_POLYLINE::DoCompare( const LIB_DRAW_ITEM& aOther ) const -{ - wxASSERT( aOther.Type() == COMPONENT_POLYLINE_DRAW_TYPE ); - - const LIB_POLYLINE* tmp = ( LIB_POLYLINE* ) &aOther; - - if( m_PolyPoints.size() != tmp->m_PolyPoints.size() ) - return m_PolyPoints.size() - tmp->m_PolyPoints.size(); - - for( size_t i = 0; i < m_PolyPoints.size(); i++ ) - { - if( m_PolyPoints[i].x != tmp->m_PolyPoints[i].x ) - return m_PolyPoints[i].x - tmp->m_PolyPoints[i].x; - if( m_PolyPoints[i].y != tmp->m_PolyPoints[i].y ) - return m_PolyPoints[i].y - tmp->m_PolyPoints[i].y; - } - - return 0; -} - - -void LIB_POLYLINE::DoOffset( const wxPoint& aOffset ) -{ - for( size_t i = 0; i < m_PolyPoints.size(); i++ ) - m_PolyPoints[i] += aOffset; -} - - -bool LIB_POLYLINE::DoTestInside( EDA_Rect& aRect ) -{ - for( size_t i = 0; i < m_PolyPoints.size(); i++ ) - { - if( aRect.Inside( m_PolyPoints[i].x, -m_PolyPoints[i].y ) ) - return true; - } - - return false; -} - - -void LIB_POLYLINE::DoMove( const wxPoint& aPosition ) -{ - DoOffset( aPosition - m_PolyPoints[0] ); -} - - -void LIB_POLYLINE::DoMirrorHorizontal( const wxPoint& aCenter ) -{ - size_t i, imax = m_PolyPoints.size(); - - for( i = 0; i < imax; i++ ) - { - m_PolyPoints[i].x -= aCenter.x; - m_PolyPoints[i].x *= -1; - m_PolyPoints[i].x += aCenter.x; - } -} - - -void LIB_POLYLINE::DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, - const int aTransform[2][2] ) -{ - wxASSERT( aPlotter != NULL ); - - size_t i; - - int* Poly = (int*) MyMalloc( sizeof(int) * 2 * GetCornerCount() ); - - if( Poly == NULL ) - return; - - for( i = 0; i < m_PolyPoints.size(); i++ ) - { - wxPoint pos = m_PolyPoints[i]; - pos = TransformCoordinate( aTransform, pos ) + aOffset; - Poly[i * 2] = pos.x; - Poly[i * 2 + 1] = pos.y; - } - - if( aFill && m_Fill == FILLED_WITH_BG_BODYCOLOR ) - { - aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); - aPlotter->poly( i, Poly, FILLED_WITH_BG_BODYCOLOR, 0 ); - } - - aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE ) ); - aPlotter->poly( i, Poly, m_Fill, GetPenSize() ); - MyFree( Poly ); -} - - -void LIB_POLYLINE::AddPoint( const wxPoint& point ) -{ - m_PolyPoints.push_back( point ); -} - - -/** Function GetPenSize - * @return the size of the "pen" that be used to draw or plot this item - */ -int LIB_POLYLINE::GetPenSize() -{ - return ( m_Width == 0 ) ? g_DrawDefaultLineThickness : m_Width; -} - - -void LIB_POLYLINE::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, - const wxPoint& aOffset, int aColor, int aDrawMode, - void* aData, const int aTransformMatrix[2][2] ) -{ - wxPoint pos1; - int color = ReturnLayerColor( LAYER_DEVICE ); - - // Buffer used to store current corners coordinates for drawings - static wxPoint* Buf_Poly_Drawings = NULL; - static unsigned Buf_Poly_Size = 0; - - if( aColor < 0 ) // Used normal color or selected color - { - if( m_Selected & IS_SELECTED ) - color = g_ItemSelectetColor; - } - else - color = aColor; - - // Set the size of the buffer od coordinates - if( Buf_Poly_Drawings == NULL ) - { - Buf_Poly_Size = m_PolyPoints.size(); - Buf_Poly_Drawings = - (wxPoint*) MyMalloc( sizeof(wxPoint) * Buf_Poly_Size ); - } - else if( Buf_Poly_Size < m_PolyPoints.size() ) - { - Buf_Poly_Size = m_PolyPoints.size(); - Buf_Poly_Drawings = - (wxPoint*) realloc( Buf_Poly_Drawings, - sizeof(wxPoint) * Buf_Poly_Size ); - - if( Buf_Poly_Drawings == NULL ) - { - DisplayError( NULL, wxT( "Cannot allocate memory to draw polylines." ) ); - } - } - - if( Buf_Poly_Drawings == NULL ) - return; - - for( unsigned ii = 0; ii < m_PolyPoints.size(); ii++ ) - { - Buf_Poly_Drawings[ii] = - TransformCoordinate( aTransformMatrix, m_PolyPoints[ii] ) + aOffset; - } - - FILL_T fill = aData ? NO_FILL : m_Fill; - if( aColor >= 0 ) - fill = NO_FILL; - - GRSetDrawMode( aDC, aDrawMode ); - - if( fill == FILLED_WITH_BG_BODYCOLOR ) - GRPoly( &aPanel->m_ClipBox, aDC, m_PolyPoints.size(), - Buf_Poly_Drawings, 1, GetPenSize( ), - (m_Flags & IS_MOVED) ? color : ReturnLayerColor( LAYER_DEVICE_BACKGROUND ), - ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); - else if( fill == FILLED_SHAPE ) - GRPoly( &aPanel->m_ClipBox, aDC, m_PolyPoints.size(), - Buf_Poly_Drawings, 1, GetPenSize( ), color, color ); - else - GRPoly( &aPanel->m_ClipBox, aDC, m_PolyPoints.size(), - Buf_Poly_Drawings, 0, GetPenSize( ), color, color ); - - /* Set to one (1) to draw bounding box around polyline to validate - * bounding box calculation. */ -#if 0 - EDA_Rect bBox = GetBoundingBox(); - bBox.Inflate( m_Width + 1, m_Width + 1 ); - GRRect( &aPanel->m_ClipBox, aDC, bBox.GetOrigin().x, bBox.GetOrigin().y, - bBox.GetEnd().x, bBox.GetEnd().y, 0, LIGHTMAGENTA ); -#endif -} - - -/** - * Function HitTest - * tests if the given wxPoint is within the bounds of this object. - * @param aRefPos A wxPoint to test - * @return true if a hit, else false - */ -bool LIB_POLYLINE::HitTest( const wxPoint& aRefPos ) -{ - int mindist = m_Width ? m_Width / 2 : g_DrawDefaultLineThickness / 2; - - // Have a minimal tolerance for hit test - if( mindist < MINIMUM_SELECTION_DISTANCE ) - mindist = MINIMUM_SELECTION_DISTANCE; - return HitTest( aRefPos, mindist, DefaultTransformMatrix ); -} - - -/** Function HitTest - * @return true if the point aPosRef is near a segment - * @param aPosRef = a wxPoint to test - * @param aThreshold = max distance to a segment - * @param aTransMat = the transform matrix - */ -bool LIB_POLYLINE::HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] ) -{ - wxPoint ref, start, end; - - for( unsigned ii = 1; ii < GetCornerCount(); ii++ ) - { - start = TransformCoordinate( aTransMat, m_PolyPoints[ii - 1] ); - end = TransformCoordinate( aTransMat, m_PolyPoints[ii] ); - - if( TestSegmentHit( aPosRef, start, end, aThreshold ) ) - return true; - } - - return false; -} - - -/** Function GetBoundingBox - * @return the boundary box for this, in library coordinates - */ -EDA_Rect LIB_POLYLINE::GetBoundingBox() -{ - EDA_Rect rect; - int xmin, xmax, ymin, ymax; - - xmin = xmax = m_PolyPoints[0].x; - ymin = ymax = m_PolyPoints[0].y; - - for( unsigned ii = 1; ii < GetCornerCount(); ii++ ) - { - xmin = MIN( xmin, m_PolyPoints[ii].x ); - xmax = MAX( xmax, m_PolyPoints[ii].x ); - ymin = MIN( ymin, m_PolyPoints[ii].y ); - ymax = MAX( ymax, m_PolyPoints[ii].y ); - } - - rect.SetOrigin( xmin, ymin * -1 ); - rect.SetEnd( xmax, ymax * -1 ); - rect.Inflate( m_Width / 2, m_Width / 2 ); - - return rect; -} - - -void LIB_POLYLINE::DisplayInfo( WinEDA_DrawFrame* aFrame ) -{ - wxString msg; - EDA_Rect bBox = GetBoundingBox(); - - LIB_DRAW_ITEM::DisplayInfo( aFrame ); - - msg = ReturnStringFromValue( g_UserUnit, m_Width, - EESCHEMA_INTERNAL_UNIT, true ); - - aFrame->AppendMsgPanel(_( "Line width" ), msg, BLUE ); - - msg.Printf( wxT( "(%d, %d, %d, %d)" ), bBox.GetOrigin().x, - bBox.GetOrigin().y, bBox.GetEnd().x, bBox.GetEnd().y ); - - aFrame->AppendMsgPanel( _( "Bounding box" ), msg, BROWN ); -} - - -/***************************/ -/** class LIB_BEZIER **/ -/***************************/ -LIB_BEZIER::LIB_BEZIER( LIB_COMPONENT* aParent ) : - LIB_DRAW_ITEM( COMPONENT_BEZIER_DRAW_TYPE, aParent ) -{ - m_Fill = NO_FILL; - m_Width = 0; - m_isFillable = true; - m_typeName = _( "Bezier" ); -} - - -LIB_BEZIER::LIB_BEZIER( const LIB_BEZIER& aBezier ) : LIB_DRAW_ITEM( aBezier ) -{ - m_PolyPoints = aBezier.m_PolyPoints; - m_BezierPoints = aBezier.m_BezierPoints; // Vector copy - m_Width = aBezier.m_Width; - m_Fill = aBezier.m_Fill; -} - - -bool LIB_BEZIER::Save( FILE* aFile ) -{ - int ccount = GetCornerCount(); - - if( fprintf( aFile, "B %d %d %d %d", - ccount, m_Unit, m_Convert, m_Width ) < 0 ) - return false; - - for( unsigned i = 0; i < GetCornerCount(); i++ ) - { - if( fprintf( aFile, " %d %d", m_BezierPoints[i].x, - m_BezierPoints[i].y ) < 0 ) - return false; - } - - if( fprintf( aFile, " %c\n", fill_tab[m_Fill] ) < 0 ) - return false; - - return true; -} - - -bool LIB_BEZIER::Load( char* aLine, wxString& aErrorMsg ) -{ - char* p; - int i, ccount = 0; - wxPoint pt; - - i = sscanf( &aLine[2], "%d %d %d %d", &ccount, &m_Unit, &m_Convert, &m_Width ); - - if( i !=4 ) - { - aErrorMsg.Printf( _( "Bezier only had %d parameters of the required 4" ), i ); - return false; - } - if( ccount <= 0 ) - { - aErrorMsg.Printf( _( "Bezier count parameter %d is invalid" ), ccount ); - return false; - } - - p = strtok( &aLine[2], " \t\n" ); - p = strtok( NULL, " \t\n" ); - p = strtok( NULL, " \t\n" ); - p = strtok( NULL, " \t\n" ); - - for( i = 0; i < ccount; i++ ) - { - wxPoint point; - p = strtok( NULL, " \t\n" ); - if( sscanf( p, "%d", &pt.x ) != 1 ) - { - aErrorMsg.Printf( _( "Bezier point %d X position not defined" ), i ); - return false; - } - p = strtok( NULL, " \t\n" ); - if( sscanf( p, "%d", &pt.y ) != 1 ) - { - aErrorMsg.Printf( _( "Bezier point %d Y position not defined" ), i ); - return false; - } - m_BezierPoints.push_back( pt ); - } - - m_Fill = NO_FILL; - - if( ( p = strtok( NULL, " \t\n" ) ) != NULL ) - { - if( p[0] == 'F' ) - m_Fill = FILLED_SHAPE; - if( p[0] == 'f' ) - m_Fill = FILLED_WITH_BG_BODYCOLOR; - } - - return true; -} - - -LIB_DRAW_ITEM* LIB_BEZIER::DoGenCopy() -{ - LIB_BEZIER* newitem = new LIB_BEZIER(GetParent()); - - newitem->m_BezierPoints = m_BezierPoints; // Vector copy - newitem->m_Width = m_Width; - newitem->m_Unit = m_Unit; - newitem->m_Convert = m_Convert; - newitem->m_Flags = m_Flags; - newitem->m_Fill = m_Fill; - return (LIB_DRAW_ITEM*) newitem; -} - - -int LIB_BEZIER::DoCompare( const LIB_DRAW_ITEM& aOther ) const -{ - wxASSERT( aOther.Type() == COMPONENT_BEZIER_DRAW_TYPE ); - - const LIB_BEZIER* tmp = ( LIB_BEZIER* ) &aOther; - - if( m_BezierPoints.size() != tmp->m_BezierPoints.size() ) - return m_BezierPoints.size() - tmp->m_BezierPoints.size(); - - for( size_t i = 0; i < m_BezierPoints.size(); i++ ) - { - if( m_BezierPoints[i].x != tmp->m_BezierPoints[i].x ) - return m_BezierPoints[i].x - tmp->m_BezierPoints[i].x; - if( m_BezierPoints[i].y != tmp->m_BezierPoints[i].y ) - return m_BezierPoints[i].y - tmp->m_BezierPoints[i].y; - } - - return 0; -} - - -void LIB_BEZIER::DoOffset( const wxPoint& aOffset ) -{ - size_t i; - - for( i = 0; i < m_BezierPoints.size(); i++ ) - m_BezierPoints[i] += aOffset; - - for( i = 0; i < m_PolyPoints.size(); i++ ) - m_PolyPoints[i] += aOffset; -} - - -bool LIB_BEZIER::DoTestInside( EDA_Rect& aRect ) -{ - for( size_t i = 0; i < m_PolyPoints.size(); i++ ) - { - if( aRect.Inside( m_PolyPoints[i].x, -m_PolyPoints[i].y ) ) - return true; - } - - return false; -} - - -void LIB_BEZIER::DoMove( const wxPoint& aPosition ) -{ - DoOffset( aPosition - m_PolyPoints[0] ); -} - - -void LIB_BEZIER::DoMirrorHorizontal( const wxPoint& aCenter ) -{ - size_t i, imax = m_PolyPoints.size(); - - for( i = 0; i < imax; i++ ) - { - m_PolyPoints[i].x -= aCenter.x; - m_PolyPoints[i].x *= -1; - m_PolyPoints[i].x += aCenter.x; - } - - imax = m_BezierPoints.size(); - for( i = 0; i < imax; i++ ) - { - m_BezierPoints[i].x -= aCenter.x; - m_BezierPoints[i].x *= -1; - m_BezierPoints[i].x += aCenter.x; - } -} - - -void LIB_BEZIER::DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, - const int aTransform[2][2] ) -{ - wxASSERT( aPlotter != NULL ); - - size_t i; - - int* Poly = (int*) MyMalloc( sizeof(int) * 2 * GetCornerCount() ); - - if( Poly == NULL ) - return; - - for( i = 0; i < m_PolyPoints.size(); i++ ) - { - wxPoint pos = m_PolyPoints[i]; - pos = TransformCoordinate( aTransform, pos ) + aOffset; - Poly[i * 2] = pos.x; - Poly[i * 2 + 1] = pos.y; - } - - if( aFill && m_Fill == FILLED_WITH_BG_BODYCOLOR ) - { - aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); - aPlotter->poly( i, Poly, FILLED_WITH_BG_BODYCOLOR, 0 ); - } - - aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE ) ); - aPlotter->poly( i, Poly, m_Fill, GetPenSize() ); - MyFree( Poly ); -} - - -/** Function GetPenSize - * @return the size of the "pen" that be used to draw or plot this item - */ -int LIB_BEZIER::GetPenSize() -{ - return ( m_Width == 0 ) ? g_DrawDefaultLineThickness : m_Width; -} - -void LIB_BEZIER::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, - const wxPoint& aOffset, int aColor, int aDrawMode, - void* aData, const int aTransformMatrix[2][2] ) -{ - wxPoint pos1; - std::vector PolyPointsTraslated; - - int color = ReturnLayerColor( LAYER_DEVICE ); - - m_PolyPoints = Bezier2Poly( m_BezierPoints[0], - m_BezierPoints[1], - m_BezierPoints[2], - m_BezierPoints[3] ); - - PolyPointsTraslated.clear(); - - for( unsigned int i = 0; i < m_PolyPoints.size() ; i++ ) - PolyPointsTraslated.push_back( - TransformCoordinate( aTransformMatrix, m_PolyPoints[i] ) + aOffset ); - - if( aColor < 0 ) // Used normal color or selected color - { - if( m_Selected & IS_SELECTED ) - color = g_ItemSelectetColor; - } - else - color = aColor; - - FILL_T fill = aData ? NO_FILL : m_Fill; - if( aColor >= 0 ) - fill = NO_FILL; - - GRSetDrawMode( aDC, aDrawMode ); - - if( fill == FILLED_WITH_BG_BODYCOLOR ) - GRPoly( &aPanel->m_ClipBox, aDC, m_PolyPoints.size(), - &PolyPointsTraslated[0], 1, GetPenSize(), - (m_Flags & IS_MOVED) ? color : ReturnLayerColor( LAYER_DEVICE_BACKGROUND ), - ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); - else if( fill == FILLED_SHAPE ) - GRPoly( &aPanel->m_ClipBox, aDC, m_PolyPoints.size(), - &PolyPointsTraslated[0], 1, GetPenSize(), color, color ); - else - GRPoly( &aPanel->m_ClipBox, aDC, m_PolyPoints.size(), - &PolyPointsTraslated[0], 0, GetPenSize(), color, color ); - - /* Set to one (1) to draw bounding box around bezier curve to validate - * bounding box calculation. */ -#if 0 - EDA_Rect bBox = GetBoundingBox(); - bBox.Inflate( m_Width + 1, m_Width + 1 ); - GRRect( &aPanel->m_ClipBox, aDC, bBox.GetOrigin().x, bBox.GetOrigin().y, - bBox.GetEnd().x, bBox.GetEnd().y, 0, LIGHTMAGENTA ); -#endif -} - - -/** - * Function HitTest - * tests if the given wxPoint is within the bounds of this object. - * @param aRefPos A wxPoint to test - * @return true if a hit, else false - */ -bool LIB_BEZIER::HitTest( const wxPoint& aRefPos ) -{ - int mindist = m_Width ? m_Width /2 : g_DrawDefaultLineThickness / 2; - // Have a minimal tolerance for hit test - if ( mindist < MINIMUM_SELECTION_DISTANCE ) - mindist = MINIMUM_SELECTION_DISTANCE; - return HitTest( aRefPos, mindist, DefaultTransformMatrix ); -} - -/** Function HitTest - * @return if the point aPosRef is near a segment - * @param aPosRef = a wxPoint to test - * @param aThreshold = max distance to a segment - * @param aTransMat = the transform matrix - */ -bool LIB_BEZIER::HitTest( wxPoint aPosRef, int aThreshold, - const int aTransMat[2][2] ) -{ - wxPoint ref, start, end; - - for( unsigned ii = 1; ii < GetCornerCount(); ii++ ) - { - start = TransformCoordinate( aTransMat, m_PolyPoints[ii - 1] ); - end = TransformCoordinate( aTransMat, m_PolyPoints[ii] ); - - if ( TestSegmentHit( aPosRef, start, end, aThreshold ) ) - return true; - } - - return false; -} - - -/** Function GetBoundingBox - * @return the boundary box for this, in library coordinates - */ -EDA_Rect LIB_BEZIER::GetBoundingBox() -{ - EDA_Rect rect; - int xmin, xmax, ymin, ymax; - - if( !GetCornerCount() ) - return rect; - - xmin = xmax = m_PolyPoints[0].x; - ymin = ymax = m_PolyPoints[0].y; - - for( unsigned ii = 1; ii < GetCornerCount(); ii++ ) - { - xmin = MIN( xmin, m_PolyPoints[ii].x ); - xmax = MAX( xmax, m_PolyPoints[ii].x ); - ymin = MIN( ymin, m_PolyPoints[ii].y ); - ymax = MAX( ymax, m_PolyPoints[ii].y ); - } - - rect.SetOrigin( xmin, ymin * -1 ); - rect.SetEnd( xmax, ymax * -1 ); - rect.Inflate( m_Width / 2, m_Width / 2 ); - - return rect; -} - - -void LIB_BEZIER::DisplayInfo( WinEDA_DrawFrame* aFrame ) -{ - wxString msg; - EDA_Rect bBox = GetBoundingBox(); - - LIB_DRAW_ITEM::DisplayInfo( aFrame ); - - msg = ReturnStringFromValue( g_UserUnit, m_Width, - EESCHEMA_INTERNAL_UNIT, true ); - - aFrame->AppendMsgPanel( _( "Line width" ), msg, BLUE ); - - msg.Printf( wxT( "(%d, %d, %d, %d)" ), bBox.GetOrigin().x, - bBox.GetOrigin().y, bBox.GetEnd().x, bBox.GetEnd().y ); - - aFrame->AppendMsgPanel( _( "Bounding box" ), msg, BROWN ); -} diff --git a/eeschema/classes_body_items.h b/eeschema/classes_body_items.h deleted file mode 100644 index cc8c1e70b7..0000000000 --- a/eeschema/classes_body_items.h +++ /dev/null @@ -1,930 +0,0 @@ -/****************************************************************/ -/* Headers for library definition and lib component definitions */ -/****************************************************************/ - -/* Definitions of graphic items used to create shapes in component libraries. - */ -#ifndef CLASSES_BODY_ITEMS_H -#define CLASSES_BODY_ITEMS_H - -#include "base_struct.h" - -#include - - -class LIB_COMPONENT; -class PLOTTER; -class LIB_DRAW_ITEM; -class LIB_PIN; - - -#define MINIMUM_SELECTION_DISTANCE 15 // Minimum selection distance in mils - - -/** - * Helper for defining a list of library draw object pointers. The Boost - * pointer containers are responsible for deleting object pointers placed - * in them. If you access a object pointer from the list, do not delete - * it directly. - */ -typedef boost::ptr_vector< LIB_DRAW_ITEM > LIB_DRAW_ITEM_LIST; - -/** - * Helper for defining a list of pin object pointers. The list does not - * use a Boost pointer class so the ojbect pointers do not accidently get - * deleted when the container is deleted. - */ -typedef std::vector< LIB_PIN* > LIB_PIN_LIST; - - -/****************************************************************************/ -/* Classes for handle the body items of a component: pins add graphic items */ -/****************************************************************************/ - - -/** - * Base class for drawable items used in library components. - * (graphic shapes, texts, fields, pins) - */ -class LIB_DRAW_ITEM : public EDA_BaseStruct -{ -public: - /** - * Unit identification for multiple parts per package. Set to 0 if the - * item is common to all units. - */ - int m_Unit; - - /** - * Shape identification for alternate body styles. Set 0 if the item - * is common to all body styles. This is commonly referred to as - * DeMorgan style and this is typically how it is used in Kicad. - */ - int m_Convert; - FILL_T m_Fill; /* NO_FILL, FILLED_SHAPE or FILLED_WITH_BG_BODYCOLOR. - * has meaning only for some items */ - wxString m_typeName; /* Name of object displayed in the message panel. */ - -public: - LIB_DRAW_ITEM* Next() - { - return (LIB_DRAW_ITEM*) Pnext; - } - - - LIB_DRAW_ITEM( KICAD_T aType, LIB_COMPONENT * aParent ); - LIB_DRAW_ITEM( const LIB_DRAW_ITEM& aItem ); - virtual ~LIB_DRAW_ITEM() { } - - /** - * Draw a body item - * - * @param aPanel - DrawPanel to use (can be null) mainly used for clipping - * purposes - * @param aDC - Device Context (can be null) - * @param aOffset - offset to draw - * @param aColor - -1 to use the normal body item color, or use this color - * if >= 0 - * @param aDrawMode - GR_OR, GR_XOR, ... - * @param aData - value or pointer used to pass others parameters, - * depending on body items. used for some items to force - * to force no fill mode ( has meaning only for items what - * can be filled ). used in printing or moving objects mode - * or to pass reference to the lib component for pins - * @param aTransformMatrix - Transform Matrix (rotation, mirror ..) - */ - virtual void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, - const wxPoint &aOffset, int aColor, int aDrawMode, - void* aData, const int aTransformMatrix[2][2] ) = 0; - - /** - * @return the size of the "pen" that be used to draw or plot this item - */ - virtual int GetPenSize() = 0; - - /** - * Write draw item object to /a aFile in "*.lib" format. - * - * @param aFile - The file to write to. - * @param aErrorMsg - Error message if write fails. - * @return - true if success writing else false. - */ - virtual bool Save( FILE* aFile ) = 0; - virtual bool Load( char* aLine, wxString& aErrorMsg ) = 0; - - LIB_COMPONENT* GetParent() - { - return (LIB_COMPONENT *)m_Parent; - } - - /** - * Tests if the given point is within the bounds of this object. - * - * Derived classes should override this function. - * - * @param aPosition - The coordinats to test. - * @return - true if a hit, else false - */ - virtual bool HitTest( const wxPoint& aPosition ) - { - return false; - } - - /** - * @param aPosRef - a wxPoint to test - * @param aThreshold - max distance to this object (usually the half - * thickness of a line) - * @param aTransMat - the transform matrix - * @return - true if the point aPosRef is near this object - */ - virtual bool HitTest( wxPoint aPosRef, int aThreshold, - const int aTransMat[2][2] ) = 0; - - /** - * @return the boundary box for this, in library coordinates - */ - virtual EDA_Rect GetBoundingBox() - { - return EDA_BaseStruct::GetBoundingBox(); - } - - virtual void DisplayInfo( WinEDA_DrawFrame* aFrame ); - - /** - * Make a copy of this draw item. - * - * Classes derived from LIB_DRAW_ITEM must implement DoGenCopy(). - * This is just a placeholder for the derived class. - * - * @return Copy of this draw item. - */ - LIB_DRAW_ITEM* GenCopy() { return DoGenCopy(); } - - /** - * Test LIB_DRAW_ITEM objects for equivalence. - * - * @param aOther - Object to test against. - * @return - True if object is identical to this object. - */ - bool operator==( const LIB_DRAW_ITEM& aOther ) const; - bool operator==( const LIB_DRAW_ITEM* aOther ) const - { - return *this == *aOther; - } - - /** - * Test if another draw item is less than this draw object. - * - * @param aOther - Draw item to compare against. - * @return - True if object is less than this object. - */ - bool operator<( const LIB_DRAW_ITEM& aOther) const; - - /** - * Set drawing object offset from the current position. - * - * @param aOffset - Cooridinates to offset position. - */ - void SetOffset( const wxPoint& aOffset ) { DoOffset( aOffset ); } - - /** - * Test if any part of the draw object is inside rectangle bounds. - * - * This is used for block selection. The real work is done by the - * DoTestInside method for each derived object type. - * - * @param aRect - Rectangle to check against. - * @return - True if object is inside rectangle. - */ - bool Inside( EDA_Rect& aRect ) { return DoTestInside( aRect ); } - - /** - * Move a draw object to a new /a aPosition. - * - * The real work is done by the DoMove method for each derived object type. - * - * @param aPosition - Position to move draw item to. - */ - void Move( const wxPoint& aPosition ) { DoMove( aPosition ); } - - /** - * Return the current draw object start position. - */ - wxPoint GetPosition() { return DoGetPosition(); } - - /** - * Mirror the draw object along the horizontal (X) axis about a point. - * - * @param aCenter - Point to mirror around. - */ - void MirrorHorizontal( const wxPoint& aCenter ) - { - DoMirrorHorizontal( aCenter ); - } - - /** - * Plot the draw item using the plot object. - * - * @param aPlotter - The plot object to plot to. - * @param aOffset - Plot offset position. - * @param aFill - Flag to indicate whether or not the object is filled. - * @param aTransform - The plot transform. - */ - void Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, - const int aTransform[2][2] ) - { - DoPlot( aPlotter, aOffset, aFill, aTransform ); - } - - /** - * Return the width of the draw item. - * - * @return Width of draw object. - */ - int GetWidth() { return DoGetWidth(); } - void SetWidth( int aWidth ) { DoSetWidth( aWidth ); } - - /** - * Check if draw object can be filled. - * - * The default setting is false. If the derived object support filling, - * set the m_isFillable member to true. - * - * @return - True if draw object can be fill. Default is false. - */ - bool IsFillable() { return m_isFillable; } - - /** - * Return the modified status of the draw object. - * - * @return - True if the draw object has been modified. - */ - bool IsModified() { return ( m_Flags & IS_CHANGED ) != 0; } - - /** - * Return the new item status of the draw object. - * - * @return - True if the draw item has been added to the parent component. - */ - bool IsNew() { return ( m_Flags & IS_NEW ) != 0; } - -protected: - virtual LIB_DRAW_ITEM* DoGenCopy() = 0; - - /** - * Provide the draw object specific comparison. - * - * This is called by the == and < operators. - * - * The sort order is as follows: - * - Component alternate part (DeMorgan) number. - * - Component part number. - * - KICAD_T enum value. - * - Result of derived classes comparison. - */ - virtual int DoCompare( const LIB_DRAW_ITEM& aOther ) const = 0; - virtual void DoOffset( const wxPoint& aOffset ) = 0; - virtual bool DoTestInside( EDA_Rect& aRect ) = 0; - virtual void DoMove( const wxPoint& aPosition ) = 0; - virtual wxPoint DoGetPosition() = 0; - virtual void DoMirrorHorizontal( const wxPoint& aCenter ) = 0; - virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, - const int aTransform[2][2] ) = 0; - virtual int DoGetWidth() = 0; - virtual void DoSetWidth( int aWidth ) = 0; - - /** Flag to indicate if draw item is fillable. Default is false. */ - bool m_isFillable; -}; - - -/**************************/ -/* Graphic Body Item: Arc */ -/**************************/ - -class LIB_ARC : public LIB_DRAW_ITEM -{ -public: - int m_Radius; - int m_t1; /* First radius angle of the arc in 0.1 degrees. */ - int m_t2; /* Second radius angle of the arc in 0.1 degrees. */ - wxPoint m_ArcStart; - wxPoint m_ArcEnd; /* Arc end position. */ - wxPoint m_Pos; /* Radius center point. */ - int m_Width; /* Line width */ - -public: - LIB_ARC(LIB_COMPONENT * aParent); - LIB_ARC( const LIB_ARC& aArc ); - ~LIB_ARC() { } - virtual wxString GetClass() const - { - return wxT( "LIB_ARC" ); - } - - - /** - * Save arc object to a FILE in "*.lib" format. - * - * @param aFile The FILE to write to. - * @return - True if success writing else false. - */ - virtual bool Save( FILE* aFile ); - virtual bool Load( char* aLine, wxString& aErrorMsg ); - - /** - * Tests if the given wxPoint is within the bounds of this object. - * - * @param aRefPos - Coordinates to test - * @return - True if a hit, else false - */ - virtual bool HitTest( const wxPoint& aRefPos ); - - /** - * @param aPosRef - a wxPoint to test - * @param aThreshold - max distance to this object (usually the half - * thickness of a line) - * @param aTransMat - the transform matrix - * @return - True if the point aPosRef is near this object - */ - virtual bool HitTest( wxPoint aPosRef, int aThreshold, - const int aTransMat[2][2] ); - - void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset, - int aColor, int aDrawMode, void* aData, - const int aTransformMatrix[2][2] ); - - virtual EDA_Rect GetBoundingBox(); - virtual void DisplayInfo( WinEDA_DrawFrame* frame ); - /** - * @return the size of the "pen" that be used to draw or plot this item - */ - virtual int GetPenSize( ); - -protected: - virtual LIB_DRAW_ITEM* DoGenCopy(); - - /** - * Provide the arc draw object specific comparison. - * - * The sort order is as follows: - * - Arc horizontal (X) position. - * - Arc vertical (Y) position. - * - Arc start angle. - * - Arc end angle. - */ - virtual int DoCompare( const LIB_DRAW_ITEM& aOther ) const; - virtual void DoOffset( const wxPoint& aOffset ); - virtual bool DoTestInside( EDA_Rect& aRect ); - virtual void DoMove( const wxPoint& aPosition ); - virtual wxPoint DoGetPosition() { return m_Pos; } - virtual void DoMirrorHorizontal( const wxPoint& aCenter ); - virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, - const int aTransform[2][2] ); - virtual int DoGetWidth() { return m_Width; } - virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; } -}; - - -/*****************************/ -/* Graphic Body Item: Circle */ -/*****************************/ -class LIB_CIRCLE : public LIB_DRAW_ITEM -{ -public: - int m_Radius; - wxPoint m_Pos; /* Position or centre (Arc and Circle) or start - * point (segments) */ - int m_Width; /* Line width */ - -public: - LIB_CIRCLE(LIB_COMPONENT * aParent); - LIB_CIRCLE( const LIB_CIRCLE& aCircle ); - ~LIB_CIRCLE() { } - virtual wxString GetClass() const - { - return wxT( "LIB_CIRCLE" ); - } - - - /** - * Write circle object to a FILE in "*.lib" format. - * - * @param aFile - The FILE to write to. - * @return - true if success writing else false. - */ - virtual bool Save( FILE* aFile ); - virtual bool Load( char* aLine, wxString& aErrorMsg ); - - /** - * Test if the given point is within the bounds of this object. - * - * @param aRefPos - A wxPoint to test - * @return bool - true if a hit, else false - */ - virtual bool HitTest( const wxPoint& aRefPos ); - - /** - * @param aPosRef - a wxPoint to test - * @param aThreshold - max distance to this object (usually the half - * thickness of a line) - * @param aTransMat - the transform matrix - * @return true if the point aPosRef is near this object - */ - virtual bool HitTest( wxPoint aPosRef, int aThreshold, - const int aTransMat[2][2] ); - - /** - * @return the size of the "pen" that be used to draw or plot this item - */ - virtual int GetPenSize( ); - - void Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint &aOffset, - int aColor, int aDrawMode, void* aData, - const int aTransformMatrix[2][2] ); - - virtual EDA_Rect GetBoundingBox(); - virtual void DisplayInfo( WinEDA_DrawFrame* aFrame ); - -protected: - virtual LIB_DRAW_ITEM* DoGenCopy(); - - /** - * Provide the circle draw object specific comparison. - * - * The sort order is as follows: - * - Circle horizontal (X) position. - * - Circle vertical (Y) position. - * - Circle radius. - */ - virtual int DoCompare( const LIB_DRAW_ITEM& aOther ) const; - - virtual void DoOffset( const wxPoint& aOffset ); - virtual bool DoTestInside( EDA_Rect& aRect ); - virtual void DoMove( const wxPoint& aPosition ); - virtual wxPoint DoGetPosition() { return m_Pos; } - virtual void DoMirrorHorizontal( const wxPoint& aCenter ); - virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, - const int aTransform[2][2] ); - virtual int DoGetWidth() { return m_Width; } - virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; } -}; - - -/*********************************************/ -/* Graphic Body Item: Text */ -/* This is only a graphic text. */ -/* Fields like Ref , value... are not Text, */ -/* they are a separate class */ -/*********************************************/ -class LIB_TEXT : public LIB_DRAW_ITEM, public EDA_TextStruct -{ -public: - LIB_TEXT(LIB_COMPONENT * aParent); - LIB_TEXT( const LIB_TEXT& aText ); - ~LIB_TEXT() { } - virtual wxString GetClass() const - { - return wxT( "LIB_TEXT" ); - } - - - /** - * Write text object out to a FILE in "*.lib" format. - * - * @param aFile - The FILE to write to. - * @return - true if success writing else false. - */ - virtual bool Save( FILE* aFile ); - virtual bool Load( char* aLine, wxString& aErrorMsg ); - - /** - * Test if the given point is within the bounds of this object. - * - * @param refPos - A wxPoint to test - * @return - true if a hit, else false - */ - virtual bool HitTest( const wxPoint& refPos ); - - /** - * @param aPosRef = a wxPoint to test, in eeschema coordinates - * @param aThreshold = max distance to a segment - * @param aTransMat = the transform matrix - * @return true if the point aPosRef is near a segment - */ - virtual bool HitTest( wxPoint aPosRef, int aThreshold, - const int aTransMat[2][2] ); - - /** - * Test if the given rectangle intersects this object. - * - * For now, an ending point must be inside this rect. - * - * @param aRect - the given EDA_Rect - * @return - true if a hit, else false - */ - virtual bool HitTest( EDA_Rect& aRect ) - { - return TextHitTest( aRect ); - } - - /** - * @return the size of the "pen" that be used to draw or plot this item - */ - virtual int GetPenSize( ); - - void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset, - int aColor, int aDrawMode, void* aData, - const int aTransformMatrix[2][2] ); - - virtual void DisplayInfo( WinEDA_DrawFrame* aFrame ); - - virtual EDA_Rect GetBoundingBox(); - -protected: - virtual LIB_DRAW_ITEM* DoGenCopy(); - - /** - * Provide the text draw object specific comparison. - * - * The sort order is as follows: - * - Text string, case insensitive compare. - * - Text horizontal (X) position. - * - Text vertical (Y) position. - * - Text width. - * - Text height. - */ - virtual int DoCompare( const LIB_DRAW_ITEM& aOther ) const; - - virtual void DoOffset( const wxPoint& aOffset ); - virtual bool DoTestInside( EDA_Rect& aRect ); - virtual void DoMove( const wxPoint& aPosition ); - virtual wxPoint DoGetPosition() { return m_Pos; } - virtual void DoMirrorHorizontal( const wxPoint& aCenter ); - virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, - const int aTransform[2][2] ); - virtual int DoGetWidth() { return m_Width; } - virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; } -}; - - -/********************************/ -/* Graphic Body Item: Rectangle */ -/********************************/ -class LIB_RECTANGLE : public LIB_DRAW_ITEM -{ -public: - wxPoint m_End; /* Rectangle end point. */ - wxPoint m_Pos; /* Rectangle start point. */ - int m_Width; /* Line width */ - bool m_isWidthLocked; /* Flag: Keep width locked */ - bool m_isHeightLocked; /* Flag: Keep height locked */ - bool m_isStartPointSelected; /* Flag: is the upper left edge selected ? */ - -public: - LIB_RECTANGLE(LIB_COMPONENT * aParent); - LIB_RECTANGLE( const LIB_RECTANGLE& aRect ); - ~LIB_RECTANGLE() { } - virtual wxString GetClass() const - { - return wxT( "LIB_RECTANGLE" ); - } - - - /** - * Write rectangle object out to a FILE in "*.lib" format. - * - * @param aFile - The FILE to write to. - * @return - true if success writing else false. - */ - virtual bool Save( FILE* aFile ); - virtual bool Load( char* aLine, wxString& aErrorMsg ); - - /** - * Test if the given point is within the bounds of this object. - * - * @param aRefPos - A wxPoint to test - * @return - true if a hit, else false - */ - virtual bool HitTest( const wxPoint& aRefPos ); - - /** - * @param aPosRef - a wxPoint to test - * @param aThreshold - max distance to this object (usually the half - * thickness of a line) - * @param aTransMat - the transform matrix - * @return true if the point aPosRef is near this object - */ - virtual bool HitTest( wxPoint aPosRef, int aThreshold, - const int aTransMat[2][2] ); - - /** - * @return the size of the "pen" that be used to draw or plot this item - */ - virtual int GetPenSize( ); - - void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset, - int aColor, int aDrawMode, void* aData, - const int aTransformMatrix[2][2] ); - - virtual EDA_Rect GetBoundingBox(); - virtual void DisplayInfo( WinEDA_DrawFrame* aFrame ); - -protected: - virtual LIB_DRAW_ITEM* DoGenCopy(); - - /** - * Provide the rectangle draw object specific comparison. - * - * The sort order is as follows: - * - Rectangle horizontal (X) start position. - * - Rectangle vertical (Y) start position. - * - Rectangle horizontal (X) end position. - * - Rectangle vertical (Y) end position. - */ - virtual int DoCompare( const LIB_DRAW_ITEM& aOther ) const; - - virtual void DoOffset( const wxPoint& aOffset ); - virtual bool DoTestInside( EDA_Rect& aRect ); - virtual void DoMove( const wxPoint& aPosition ); - virtual wxPoint DoGetPosition() { return m_Pos; } - virtual void DoMirrorHorizontal( const wxPoint& aCenter ); - virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, - const int aTransform[2][2] ); - virtual int DoGetWidth() { return m_Width; } - virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; } -}; - - -/**********************************/ -/* Graphic Body Item: single line */ -/**********************************/ -class LIB_SEGMENT : public LIB_DRAW_ITEM -{ -public: - wxPoint m_End; - wxPoint m_Pos; /* Segment start point */ - int m_Width; /* Line width */ - -public: - LIB_SEGMENT(LIB_COMPONENT * aParent); - LIB_SEGMENT( const LIB_SEGMENT& aSegment ); - ~LIB_SEGMENT() { } - virtual wxString GetClass() const - { - return wxT( "LIB_SEGMENT" ); - } - - - /** - * Writes segment object out to a FILE in "*.lib" format. - * - * @param aFile - The FILE to write to. - * @return - true if success writing else false. - */ - virtual bool Save( FILE* aFile ); - virtual bool Load( char* aLine, wxString& aErrorMsg ); - - /** - * Test if the given point is within the bounds of this object. - * - * @param aRefPos - A wxPoint to test - * @return bool - true if a hit, else false - */ - virtual bool HitTest( const wxPoint& aRefPos ); - - /** - * @param aPosRef = a wxPoint to test - * @param aThreshold = max distance to this object (usually the half - * thickness of a line) - * @param aTransMat = the transform matrix - * @return true if the point aPosRef is near this object - */ - virtual bool HitTest( wxPoint aPosRef, int aThreshold, - const int aTransMat[2][2] ); - - /** - * @return the size of the "pen" that be used to draw or plot this item - */ - virtual int GetPenSize( ); - - void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset, - int aColor, int aDrawMode, void* aData, - const int aTransformMatrix[2][2] ); - - virtual void DisplayInfo( WinEDA_DrawFrame* aFrame ); - -protected: - virtual LIB_DRAW_ITEM* DoGenCopy(); - - /** - * Provide the line segment draw object specific comparison. - * - * The sort order is as follows: - * - Line segment horizontal (X) start position. - * - Line segment vertical (Y) start position. - * - Line segment horizontal (X) end position. - * - Line segment vertical (Y) end position. - */ - virtual int DoCompare( const LIB_DRAW_ITEM& aOther ) const; - - virtual void DoOffset( const wxPoint& aOffset ); - virtual bool DoTestInside( EDA_Rect& aRect ); - virtual void DoMove( const wxPoint& aPosition ); - virtual wxPoint DoGetPosition() { return m_Pos; } - virtual void DoMirrorHorizontal( const wxPoint& aCenter ); - virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, - const int aTransform[2][2] ); - virtual int DoGetWidth() { return m_Width; } - virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; } -}; - - -/**********************************************************/ -/* Graphic Body Item: Polygon and polyline (set of lines) */ -/**********************************************************/ -class LIB_POLYLINE : public LIB_DRAW_ITEM -{ -public: - int m_Width; /* Line width */ - std::vector m_PolyPoints; // list of points (>= 2) - int m_ModifyIndex; // Index of the polyline point to modify - -public: - LIB_POLYLINE(LIB_COMPONENT * aParent); - LIB_POLYLINE( const LIB_POLYLINE& aPolyline ); - ~LIB_POLYLINE() { } - - virtual wxString GetClass() const - { - return wxT( "LIB_POLYLINE" ); - } - - - /** - * Write polyline object out to a FILE in "*.lib" format. - * - * @param aFile - The FILE to write to. - * @return - true if success writing else false. - */ - virtual bool Save( FILE* aFile ); - virtual bool Load( char* aLine, wxString& aErrorMsg ); - - void AddPoint( const wxPoint& aPoint ); - - /** - * @return the number of corners - */ - unsigned GetCornerCount() const { return m_PolyPoints.size(); } - - /** - * Test if the given point is within the bounds of this object. - * - * @param aRefPos - A wxPoint to test - * @return - true if a hit, else false - */ - virtual bool HitTest( const wxPoint& aRefPos ); - - /** - * @param aPosRef = a wxPoint to test - * @param aThreshold = max distance to a segment - * @param aTransMat = the transform matrix - * @return true if the point aPosRef is near a segment - */ - virtual bool HitTest( wxPoint aPosRef, int aThreshold, - const int aTransMat[2][2] ); - - /** - * @return the boundary box for this, in library coordinates - */ - virtual EDA_Rect GetBoundingBox(); - - /** - * @return the size of the "pen" that be used to draw or plot this item - */ - virtual int GetPenSize( ); - - void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset, - int aColor, int aDrawMode, void* aData, - const int aTransformMatrix[2][2] ); - - virtual void DisplayInfo( WinEDA_DrawFrame* aFrame ); - -protected: - virtual LIB_DRAW_ITEM* DoGenCopy(); - - /** - * Provide the ployline segment draw object specific comparison. - * - * The sort order for each polyline segment point is as follows: - * - Line segment point horizontal (X) position. - * - Line segment point vertical (Y) position. - */ - virtual int DoCompare( const LIB_DRAW_ITEM& aOther ) const; - - virtual void DoOffset( const wxPoint& aOffset ); - virtual bool DoTestInside( EDA_Rect& aRect ); - virtual void DoMove( const wxPoint& aPosition ); - virtual wxPoint DoGetPosition() { return m_PolyPoints[0]; } - virtual void DoMirrorHorizontal( const wxPoint& aCenter ); - virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, - const int aTransform[2][2] ); - virtual int DoGetWidth() { return m_Width; } - virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; } -}; - - -/**********************************************************/ -/* Graphic Body Item: Bezier Curve (set of lines) */ -/**********************************************************/ -class LIB_BEZIER : public LIB_DRAW_ITEM -{ -public: - int m_Width; /* Line width */ - std::vector m_BezierPoints; // list of parameter (3|4) - std::vector m_PolyPoints; // list of points (>= 2) - -public: - LIB_BEZIER( LIB_COMPONENT * aParent ); - LIB_BEZIER( const LIB_BEZIER& aBezier ); - ~LIB_BEZIER() { } - - virtual wxString GetClass() const - { - return wxT( "LIB_BEZIER" ); - } - - - /** - * Write bezier curve object out to a FILE in "*.lib" format. - * - * @param aFile - The FILE to write to. - * @return true if success writing else false. - */ - virtual bool Save( FILE* aFile ); - virtual bool Load( char* aLine, wxString& aErrorMsg ); - - void AddPoint( const wxPoint& aPoint ); - - /** - * @return the number of corners - */ - unsigned GetCornerCount() const { return m_PolyPoints.size(); } - - /** - * Test if the given point is within the bounds of this object. - * - * @param aRefPos - A wxPoint to test - * @return true if a hit, else false - */ - virtual bool HitTest( const wxPoint& aRefPos ); - - /** - * @param aPosRef = a wxPoint to test - * @param aThreshold = max distance to a segment - * @param aTransMat = the transform matrix - * @return true if the point aPosRef is near a segment - */ - virtual bool HitTest( wxPoint aPosRef, int aThreshold, - const int aTransMat[2][2] ); - - /** - * @return the boundary box for this, in library coordinates - */ - virtual EDA_Rect GetBoundingBox(); - - /** - * @return the size of the "pen" that be used to draw or plot this item - */ - virtual int GetPenSize( ); - - void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset, - int aColor, int aDrawMode, void* aData, - const int aTransformMatrix[2][2] ); - - virtual void DisplayInfo( WinEDA_DrawFrame* aFrame ); - -protected: - virtual LIB_DRAW_ITEM* DoGenCopy(); - - /** - * Provide the bezier curve draw object specific comparison. - * - * The sort order for each bezier curve segment point is as follows: - * - Bezier point horizontal (X) point position. - * - Bezier point vertical (Y) point position. - */ - virtual int DoCompare( const LIB_DRAW_ITEM& aOther ) const; - - virtual void DoOffset( const wxPoint& aOffset ); - virtual bool DoTestInside( EDA_Rect& aRect ); - virtual void DoMove( const wxPoint& aPosition ); - virtual wxPoint DoGetPosition() { return m_PolyPoints[0]; } - virtual void DoMirrorHorizontal( const wxPoint& aCenter ); - virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, - const int aTransform[2][2] ); - virtual int DoGetWidth() { return m_Width; } - virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; } -}; - -#endif // CLASSES_BODY_ITEMS_H diff --git a/eeschema/controle.cpp b/eeschema/controle.cpp index 6985cac397..02bdaece6f 100644 --- a/eeschema/controle.cpp +++ b/eeschema/controle.cpp @@ -14,7 +14,7 @@ #include "protos.h" #include "libeditframe.h" #include "viewlib_frame.h" -#include "classes_body_items.h" +#include "lib_draw_item.h" #include "class_pin.h" #include "class_marker_sch.h" diff --git a/eeschema/cross-probing.cpp b/eeschema/cross-probing.cpp index ca914f0d3a..b07554cda4 100644 --- a/eeschema/cross-probing.cpp +++ b/eeschema/cross-probing.cpp @@ -11,7 +11,7 @@ #include "general.h" #include "eeschema_id.h" #include "protos.h" -#include "classes_body_items.h" +#include "lib_draw_item.h" #include "class_pin.h" diff --git a/eeschema/general.h b/eeschema/general.h index 487e423c89..f09863fe9b 100644 --- a/eeschema/general.h +++ b/eeschema/general.h @@ -5,6 +5,16 @@ #ifndef _GENERAL_H_ #define _GENERAL_H_ +#include +#include + +#include "block_commande.h" + +#include "program.h" + + +class SCH_ITEM; +class SCH_SHEET; #define EESCHEMA_VERSION 2 diff --git a/eeschema/lib_arc.cpp b/eeschema/lib_arc.cpp new file mode 100644 index 0000000000..2b7c10998e --- /dev/null +++ b/eeschema/lib_arc.cpp @@ -0,0 +1,438 @@ +/*******************/ +/** class LIB_ARC **/ +/*******************/ + +#include "fctsys.h" +#include "gr_basic.h" +#include "common.h" +#include "class_drawpanel.h" +#include "plot_common.h" +#include "trigo.h" + +#include "general.h" +#include "protos.h" +#include "lib_arc.h" + + +LIB_ARC::LIB_ARC( LIB_COMPONENT* aParent ) : LIB_DRAW_ITEM( COMPONENT_ARC_DRAW_TYPE, aParent ) +{ + m_Radius = 0; + m_t1 = 0; + m_t2 = 0; + m_Width = 0; + m_Fill = NO_FILL; + m_isFillable = true; + m_typeName = _( "Arc" ); +} + + +LIB_ARC::LIB_ARC( const LIB_ARC& aArc ) : LIB_DRAW_ITEM( aArc ) +{ + m_Radius = aArc.m_Radius; + m_t1 = aArc.m_t1; + m_t2 = aArc.m_t2; + m_Width = aArc.m_Width; + m_Fill = aArc.m_Fill; + m_Pos = aArc.m_Pos; + m_ArcStart = aArc.m_ArcStart; + m_ArcEnd = aArc.m_ArcEnd; +} + + +/** + * format: + * A centre_posx centre_posy rayon start_angle end_angle unit convert + * fill('N', 'F' ou 'f') startx starty endx endy + */ +bool LIB_ARC::Save( FILE* aFile ) +{ + int x1 = m_t1; + + if( x1 > 1800 ) + x1 -= 3600; + + int x2 = m_t2; + + if( x2 > 1800 ) + x2 -= 3600; + + if( fprintf( aFile, "A %d %d %d %d %d %d %d %d %c %d %d %d %d\n", + m_Pos.x, m_Pos.y, m_Radius, x1, x2, m_Unit, m_Convert, m_Width, + fill_tab[m_Fill], m_ArcStart.x, m_ArcStart.y, m_ArcEnd.x, + m_ArcEnd.y ) < 0 ) + return false; + + return true; +} + + +bool LIB_ARC::Load( char* aLine, wxString& aErrorMsg ) +{ + int startx, starty, endx, endy, cnt; + char tmp[256]; + + cnt = sscanf( &aLine[2], "%d %d %d %d %d %d %d %d %s %d %d %d %d", + &m_Pos.x, &m_Pos.y, &m_Radius, &m_t1, &m_t2, &m_Unit, + &m_Convert, &m_Width, tmp, &startx, &starty, &endx, &endy ); + if( cnt < 8 ) + { + aErrorMsg.Printf( _( "arc only had %d parameters of the required 8" ), cnt ); + return false; + } + + if( tmp[0] == 'F' ) + m_Fill = FILLED_SHAPE; + if( tmp[0] == 'f' ) + m_Fill = FILLED_WITH_BG_BODYCOLOR; + + NORMALIZE_ANGLE( m_t1 ); + NORMALIZE_ANGLE( m_t2 ); + + // Actual Coordinates of arc ends are read from file + if( cnt >= 13 ) + { + m_ArcStart.x = startx; + m_ArcStart.y = starty; + m_ArcEnd.x = endx; + m_ArcEnd.y = endy; + } + else + { + // Actual Coordinates of arc ends are not read from file + // (old library), calculate them + m_ArcStart.x = m_Radius; + m_ArcStart.y = 0; + m_ArcEnd.x = m_Radius; + m_ArcEnd.y = 0; + RotatePoint( &m_ArcStart.x, &m_ArcStart.y, -m_t1 ); + m_ArcStart.x += m_Pos.x; + m_ArcStart.y += m_Pos.y; + RotatePoint( &m_ArcEnd.x, &m_ArcEnd.y, -m_t2 ); + m_ArcEnd.x += m_Pos.x; + m_ArcEnd.y += m_Pos.y; + } + + return true; +} + + +/** + * Function HitTest + * tests if the given wxPoint is within the bounds of this object. + * @param aRefPoint A wxPoint to test in eeschema space + * @return bool - true if a hit, else false + */ +bool LIB_ARC::HitTest( const wxPoint& aRefPoint ) +{ + int mindist = m_Width ? m_Width / 2 : g_DrawDefaultLineThickness / 2; + + // Have a minimal tolerance for hit test + if( mindist < MINIMUM_SELECTION_DISTANCE ) + mindist = MINIMUM_SELECTION_DISTANCE; + + return HitTest( aRefPoint, mindist, DefaultTransformMatrix ); +} + +/** Function HitTest + * @return true if the point aPosRef is near this object + * @param aRefPoint = a wxPoint to test + * @param aThreshold = max distance to this object (usually the half thickness + * of a line) + * @param aTransMat = the transform matrix + */ +bool LIB_ARC::HitTest( wxPoint aReferencePoint, int aThreshold, + const int aTransformationMatrix[2][2] ) +{ + + // TODO: use aTransMat to calculmates parameters + wxPoint relativePosition = aReferencePoint; + + NEGATE( relativePosition.y ); // reverse Y axis + + int distance = wxRound( EuclideanNorm( TwoPointVector(m_Pos, relativePosition) ) ); + + if( abs( distance - m_Radius ) > aThreshold ) + return false; + + // We are on the circle, ensure we are only on the arc, i.e. between + // m_ArcStart and m_ArcEnd + + wxPoint startEndVector = TwoPointVector( m_ArcStart, m_ArcEnd); + wxPoint startRelativePositionVector = TwoPointVector( m_ArcStart, relativePosition ); + + wxPoint centerStartVector = TwoPointVector( m_Pos, m_ArcStart); + wxPoint centerEndVector = TwoPointVector( m_Pos, m_ArcEnd); + wxPoint centerRelativePositionVector = TwoPointVector( m_Pos, relativePosition ); + + // Compute the cross product to check if the point is in the sector + int crossProductStart = CrossProduct( centerStartVector, centerRelativePositionVector ); + int crossProductEnd = CrossProduct( centerEndVector, centerRelativePositionVector ); + + // The cross products need to be exchanged, depending on which side the center point + // relative to the start point to end point vector lies + if( CrossProduct( startEndVector, startRelativePositionVector ) < 0 ) + { + EXCHG(crossProductStart, crossProductEnd); + } + + // When the cross products have a different sign, the point lies in sector + // also check, if the reference is near start or end point + return HitTestPoints( m_ArcStart, relativePosition, MINIMUM_SELECTION_DISTANCE ) || + HitTestPoints( m_ArcEnd, relativePosition, MINIMUM_SELECTION_DISTANCE ) || + ( crossProductStart <= 0 && crossProductEnd >= 0 ); +} + + +LIB_DRAW_ITEM* LIB_ARC::DoGenCopy() +{ + LIB_ARC* newitem = new LIB_ARC( GetParent() ); + + newitem->m_Pos = m_Pos; + newitem->m_ArcStart = m_ArcStart; + newitem->m_ArcEnd = m_ArcEnd; + newitem->m_Radius = m_Radius; + newitem->m_t1 = m_t1; + newitem->m_t2 = m_t2; + newitem->m_Width = m_Width; + newitem->m_Unit = m_Unit; + newitem->m_Convert = m_Convert; + newitem->m_Flags = m_Flags; + newitem->m_Fill = m_Fill; + + return (LIB_DRAW_ITEM*) newitem; +} + + +int LIB_ARC::DoCompare( const LIB_DRAW_ITEM& aOther ) const +{ + wxASSERT( aOther.Type() == COMPONENT_ARC_DRAW_TYPE ); + + const LIB_ARC* tmp = ( LIB_ARC* ) &aOther; + + if( m_Pos.x != tmp->m_Pos.x ) + return m_Pos.x - tmp->m_Pos.x; + + if( m_Pos.y != tmp->m_Pos.y ) + return m_Pos.y - tmp->m_Pos.y; + + if( m_t1 != tmp->m_t1 ) + return m_t1 - tmp->m_t1; + + if( m_t2 != tmp->m_t2 ) + return m_t2 - tmp->m_t2; + + return 0; +} + + +void LIB_ARC::DoOffset( const wxPoint& aOffset ) +{ + m_Pos += aOffset; + m_ArcStart += aOffset; + m_ArcEnd += aOffset; +} + + +bool LIB_ARC::DoTestInside( EDA_Rect& aRect ) +{ + return aRect.Inside( m_ArcStart.x, -m_ArcStart.y ) + || aRect.Inside( m_ArcEnd.x, -m_ArcEnd.y ); +} + + +void LIB_ARC::DoMove( const wxPoint& aPosition ) +{ + wxPoint offset = aPosition - m_Pos; + m_Pos = aPosition; + m_ArcStart += offset; + m_ArcEnd += offset; +} + + +void LIB_ARC::DoMirrorHorizontal( const wxPoint& aCenter ) +{ + m_Pos.x -= aCenter.x; + m_Pos.x *= -1; + m_Pos.x += aCenter.x; + m_ArcStart.x -= aCenter.x; + m_ArcStart.x *= -1; + m_ArcStart.x += aCenter.x; + m_ArcEnd.x -= aCenter.x; + m_ArcEnd.x *= -1; + m_ArcEnd.x += aCenter.x; + EXCHG( m_ArcStart, m_ArcEnd ); +} + + +void LIB_ARC::DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, + const int aTransform[2][2] ) +{ + wxASSERT( aPlotter != NULL ); + + int t1 = m_t1; + int t2 = m_t2; + wxPoint pos = TransformCoordinate( aTransform, m_Pos ) + aOffset; + + MapAngles( &t1, &t2, aTransform ); + + if( aFill && m_Fill == FILLED_WITH_BG_BODYCOLOR ) + { + aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); + aPlotter->arc( pos, -t2, -t1, m_Radius, FILLED_SHAPE, 0 ); + } + + aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE ) ); + aPlotter->arc( pos, -t2, -t1, m_Radius, m_Fill, GetPenSize() ); +} + + +/** Function GetPenSize + * @return the size of the "pen" that be used to draw or plot this item + */ +int LIB_ARC::GetPenSize() +{ + return ( m_Width == 0 ) ? g_DrawDefaultLineThickness : m_Width; +} + + +void LIB_ARC::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, + const wxPoint& aOffset, int aColor, int aDrawMode, + void* aData, const int aTransformMatrix[2][2] ) +{ + wxPoint pos1, pos2, posc; + + int color = ReturnLayerColor( LAYER_DEVICE ); + + if( aColor < 0 ) // Used normal color or selected color + { + if( ( m_Selected & IS_SELECTED ) ) + color = g_ItemSelectetColor; + } + else + color = aColor; + + pos1 = TransformCoordinate( aTransformMatrix, m_ArcEnd ) + aOffset; + pos2 = TransformCoordinate( aTransformMatrix, m_ArcStart ) + aOffset; + posc = TransformCoordinate( aTransformMatrix, m_Pos ) + aOffset; + int pt1 = m_t1; + int pt2 = m_t2; + bool swap = MapAngles( &pt1, &pt2, aTransformMatrix ); + if( swap ) + { + EXCHG( pos1.x, pos2.x ); + EXCHG( pos1.y, pos2.y ); + } + + GRSetDrawMode( aDC, aDrawMode ); + + FILL_T fill = aData ? NO_FILL : m_Fill; + if( aColor >= 0 ) + fill = NO_FILL; + + if( fill == FILLED_WITH_BG_BODYCOLOR ) + GRFilledArc( &aPanel->m_ClipBox, aDC, posc.x, posc.y, pt1, pt2, + m_Radius, GetPenSize( ), + (m_Flags & IS_MOVED) ? color : ReturnLayerColor( LAYER_DEVICE_BACKGROUND ), + ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); + else if( fill == FILLED_SHAPE && !aData ) + GRFilledArc( &aPanel->m_ClipBox, aDC, posc.x, posc.y, pt1, pt2, + m_Radius, color, color ); + else + { +#ifdef DRAW_ARC_WITH_ANGLE + + GRArc( &aPanel->m_ClipBox, aDC, posc.x, posc.y, pt1, pt2, + m_Radius, GetPenSize( ), color ); +#else + + GRArc1( &aPanel->m_ClipBox, aDC, pos1.x, pos1.y, pos2.x, pos2.y, + posc.x, posc.y, GetPenSize( ), color ); +#endif + } + + /* Set to one (1) to draw bounding box around arc to validate bounding box + * calculation. */ +#if 0 + EDA_Rect bBox = GetBoundingBox(); + GRRect( &aPanel->m_ClipBox, aDC, bBox.GetOrigin().x, bBox.GetOrigin().y, + bBox.GetEnd().x, bBox.GetEnd().y, 0, LIGHTMAGENTA ); +#endif +} + + +EDA_Rect LIB_ARC::GetBoundingBox() +{ + int minX, minY, maxX, maxY, angleStart, angleEnd; + EDA_Rect rect; + wxPoint nullPoint, startPos, endPos, centerPos; + wxPoint normStart = m_ArcStart - m_Pos; + wxPoint normEnd = m_ArcEnd - m_Pos; + + if( ( normStart == nullPoint ) || ( normEnd == nullPoint ) || ( m_Radius == 0 ) ) + { + wxLogDebug( wxT("Invalid arc drawing definition, center(%d, %d) \ +start(%d, %d), end(%d, %d), radius %d" ), + m_Pos.x, m_Pos.y, m_ArcStart.x, m_ArcStart.y, m_ArcEnd.x, + m_ArcEnd.y, m_Radius ); + return rect; + } + + endPos = TransformCoordinate( DefaultTransformMatrix, m_ArcEnd ); + startPos = TransformCoordinate( DefaultTransformMatrix, m_ArcStart ); + centerPos = TransformCoordinate( DefaultTransformMatrix, m_Pos ); + angleStart = m_t1; + angleEnd = m_t2; + + if( MapAngles( &angleStart, &angleEnd, DefaultTransformMatrix ) ) + { + EXCHG( endPos.x, startPos.x ); + EXCHG( endPos.y, startPos.y ); + } + + /* Start with the start and end point of the arc. */ + minX = MIN( startPos.x, endPos.x ); + minY = MIN( startPos.y, endPos.y ); + maxX = MAX( startPos.x, endPos.x ); + maxY = MAX( startPos.y, endPos.y ); + + /* Zero degrees is a special case. */ + if( angleStart == 0 ) + maxX = centerPos.x + m_Radius; + + /* Arc end angle wrapped passed 360. */ + if( angleStart > angleEnd ) + angleEnd += 3600; + + if( angleStart <= 900 && angleEnd >= 900 ) /* 90 deg */ + maxY = centerPos.y + m_Radius; + if( angleStart <= 1800 && angleEnd >= 1800 ) /* 180 deg */ + minX = centerPos.x - m_Radius; + if( angleStart <= 2700 && angleEnd >= 2700 ) /* 270 deg */ + minY = centerPos.y - m_Radius; + if( angleStart <= 3600 && angleEnd >= 3600 ) /* 0 deg */ + maxX = centerPos.x + m_Radius; + + rect.SetOrigin( minX, minY ); + rect.SetEnd( maxX, maxY ); + rect.Inflate( m_Width / 2, m_Width / 2 ); + + return rect; +} + + +void LIB_ARC::DisplayInfo( WinEDA_DrawFrame* aFrame ) +{ + wxString msg; + EDA_Rect bBox = GetBoundingBox(); + + LIB_DRAW_ITEM::DisplayInfo( aFrame ); + + msg = ReturnStringFromValue( g_UserUnit, m_Width, EESCHEMA_INTERNAL_UNIT, true ); + + aFrame->AppendMsgPanel( _( "Line width" ), msg, BLUE ); + + msg.Printf( wxT( "(%d, %d, %d, %d)" ), bBox.GetOrigin().x, + bBox.GetOrigin().y, bBox.GetEnd().x, bBox.GetEnd().y ); + + aFrame->AppendMsgPanel( _( "Bounding box" ), msg, BROWN ); +} diff --git a/eeschema/lib_arc.h b/eeschema/lib_arc.h new file mode 100644 index 0000000000..45640dfd1b --- /dev/null +++ b/eeschema/lib_arc.h @@ -0,0 +1,96 @@ +/**************************/ +/* Graphic Body Item: Arc */ +/**************************/ + +#ifndef _LIB_ARC_H_ +#define _LIB_ARC_H_ + + +#include "lib_draw_item.h" + + +class LIB_ARC : public LIB_DRAW_ITEM +{ +public: + int m_Radius; + int m_t1; /* First radius angle of the arc in 0.1 degrees. */ + int m_t2; /* Second radius angle of the arc in 0.1 degrees. */ + wxPoint m_ArcStart; + wxPoint m_ArcEnd; /* Arc end position. */ + wxPoint m_Pos; /* Radius center point. */ + int m_Width; /* Line width */ + +public: + LIB_ARC(LIB_COMPONENT * aParent); + LIB_ARC( const LIB_ARC& aArc ); + ~LIB_ARC() { } + virtual wxString GetClass() const + { + return wxT( "LIB_ARC" ); + } + + + /** + * Save arc object to a FILE in "*.lib" format. + * + * @param aFile The FILE to write to. + * @return - True if success writing else false. + */ + virtual bool Save( FILE* aFile ); + virtual bool Load( char* aLine, wxString& aErrorMsg ); + + /** + * Tests if the given wxPoint is within the bounds of this object. + * + * @param aRefPos - Coordinates to test + * @return - True if a hit, else false + */ + virtual bool HitTest( const wxPoint& aRefPos ); + + /** + * @param aPosRef - a wxPoint to test + * @param aThreshold - max distance to this object (usually the half + * thickness of a line) + * @param aTransMat - the transform matrix + * @return - True if the point aPosRef is near this object + */ + virtual bool HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] ); + + void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset, + int aColor, int aDrawMode, void* aData, + const int aTransformMatrix[2][2] ); + + virtual EDA_Rect GetBoundingBox(); + virtual void DisplayInfo( WinEDA_DrawFrame* frame ); + + /** + * @return the size of the "pen" that be used to draw or plot this item + */ + virtual int GetPenSize( ); + +protected: + virtual LIB_DRAW_ITEM* DoGenCopy(); + + /** + * Provide the arc draw object specific comparison. + * + * The sort order is as follows: + * - Arc horizontal (X) position. + * - Arc vertical (Y) position. + * - Arc start angle. + * - Arc end angle. + */ + virtual int DoCompare( const LIB_DRAW_ITEM& aOther ) const; + virtual void DoOffset( const wxPoint& aOffset ); + virtual bool DoTestInside( EDA_Rect& aRect ); + virtual void DoMove( const wxPoint& aPosition ); + virtual wxPoint DoGetPosition() { return m_Pos; } + virtual void DoMirrorHorizontal( const wxPoint& aCenter ); + virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, + const int aTransform[2][2] ); + virtual int DoGetWidth() { return m_Width; } + virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; } +}; + + +#endif // _LIB_ARC_H_ diff --git a/eeschema/lib_bezier.cpp b/eeschema/lib_bezier.cpp new file mode 100644 index 0000000000..f4c6f91d1d --- /dev/null +++ b/eeschema/lib_bezier.cpp @@ -0,0 +1,379 @@ +/**********************/ +/** class LIB_BEZIER **/ +/**********************/ + +#include "fctsys.h" +#include "gr_basic.h" +#include "common.h" +#include "class_drawpanel.h" +#include "plot_common.h" +#include "trigo.h" +#include "bezier_curves.h" + +#include "general.h" +#include "protos.h" +#include "lib_bezier.h" + + +LIB_BEZIER::LIB_BEZIER( LIB_COMPONENT* aParent ) : + LIB_DRAW_ITEM( COMPONENT_BEZIER_DRAW_TYPE, aParent ) +{ + m_Fill = NO_FILL; + m_Width = 0; + m_isFillable = true; + m_typeName = _( "Bezier" ); +} + + +LIB_BEZIER::LIB_BEZIER( const LIB_BEZIER& aBezier ) : LIB_DRAW_ITEM( aBezier ) +{ + m_PolyPoints = aBezier.m_PolyPoints; + m_BezierPoints = aBezier.m_BezierPoints; // Vector copy + m_Width = aBezier.m_Width; + m_Fill = aBezier.m_Fill; +} + + +bool LIB_BEZIER::Save( FILE* aFile ) +{ + int ccount = GetCornerCount(); + + if( fprintf( aFile, "B %d %d %d %d", ccount, m_Unit, m_Convert, m_Width ) < 0 ) + return false; + + for( unsigned i = 0; i < GetCornerCount(); i++ ) + { + if( fprintf( aFile, " %d %d", m_BezierPoints[i].x, m_BezierPoints[i].y ) < 0 ) + return false; + } + + if( fprintf( aFile, " %c\n", fill_tab[m_Fill] ) < 0 ) + return false; + + return true; +} + + +bool LIB_BEZIER::Load( char* aLine, wxString& aErrorMsg ) +{ + char* p; + int i, ccount = 0; + wxPoint pt; + + i = sscanf( &aLine[2], "%d %d %d %d", &ccount, &m_Unit, &m_Convert, &m_Width ); + + if( i !=4 ) + { + aErrorMsg.Printf( _( "Bezier only had %d parameters of the required 4" ), i ); + return false; + } + if( ccount <= 0 ) + { + aErrorMsg.Printf( _( "Bezier count parameter %d is invalid" ), ccount ); + return false; + } + + p = strtok( &aLine[2], " \t\n" ); + p = strtok( NULL, " \t\n" ); + p = strtok( NULL, " \t\n" ); + p = strtok( NULL, " \t\n" ); + + for( i = 0; i < ccount; i++ ) + { + wxPoint point; + p = strtok( NULL, " \t\n" ); + if( sscanf( p, "%d", &pt.x ) != 1 ) + { + aErrorMsg.Printf( _( "Bezier point %d X position not defined" ), i ); + return false; + } + p = strtok( NULL, " \t\n" ); + if( sscanf( p, "%d", &pt.y ) != 1 ) + { + aErrorMsg.Printf( _( "Bezier point %d Y position not defined" ), i ); + return false; + } + m_BezierPoints.push_back( pt ); + } + + m_Fill = NO_FILL; + + if( ( p = strtok( NULL, " \t\n" ) ) != NULL ) + { + if( p[0] == 'F' ) + m_Fill = FILLED_SHAPE; + if( p[0] == 'f' ) + m_Fill = FILLED_WITH_BG_BODYCOLOR; + } + + return true; +} + + +LIB_DRAW_ITEM* LIB_BEZIER::DoGenCopy() +{ + LIB_BEZIER* newitem = new LIB_BEZIER(GetParent()); + + newitem->m_BezierPoints = m_BezierPoints; // Vector copy + newitem->m_Width = m_Width; + newitem->m_Unit = m_Unit; + newitem->m_Convert = m_Convert; + newitem->m_Flags = m_Flags; + newitem->m_Fill = m_Fill; + return (LIB_DRAW_ITEM*) newitem; +} + + +int LIB_BEZIER::DoCompare( const LIB_DRAW_ITEM& aOther ) const +{ + wxASSERT( aOther.Type() == COMPONENT_BEZIER_DRAW_TYPE ); + + const LIB_BEZIER* tmp = ( LIB_BEZIER* ) &aOther; + + if( m_BezierPoints.size() != tmp->m_BezierPoints.size() ) + return m_BezierPoints.size() - tmp->m_BezierPoints.size(); + + for( size_t i = 0; i < m_BezierPoints.size(); i++ ) + { + if( m_BezierPoints[i].x != tmp->m_BezierPoints[i].x ) + return m_BezierPoints[i].x - tmp->m_BezierPoints[i].x; + if( m_BezierPoints[i].y != tmp->m_BezierPoints[i].y ) + return m_BezierPoints[i].y - tmp->m_BezierPoints[i].y; + } + + return 0; +} + + +void LIB_BEZIER::DoOffset( const wxPoint& aOffset ) +{ + size_t i; + + for( i = 0; i < m_BezierPoints.size(); i++ ) + m_BezierPoints[i] += aOffset; + + for( i = 0; i < m_PolyPoints.size(); i++ ) + m_PolyPoints[i] += aOffset; +} + + +bool LIB_BEZIER::DoTestInside( EDA_Rect& aRect ) +{ + for( size_t i = 0; i < m_PolyPoints.size(); i++ ) + { + if( aRect.Inside( m_PolyPoints[i].x, -m_PolyPoints[i].y ) ) + return true; + } + + return false; +} + + +void LIB_BEZIER::DoMove( const wxPoint& aPosition ) +{ + DoOffset( aPosition - m_PolyPoints[0] ); +} + + +void LIB_BEZIER::DoMirrorHorizontal( const wxPoint& aCenter ) +{ + size_t i, imax = m_PolyPoints.size(); + + for( i = 0; i < imax; i++ ) + { + m_PolyPoints[i].x -= aCenter.x; + m_PolyPoints[i].x *= -1; + m_PolyPoints[i].x += aCenter.x; + } + + imax = m_BezierPoints.size(); + for( i = 0; i < imax; i++ ) + { + m_BezierPoints[i].x -= aCenter.x; + m_BezierPoints[i].x *= -1; + m_BezierPoints[i].x += aCenter.x; + } +} + + +void LIB_BEZIER::DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, + const int aTransform[2][2] ) +{ + wxASSERT( aPlotter != NULL ); + + size_t i; + + int* Poly = (int*) MyMalloc( sizeof(int) * 2 * GetCornerCount() ); + + if( Poly == NULL ) + return; + + for( i = 0; i < m_PolyPoints.size(); i++ ) + { + wxPoint pos = m_PolyPoints[i]; + pos = TransformCoordinate( aTransform, pos ) + aOffset; + Poly[i * 2] = pos.x; + Poly[i * 2 + 1] = pos.y; + } + + if( aFill && m_Fill == FILLED_WITH_BG_BODYCOLOR ) + { + aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); + aPlotter->poly( i, Poly, FILLED_WITH_BG_BODYCOLOR, 0 ); + } + + aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE ) ); + aPlotter->poly( i, Poly, m_Fill, GetPenSize() ); + MyFree( Poly ); +} + + +/** Function GetPenSize + * @return the size of the "pen" that be used to draw or plot this item + */ +int LIB_BEZIER::GetPenSize() +{ + return ( m_Width == 0 ) ? g_DrawDefaultLineThickness : m_Width; +} + +void LIB_BEZIER::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, + const wxPoint& aOffset, int aColor, int aDrawMode, + void* aData, const int aTransformMatrix[2][2] ) +{ + wxPoint pos1; + std::vector PolyPointsTraslated; + + int color = ReturnLayerColor( LAYER_DEVICE ); + + m_PolyPoints = Bezier2Poly( m_BezierPoints[0], + m_BezierPoints[1], + m_BezierPoints[2], + m_BezierPoints[3] ); + + PolyPointsTraslated.clear(); + + for( unsigned int i = 0; i < m_PolyPoints.size() ; i++ ) + PolyPointsTraslated.push_back( TransformCoordinate( aTransformMatrix, + m_PolyPoints[i] ) + aOffset ); + + if( aColor < 0 ) // Used normal color or selected color + { + if( m_Selected & IS_SELECTED ) + color = g_ItemSelectetColor; + } + else + color = aColor; + + FILL_T fill = aData ? NO_FILL : m_Fill; + if( aColor >= 0 ) + fill = NO_FILL; + + GRSetDrawMode( aDC, aDrawMode ); + + if( fill == FILLED_WITH_BG_BODYCOLOR ) + GRPoly( &aPanel->m_ClipBox, aDC, m_PolyPoints.size(), + &PolyPointsTraslated[0], 1, GetPenSize(), + (m_Flags & IS_MOVED) ? color : ReturnLayerColor( LAYER_DEVICE_BACKGROUND ), + ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); + else if( fill == FILLED_SHAPE ) + GRPoly( &aPanel->m_ClipBox, aDC, m_PolyPoints.size(), + &PolyPointsTraslated[0], 1, GetPenSize(), color, color ); + else + GRPoly( &aPanel->m_ClipBox, aDC, m_PolyPoints.size(), + &PolyPointsTraslated[0], 0, GetPenSize(), color, color ); + + /* Set to one (1) to draw bounding box around bezier curve to validate + * bounding box calculation. */ +#if 0 + EDA_Rect bBox = GetBoundingBox(); + bBox.Inflate( m_Width + 1, m_Width + 1 ); + GRRect( &aPanel->m_ClipBox, aDC, bBox.GetOrigin().x, bBox.GetOrigin().y, + bBox.GetEnd().x, bBox.GetEnd().y, 0, LIGHTMAGENTA ); +#endif +} + + +/** + * Function HitTest + * tests if the given wxPoint is within the bounds of this object. + * @param aRefPos A wxPoint to test + * @return true if a hit, else false + */ +bool LIB_BEZIER::HitTest( const wxPoint& aRefPos ) +{ + int mindist = m_Width ? m_Width / 2 : g_DrawDefaultLineThickness / 2; + // Have a minimal tolerance for hit test + if ( mindist < MINIMUM_SELECTION_DISTANCE ) + mindist = MINIMUM_SELECTION_DISTANCE; + return HitTest( aRefPos, mindist, DefaultTransformMatrix ); +} + +/** Function HitTest + * @return if the point aPosRef is near a segment + * @param aPosRef = a wxPoint to test + * @param aThreshold = max distance to a segment + * @param aTransMat = the transform matrix + */ +bool LIB_BEZIER::HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] ) +{ + wxPoint ref, start, end; + + for( unsigned ii = 1; ii < GetCornerCount(); ii++ ) + { + start = TransformCoordinate( aTransMat, m_PolyPoints[ii - 1] ); + end = TransformCoordinate( aTransMat, m_PolyPoints[ii] ); + + if ( TestSegmentHit( aPosRef, start, end, aThreshold ) ) + return true; + } + + return false; +} + + +/** Function GetBoundingBox + * @return the boundary box for this, in library coordinates + */ +EDA_Rect LIB_BEZIER::GetBoundingBox() +{ + EDA_Rect rect; + int xmin, xmax, ymin, ymax; + + if( !GetCornerCount() ) + return rect; + + xmin = xmax = m_PolyPoints[0].x; + ymin = ymax = m_PolyPoints[0].y; + + for( unsigned ii = 1; ii < GetCornerCount(); ii++ ) + { + xmin = MIN( xmin, m_PolyPoints[ii].x ); + xmax = MAX( xmax, m_PolyPoints[ii].x ); + ymin = MIN( ymin, m_PolyPoints[ii].y ); + ymax = MAX( ymax, m_PolyPoints[ii].y ); + } + + rect.SetOrigin( xmin, ymin * -1 ); + rect.SetEnd( xmax, ymax * -1 ); + rect.Inflate( m_Width / 2, m_Width / 2 ); + + return rect; +} + + +void LIB_BEZIER::DisplayInfo( WinEDA_DrawFrame* aFrame ) +{ + wxString msg; + EDA_Rect bBox = GetBoundingBox(); + + LIB_DRAW_ITEM::DisplayInfo( aFrame ); + + msg = ReturnStringFromValue( g_UserUnit, m_Width, EESCHEMA_INTERNAL_UNIT, true ); + + aFrame->AppendMsgPanel( _( "Line width" ), msg, BLUE ); + + msg.Printf( wxT( "(%d, %d, %d, %d)" ), bBox.GetOrigin().x, + bBox.GetOrigin().y, bBox.GetEnd().x, bBox.GetEnd().y ); + + aFrame->AppendMsgPanel( _( "Bounding box" ), msg, BROWN ); +} diff --git a/eeschema/lib_bezier.h b/eeschema/lib_bezier.h new file mode 100644 index 0000000000..1ed46e6f93 --- /dev/null +++ b/eeschema/lib_bezier.h @@ -0,0 +1,102 @@ + +#ifndef _LIB_BEZIER_H_ +#define _LIB_BEZIER_H_ + + +#include "lib_draw_item.h" + + +/**************************************************/ +/* Graphic Body Item: Bezier Curve (set of lines) */ +/**************************************************/ +class LIB_BEZIER : public LIB_DRAW_ITEM +{ +public: + int m_Width; /* Line width */ + std::vector m_BezierPoints; // list of parameter (3|4) + std::vector m_PolyPoints; // list of points (>= 2) + +public: + LIB_BEZIER( LIB_COMPONENT * aParent ); + LIB_BEZIER( const LIB_BEZIER& aBezier ); + ~LIB_BEZIER() { } + + virtual wxString GetClass() const + { + return wxT( "LIB_BEZIER" ); + } + + + /** + * Write bezier curve object out to a FILE in "*.lib" format. + * + * @param aFile - The FILE to write to. + * @return true if success writing else false. + */ + virtual bool Save( FILE* aFile ); + virtual bool Load( char* aLine, wxString& aErrorMsg ); + + void AddPoint( const wxPoint& aPoint ); + + /** + * @return the number of corners + */ + unsigned GetCornerCount() const { return m_PolyPoints.size(); } + + /** + * Test if the given point is within the bounds of this object. + * + * @param aRefPos - A wxPoint to test + * @return true if a hit, else false + */ + virtual bool HitTest( const wxPoint& aRefPos ); + + /** + * @param aPosRef = a wxPoint to test + * @param aThreshold = max distance to a segment + * @param aTransMat = the transform matrix + * @return true if the point aPosRef is near a segment + */ + virtual bool HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] ); + + /** + * @return the boundary box for this, in library coordinates + */ + virtual EDA_Rect GetBoundingBox(); + + /** + * @return the size of the "pen" that be used to draw or plot this item + */ + virtual int GetPenSize( ); + + void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset, + int aColor, int aDrawMode, void* aData, + const int aTransformMatrix[2][2] ); + + virtual void DisplayInfo( WinEDA_DrawFrame* aFrame ); + +protected: + virtual LIB_DRAW_ITEM* DoGenCopy(); + + /** + * Provide the bezier curve draw object specific comparison. + * + * The sort order for each bezier curve segment point is as follows: + * - Bezier point horizontal (X) point position. + * - Bezier point vertical (Y) point position. + */ + virtual int DoCompare( const LIB_DRAW_ITEM& aOther ) const; + + virtual void DoOffset( const wxPoint& aOffset ); + virtual bool DoTestInside( EDA_Rect& aRect ); + virtual void DoMove( const wxPoint& aPosition ); + virtual wxPoint DoGetPosition() { return m_PolyPoints[0]; } + virtual void DoMirrorHorizontal( const wxPoint& aCenter ); + virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, + const int aTransform[2][2] ); + virtual int DoGetWidth() { return m_Width; } + virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; } +}; + + +#endif // _LIB_BEZIER_H_ diff --git a/eeschema/lib_circle.cpp b/eeschema/lib_circle.cpp new file mode 100644 index 0000000000..16b72efeaa --- /dev/null +++ b/eeschema/lib_circle.cpp @@ -0,0 +1,269 @@ +/*************************/ +/** class LIB_CIRCLE **/ +/*************************/ + +#include "fctsys.h" +#include "gr_basic.h" +#include "common.h" +#include "class_drawpanel.h" +#include "plot_common.h" +#include "trigo.h" + +#include "general.h" +#include "protos.h" +#include "lib_circle.h" + + +LIB_CIRCLE::LIB_CIRCLE( LIB_COMPONENT* aParent ) : + LIB_DRAW_ITEM( COMPONENT_CIRCLE_DRAW_TYPE, aParent ) +{ + m_Radius = 0; + m_Fill = NO_FILL; + m_isFillable = true; + m_typeName = _( "Circle" ); +} + + +LIB_CIRCLE::LIB_CIRCLE( const LIB_CIRCLE& aCircle ) : + LIB_DRAW_ITEM( aCircle ) +{ + m_Pos = aCircle.m_Pos; + m_Radius = aCircle.m_Radius; + m_Fill = aCircle.m_Fill; +} + + +bool LIB_CIRCLE::Save( FILE* aFile ) +{ + if( fprintf( aFile, "C %d %d %d %d %d %d %c\n", m_Pos.x, m_Pos.y, + m_Radius, m_Unit, m_Convert, m_Width, fill_tab[m_Fill] ) < 0 ) + return false; + + return true; +} + + +bool LIB_CIRCLE::Load( char* aLine, wxString& aErrorMsg ) +{ + char tmp[256]; + + int cnt = sscanf( &aLine[2], "%d %d %d %d %d %d %s", &m_Pos.x, &m_Pos.y, + &m_Radius, &m_Unit, &m_Convert, &m_Width, tmp ); + + if( cnt < 6 ) + { + aErrorMsg.Printf( _( "circle only had %d parameters of the required 6" ), cnt ); + return false; + } + + if( tmp[0] == 'F' ) + m_Fill = FILLED_SHAPE; + if( tmp[0] == 'f' ) + m_Fill = FILLED_WITH_BG_BODYCOLOR; + + return true; +} + + +/** + * Function HitTest + * tests if the given wxPoint is within the bounds of this object. + * @param aRefPos A wxPoint to test in eeschema space + * @return - true if a hit, else false + */ +bool LIB_CIRCLE::HitTest( const wxPoint& aPosRef ) +{ + int mindist = m_Width ? m_Width / 2 : g_DrawDefaultLineThickness / 2; + + // Have a minimal tolerance for hit test + if( mindist < MINIMUM_SELECTION_DISTANCE ) + mindist = MINIMUM_SELECTION_DISTANCE; + + return HitTest( aPosRef, mindist, DefaultTransformMatrix ); +} + + +/** Function HitTest + * @return true if the point aPosRef is near this object + * @param aPosRef = a wxPoint to test + * @param aThreshold = max distance to this object (usually the half + * thickness of a line) + * @param aTransMat = the transform matrix + */ +bool LIB_CIRCLE::HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] ) +{ + wxPoint relpos = aPosRef - TransformCoordinate( aTransMat, m_Pos ); + + int dist = wxRound( sqrt( ( (double) relpos.x * relpos.x ) + + ( (double) relpos.y * relpos.y ) ) ); + + if( abs( dist - m_Radius ) <= aThreshold ) + return true; + return false; +} + + +LIB_DRAW_ITEM* LIB_CIRCLE::DoGenCopy() +{ + LIB_CIRCLE* newitem = new LIB_CIRCLE( GetParent() ); + + newitem->m_Pos = m_Pos; + newitem->m_Radius = m_Radius; + newitem->m_Width = m_Width; + newitem->m_Unit = m_Unit; + newitem->m_Convert = m_Convert; + newitem->m_Flags = m_Flags; + newitem->m_Fill = m_Fill; + + return (LIB_DRAW_ITEM*) newitem; +} + + +int LIB_CIRCLE::DoCompare( const LIB_DRAW_ITEM& aOther ) const +{ + wxASSERT( aOther.Type() == COMPONENT_CIRCLE_DRAW_TYPE ); + + const LIB_CIRCLE* tmp = ( LIB_CIRCLE* ) &aOther; + + if( m_Pos.x != tmp->m_Pos.x ) + return m_Pos.x - tmp->m_Pos.x; + + if( m_Pos.y != tmp->m_Pos.y ) + return m_Pos.y - tmp->m_Pos.y; + + if( m_Radius != tmp->m_Radius ) + return m_Radius - tmp->m_Radius; + + return 0; +} + + +void LIB_CIRCLE::DoOffset( const wxPoint& aOffset ) +{ + m_Pos += aOffset; +} + + +bool LIB_CIRCLE::DoTestInside( EDA_Rect& aRect ) +{ + /* + * FIXME: This fails to take into acount the radius around the center + * point. + */ + return aRect.Inside( m_Pos.x, -m_Pos.y ); +} + + +void LIB_CIRCLE::DoMove( const wxPoint& aPosition ) +{ + m_Pos = aPosition; +} + + +void LIB_CIRCLE::DoMirrorHorizontal( const wxPoint& aCenter ) +{ + m_Pos.x -= aCenter.x; + m_Pos.x *= -1; + m_Pos.x += aCenter.x; +} + + +void LIB_CIRCLE::DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, + const int aTransform[2][2] ) +{ + wxPoint pos = TransformCoordinate( aTransform, m_Pos ) + aOffset; + + if( aFill && m_Fill == FILLED_WITH_BG_BODYCOLOR ) + { + aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); + aPlotter->circle( pos, m_Radius * 2, FILLED_SHAPE, 0 ); + } + + aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE ) ); + aPlotter->circle( pos, m_Radius * 2, m_Fill, GetPenSize() ); +} + + +/** Function GetPenSize + * @return the size of the "pen" that be used to draw or plot this item + */ +int LIB_CIRCLE::GetPenSize() +{ + return ( m_Width == 0 ) ? g_DrawDefaultLineThickness : m_Width; +} + + +void LIB_CIRCLE::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, + const wxPoint& aOffset, int aColor, int aDrawMode, + void* aData, const int aTransformMatrix[2][2] ) +{ + wxPoint pos1; + + int color = ReturnLayerColor( LAYER_DEVICE ); + + if( aColor < 0 ) // Used normal color or selected color + { + if( ( m_Selected & IS_SELECTED ) ) + color = g_ItemSelectetColor; + } + else + color = aColor; + + pos1 = TransformCoordinate( aTransformMatrix, m_Pos ) + aOffset; + GRSetDrawMode( aDC, aDrawMode ); + + FILL_T fill = aData ? NO_FILL : m_Fill; + if( aColor >= 0 ) + fill = NO_FILL; + + if( fill == FILLED_WITH_BG_BODYCOLOR ) + GRFilledCircle( &aPanel->m_ClipBox, aDC, pos1.x, pos1.y, + m_Radius, GetPenSize( ), + (m_Flags & IS_MOVED) ? color : ReturnLayerColor( LAYER_DEVICE_BACKGROUND ), + ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); + else if( fill == FILLED_SHAPE ) + GRFilledCircle( &aPanel->m_ClipBox, aDC, pos1.x, pos1.y, m_Radius, 0, color, color ); + else + GRCircle( &aPanel->m_ClipBox, aDC, pos1.x, pos1.y, m_Radius, GetPenSize( ), color ); + + /* Set to one (1) to draw bounding box around circle to validate bounding + * box calculation. */ +#if 0 + EDA_Rect bBox = GetBoundingBox(); + GRRect( &aPanel->m_ClipBox, aDC, bBox.GetOrigin().x, bBox.GetOrigin().y, + bBox.GetEnd().x, bBox.GetEnd().y, 0, LIGHTMAGENTA ); +#endif +} + + +EDA_Rect LIB_CIRCLE::GetBoundingBox() +{ + EDA_Rect rect; + + rect.SetOrigin( m_Pos.x - m_Radius, ( m_Pos.y - m_Radius ) * -1 ); + rect.SetEnd( m_Pos.x + m_Radius, ( m_Pos.y + m_Radius ) * -1 ); + rect.Inflate( m_Width / 2, m_Width / 2 ); + + return rect; +} + + +void LIB_CIRCLE::DisplayInfo( WinEDA_DrawFrame* aFrame ) +{ + wxString msg; + EDA_Rect bBox = GetBoundingBox(); + + LIB_DRAW_ITEM::DisplayInfo( aFrame ); + + msg = ReturnStringFromValue( g_UserUnit, m_Width, EESCHEMA_INTERNAL_UNIT, true ); + + aFrame->AppendMsgPanel( _( "Line width" ), msg, BLUE ); + + msg = ReturnStringFromValue( g_UserUnit, m_Radius, EESCHEMA_INTERNAL_UNIT, true ); + aFrame->AppendMsgPanel( _( "Radius" ), msg, RED ); + + msg.Printf( wxT( "(%d, %d, %d, %d)" ), bBox.GetOrigin().x, + bBox.GetOrigin().y, bBox.GetEnd().x, bBox.GetEnd().y ); + + aFrame->AppendMsgPanel( _( "Bounding box" ), msg, BROWN ); +} diff --git a/eeschema/lib_circle.h b/eeschema/lib_circle.h new file mode 100644 index 0000000000..89a18a3fe2 --- /dev/null +++ b/eeschema/lib_circle.h @@ -0,0 +1,92 @@ +/*****************************/ +/* Graphic Body Item: Circle */ +/*****************************/ + +#ifndef _LIB_CIRCLE_H_ +#define _LIB_CIRCLE_H_ + + +#include "lib_draw_item.h" + + +class LIB_CIRCLE : public LIB_DRAW_ITEM +{ +public: + int m_Radius; + wxPoint m_Pos; /* Position or centre (Arc and Circle) or start point (segments) */ + int m_Width; /* Line width */ + +public: + LIB_CIRCLE(LIB_COMPONENT * aParent); + LIB_CIRCLE( const LIB_CIRCLE& aCircle ); + ~LIB_CIRCLE() { } + virtual wxString GetClass() const + { + return wxT( "LIB_CIRCLE" ); + } + + + /** + * Write circle object to a FILE in "*.lib" format. + * + * @param aFile - The FILE to write to. + * @return - true if success writing else false. + */ + virtual bool Save( FILE* aFile ); + virtual bool Load( char* aLine, wxString& aErrorMsg ); + + /** + * Test if the given point is within the bounds of this object. + * + * @param aRefPos - A wxPoint to test + * @return bool - true if a hit, else false + */ + virtual bool HitTest( const wxPoint& aRefPos ); + + /** + * @param aPosRef - a wxPoint to test + * @param aThreshold - max distance to this object (usually the half + * thickness of a line) + * @param aTransMat - the transform matrix + * @return true if the point aPosRef is near this object + */ + virtual bool HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] ); + + /** + * @return the size of the "pen" that be used to draw or plot this item + */ + virtual int GetPenSize( ); + + void Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint &aOffset, + int aColor, int aDrawMode, void* aData, + const int aTransformMatrix[2][2] ); + + virtual EDA_Rect GetBoundingBox(); + virtual void DisplayInfo( WinEDA_DrawFrame* aFrame ); + +protected: + virtual LIB_DRAW_ITEM* DoGenCopy(); + + /** + * Provide the circle draw object specific comparison. + * + * The sort order is as follows: + * - Circle horizontal (X) position. + * - Circle vertical (Y) position. + * - Circle radius. + */ + virtual int DoCompare( const LIB_DRAW_ITEM& aOther ) const; + + virtual void DoOffset( const wxPoint& aOffset ); + virtual bool DoTestInside( EDA_Rect& aRect ); + virtual void DoMove( const wxPoint& aPosition ); + virtual wxPoint DoGetPosition() { return m_Pos; } + virtual void DoMirrorHorizontal( const wxPoint& aCenter ); + virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, + const int aTransform[2][2] ); + virtual int DoGetWidth() { return m_Width; } + virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; } +}; + + +#endif // _LIB_CIRCLE_H_ diff --git a/eeschema/lib_draw_item.cpp b/eeschema/lib_draw_item.cpp new file mode 100644 index 0000000000..69c9ff9276 --- /dev/null +++ b/eeschema/lib_draw_item.cpp @@ -0,0 +1,113 @@ +/*********************/ +/* lib_draw_item.cpp */ +/*********************/ + +#include "fctsys.h" +#include "gr_basic.h" +#include "common.h" +#include "class_drawpanel.h" +#include "plot_common.h" +#include "drawtxt.h" +#include "trigo.h" +#include "bezier_curves.h" +#include "confirm.h" + +#include "program.h" +#include "general.h" +#include "protos.h" +#include "lib_draw_item.h" + +const int fill_tab[3] = { 'N', 'F', 'f' }; + +//#define DRAW_ARC_WITH_ANGLE // Used to draw arcs + + +/* Base class (abstract) for components bodies items */ +LIB_DRAW_ITEM::LIB_DRAW_ITEM( KICAD_T aType, + LIB_COMPONENT* aComponent, + int aUnit, + int aConvert, + FILL_T aFillType ) : + EDA_BaseStruct( aType ) +{ + m_Unit = aUnit; + m_Convert = aConvert; + m_Fill = aFillType; + m_Parent = (EDA_BaseStruct*) aComponent; + m_typeName = _( "Undefined" ); + m_isFillable = false; +} + + +LIB_DRAW_ITEM::LIB_DRAW_ITEM( const LIB_DRAW_ITEM& aItem ) : + EDA_BaseStruct( aItem ) +{ + m_Unit = aItem.m_Unit; + m_Convert = aItem.m_Convert; + m_Fill = aItem.m_Fill; + m_Parent = aItem.m_Parent; + m_typeName = aItem.m_typeName; + m_isFillable = aItem.m_isFillable; +} + + +/** + * Update the message panel information with the drawing information. + * + * This base function is used to display the information common to the + * all library items. Call the base class from the derived class or the + * common information will not be updated in the message panel. + */ +void LIB_DRAW_ITEM::DisplayInfo( WinEDA_DrawFrame* aFrame ) +{ + wxString msg; + + aFrame->ClearMsgPanel(); + aFrame->AppendMsgPanel( _( "Type" ), m_typeName, CYAN ); + + if( m_Unit == 0 ) + msg = _( "All" ); + else + msg.Printf( wxT( "%d" ), m_Unit ); + aFrame->AppendMsgPanel( _( "Unit" ), msg, BROWN ); + + if( m_Convert == 0 ) + msg = _( "All" ); + else if( m_Convert == 1 ) + msg = _( "no" ); + else if( m_Convert == 2 ) + msg = _( "yes" ); + else + msg = wxT( "?" ); + aFrame->AppendMsgPanel( _( "Convert" ), msg, BROWN ); +} + + +bool LIB_DRAW_ITEM::operator==( const LIB_DRAW_ITEM& aOther ) const +{ + return ( ( Type() == aOther.Type() ) + && ( m_Unit == aOther.m_Unit ) + && ( m_Convert == aOther.m_Convert ) + && DoCompare( aOther ) == 0 ); +} + + +bool LIB_DRAW_ITEM::operator<( const LIB_DRAW_ITEM& aOther ) const +{ + int result = m_Convert - aOther.m_Convert; + + if( result != 0 ) + return result < 0; + + result = m_Unit - aOther.m_Unit; + + if( result != 0 ) + return result < 0; + + result = Type() - aOther.Type(); + + if( result != 0 ) + return result < 0; + + return ( DoCompare( aOther ) < 0 ); +} diff --git a/eeschema/lib_draw_item.h b/eeschema/lib_draw_item.h new file mode 100644 index 0000000000..e642a7f93c --- /dev/null +++ b/eeschema/lib_draw_item.h @@ -0,0 +1,446 @@ +/****************************************************************/ +/* Headers for library definition and lib component definitions */ +/****************************************************************/ + +/* Definitions of graphic items used to create shapes in component libraries. + */ +#ifndef _LIB_DRAW_ITEM_H_ +#define _LIB_DRAW_ITEM_H_ + +#include "base_struct.h" + +#include + + +class LIB_COMPONENT; +class PLOTTER; +class LIB_DRAW_ITEM; +class LIB_PIN; + + +extern const int fill_tab[]; + + +#define MINIMUM_SELECTION_DISTANCE 15 // Minimum selection distance in mils + + +/** + * Helper for defining a list of library draw object pointers. The Boost + * pointer containers are responsible for deleting object pointers placed + * in them. If you access a object pointer from the list, do not delete + * it directly. + */ +typedef boost::ptr_vector< LIB_DRAW_ITEM > LIB_DRAW_ITEM_LIST; + +/** + * Helper for defining a list of pin object pointers. The list does not + * use a Boost pointer class so the ojbect pointers do not accidently get + * deleted when the container is deleted. + */ +typedef std::vector< LIB_PIN* > LIB_PIN_LIST; + + +/****************************************************************************/ +/* Classes for handle the body items of a component: pins add graphic items */ +/****************************************************************************/ + + +/** + * Base class for drawable items used in library components. + * (graphic shapes, texts, fields, pins) + */ +class LIB_DRAW_ITEM : public EDA_BaseStruct +{ + wxPoint m_lastPosition; ///< Last position when moving the draw item. + +public: + /** + * Unit identification for multiple parts per package. Set to 0 if the + * item is common to all units. + */ + int m_Unit; + + /** + * Shape identification for alternate body styles. Set 0 if the item + * is common to all body styles. This is commonly referred to as + * DeMorgan style and this is typically how it is used in Kicad. + */ + int m_Convert; + + /** + * The body fill type. This has meaning only for some items. For a list of + * fill types see #FILL_T. + */ + FILL_T m_Fill; + + wxString m_typeName; ///< Name of object displayed in the message panel. + +public: + LIB_DRAW_ITEM* Next() + { + return (LIB_DRAW_ITEM*) Pnext; + } + + + LIB_DRAW_ITEM( KICAD_T aType, + LIB_COMPONENT* aComponent = NULL, + int aUnit = 0, + int aConvert = 0, + FILL_T aFillType = NO_FILL ); + + LIB_DRAW_ITEM( const LIB_DRAW_ITEM& aItem ); + + virtual ~LIB_DRAW_ITEM() { } + + /** + * Begin an editing a component library draw item in \a aEditMode at \a aStartPoint. + * + * This is used to start an editing action such as resize or move a draw object. + * It typically would be called on a left click when a draw tool is selected in + * the component library editor and one of the graphics tools is selected. It + * allows the draw item to maintian it's own internal state while it is being + * edited. Call AbortEdit() to quit the editing mode. + * + * @param aEditMode - The editing mode being performed. See base_struct.h for a list + * of mode flags. + * @param aStartPoint - The where the editing mode was started. This may or may not + * be required depending on the item being edited and the edit + * mode. + */ + virtual void BeginEdit( int aEditMode, const wxPoint aStartPoint = wxPoint( 0, 0 ) ) {} + + /** + * Continue an edit in progress at \a aNextPoint. + * + * This is used to perform the next action while editing a draw item. This would be + * called for each additional left click when the mouse is captured while the item + * is being edited. + */ + virtual void ContinueEdit( const wxPoint aNextPoint ) {} + + /** + * End an object editing action. + * + * This is used to abort an edit action in progress initiated by BeginEdit(). + */ + virtual void AbortEdit() { m_Flags = 0; } + + /** + * Draw a body item + * + * @param aPanel - DrawPanel to use (can be null) mainly used for clipping + * purposes + * @param aDC - Device Context (can be null) + * @param aOffset - offset to draw + * @param aColor - -1 to use the normal body item color, or use this color + * if >= 0 + * @param aDrawMode - GR_OR, GR_XOR, ... + * @param aData - value or pointer used to pass others parameters, + * depending on body items. used for some items to force + * to force no fill mode ( has meaning only for items what + * can be filled ). used in printing or moving objects mode + * or to pass reference to the lib component for pins + * @param aTransformMatrix - Transform Matrix (rotation, mirror ..) + */ + virtual void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, + const wxPoint &aOffset, int aColor, int aDrawMode, + void* aData, const int aTransformMatrix[2][2] ) = 0; + + /** + * @return the size of the "pen" that be used to draw or plot this item + */ + virtual int GetPenSize() = 0; + + /** + * Write draw item object to /a aFile in "*.lib" format. + * + * @param aFile - The file to write to. + * @param aErrorMsg - Error message if write fails. + * @return - true if success writing else false. + */ + virtual bool Save( FILE* aFile ) = 0; + virtual bool Load( char* aLine, wxString& aErrorMsg ) = 0; + + LIB_COMPONENT* GetParent() + { + return (LIB_COMPONENT *)m_Parent; + } + + /** + * Tests if the given point is within the bounds of this object. + * + * Derived classes should override this function. + * + * @param aPosition - The coordinats to test. + * @return - true if a hit, else false + */ + virtual bool HitTest( const wxPoint& aPosition ) + { + return false; + } + + /** + * @param aPosRef - a wxPoint to test + * @param aThreshold - max distance to this object (usually the half + * thickness of a line) + * @param aTransMat - the transform matrix + * @return - true if the point aPosRef is near this object + */ + virtual bool HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] ) = 0; + + /** + * @return the boundary box for this, in library coordinates + */ + virtual EDA_Rect GetBoundingBox() + { + return EDA_BaseStruct::GetBoundingBox(); + } + + virtual void DisplayInfo( WinEDA_DrawFrame* aFrame ); + + /** + * Make a copy of this draw item. + * + * Classes derived from LIB_DRAW_ITEM must implement DoGenCopy(). + * This is just a placeholder for the derived class. + * + * @return Copy of this draw item. + */ + LIB_DRAW_ITEM* GenCopy() { return DoGenCopy(); } + + /** + * Test LIB_DRAW_ITEM objects for equivalence. + * + * @param aOther - Object to test against. + * @return - True if object is identical to this object. + */ + bool operator==( const LIB_DRAW_ITEM& aOther ) const; + bool operator==( const LIB_DRAW_ITEM* aOther ) const + { + return *this == *aOther; + } + + /** + * Test if another draw item is less than this draw object. + * + * @param aOther - Draw item to compare against. + * @return - True if object is less than this object. + */ + bool operator<( const LIB_DRAW_ITEM& aOther) const; + + /** + * Set drawing object offset from the current position. + * + * @param aOffset - Cooridinates to offset position. + */ + void SetOffset( const wxPoint& aOffset ) { DoOffset( aOffset ); } + + /** + * Test if any part of the draw object is inside rectangle bounds. + * + * This is used for block selection. The real work is done by the + * DoTestInside method for each derived object type. + * + * @param aRect - Rectangle to check against. + * @return - True if object is inside rectangle. + */ + bool Inside( EDA_Rect& aRect ) { return DoTestInside( aRect ); } + + /** + * Move a draw object to a new /a aPosition. + * + * The real work is done by the DoMove method for each derived object type. + * + * @param aPosition - Position to move draw item to. + */ + void Move( const wxPoint& aPosition ) { DoMove( aPosition ); } + + /** + * Return the current draw object start position. + */ + wxPoint GetPosition() { return DoGetPosition(); } + + /** + * Mirror the draw object along the horizontal (X) axis about a point. + * + * @param aCenter - Point to mirror around. + */ + void MirrorHorizontal( const wxPoint& aCenter ) + { + DoMirrorHorizontal( aCenter ); + } + + /** + * Plot the draw item using the plot object. + * + * @param aPlotter - The plot object to plot to. + * @param aOffset - Plot offset position. + * @param aFill - Flag to indicate whether or not the object is filled. + * @param aTransform - The plot transform. + */ + void Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, + const int aTransform[2][2] ) + { + DoPlot( aPlotter, aOffset, aFill, aTransform ); + } + + /** + * Return the width of the draw item. + * + * @return Width of draw object. + */ + int GetWidth() { return DoGetWidth(); } + void SetWidth( int aWidth ) { DoSetWidth( aWidth ); } + + /** + * Check if draw object can be filled. + * + * The default setting is false. If the derived object support filling, + * set the m_isFillable member to true. + * + * @return - True if draw object can be fill. Default is false. + */ + bool IsFillable() { return m_isFillable; } + + /** + * Return the modified status of the draw object. + * + * @return - True if the draw object has been modified. + */ + bool IsModified() { return ( m_Flags & IS_CHANGED ) != 0; } + + /** + * Return the new item status of the draw object. + * + * @return - True if the draw item has been added to the parent component. + */ + bool IsNew() { return ( m_Flags & IS_NEW ) != 0; } + +protected: + virtual LIB_DRAW_ITEM* DoGenCopy() = 0; + + /** + * Provide the draw object specific comparison. + * + * This is called by the == and < operators. + * + * The sort order is as follows: + * - Component alternate part (DeMorgan) number. + * - Component part number. + * - KICAD_T enum value. + * - Result of derived classes comparison. + */ + virtual int DoCompare( const LIB_DRAW_ITEM& aOther ) const = 0; + virtual void DoOffset( const wxPoint& aOffset ) = 0; + virtual bool DoTestInside( EDA_Rect& aRect ) = 0; + virtual void DoMove( const wxPoint& aPosition ) = 0; + virtual wxPoint DoGetPosition() = 0; + virtual void DoMirrorHorizontal( const wxPoint& aCenter ) = 0; + virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, + const int aTransform[2][2] ) = 0; + virtual int DoGetWidth() = 0; + virtual void DoSetWidth( int aWidth ) = 0; + + /** Flag to indicate if draw item is fillable. Default is false. */ + bool m_isFillable; +}; + + +/*********************************************/ +/* Graphic Body Item: Text */ +/* This is only a graphic text. */ +/* Fields like Ref , value... are not Text, */ +/* they are a separate class */ +/*********************************************/ +class LIB_TEXT : public LIB_DRAW_ITEM, public EDA_TextStruct +{ +public: + LIB_TEXT(LIB_COMPONENT * aParent); + LIB_TEXT( const LIB_TEXT& aText ); + ~LIB_TEXT() { } + virtual wxString GetClass() const + { + return wxT( "LIB_TEXT" ); + } + + + /** + * Write text object out to a FILE in "*.lib" format. + * + * @param aFile - The FILE to write to. + * @return - true if success writing else false. + */ + virtual bool Save( FILE* aFile ); + virtual bool Load( char* aLine, wxString& aErrorMsg ); + + /** + * Test if the given point is within the bounds of this object. + * + * @param refPos - A wxPoint to test + * @return - true if a hit, else false + */ + virtual bool HitTest( const wxPoint& refPos ); + + /** + * @param aPosRef = a wxPoint to test, in eeschema coordinates + * @param aThreshold = max distance to a segment + * @param aTransMat = the transform matrix + * @return true if the point aPosRef is near a segment + */ + virtual bool HitTest( wxPoint aPosRef, int aThreshold, + const int aTransMat[2][2] ); + + /** + * Test if the given rectangle intersects this object. + * + * For now, an ending point must be inside this rect. + * + * @param aRect - the given EDA_Rect + * @return - true if a hit, else false + */ + virtual bool HitTest( EDA_Rect& aRect ) + { + return TextHitTest( aRect ); + } + + /** + * @return the size of the "pen" that be used to draw or plot this item + */ + virtual int GetPenSize( ); + + void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset, + int aColor, int aDrawMode, void* aData, + const int aTransformMatrix[2][2] ); + + virtual void DisplayInfo( WinEDA_DrawFrame* aFrame ); + + virtual EDA_Rect GetBoundingBox(); + +protected: + virtual LIB_DRAW_ITEM* DoGenCopy(); + + /** + * Provide the text draw object specific comparison. + * + * The sort order is as follows: + * - Text string, case insensitive compare. + * - Text horizontal (X) position. + * - Text vertical (Y) position. + * - Text width. + * - Text height. + */ + virtual int DoCompare( const LIB_DRAW_ITEM& aOther ) const; + + virtual void DoOffset( const wxPoint& aOffset ); + virtual bool DoTestInside( EDA_Rect& aRect ); + virtual void DoMove( const wxPoint& aPosition ); + virtual wxPoint DoGetPosition() { return m_Pos; } + virtual void DoMirrorHorizontal( const wxPoint& aCenter ); + virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, + const int aTransform[2][2] ); + virtual int DoGetWidth() { return m_Width; } + virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; } +}; + + +#endif // _LIB_DRAW_ITEM_H_ diff --git a/eeschema/lib_polyline.cpp b/eeschema/lib_polyline.cpp new file mode 100644 index 0000000000..850b0ff402 --- /dev/null +++ b/eeschema/lib_polyline.cpp @@ -0,0 +1,392 @@ +/************************/ +/** class LIB_POLYLINE **/ +/************************/ + +#include "fctsys.h" +#include "gr_basic.h" +#include "common.h" +#include "class_drawpanel.h" +#include "plot_common.h" +#include "trigo.h" +#include "bezier_curves.h" + +#include "general.h" +#include "protos.h" +#include "lib_polyline.h" + + +LIB_POLYLINE::LIB_POLYLINE( LIB_COMPONENT* aParent ) : + LIB_DRAW_ITEM( COMPONENT_POLYLINE_DRAW_TYPE, aParent ) +{ + m_Fill = NO_FILL; + m_Width = 0; + m_isFillable = true; + m_typeName = _( "PolyLine" ); +} + + +LIB_POLYLINE::LIB_POLYLINE( const LIB_POLYLINE& polyline ) : + LIB_DRAW_ITEM( polyline ) +{ + m_PolyPoints = polyline.m_PolyPoints; // Vector copy + m_Width = polyline.m_Width; + m_Fill = polyline.m_Fill; +} + + +bool LIB_POLYLINE::Save( FILE* aFile ) +{ + int ccount = GetCornerCount(); + + if( fprintf( aFile, "P %d %d %d %d", ccount, m_Unit, m_Convert, m_Width ) < 0 ) + return false; + + for( unsigned i = 0; i < GetCornerCount(); i++ ) + { + if( fprintf( aFile, " %d %d", m_PolyPoints[i].x, m_PolyPoints[i].y ) < 0 ) + return false; + } + + if( fprintf( aFile, " %c\n", fill_tab[m_Fill] ) < 0 ) + return false; + + return true; +} + + +bool LIB_POLYLINE::Load( char* aLine, wxString& aErrorMsg ) +{ + char* p; + int i, ccount = 0; + wxPoint pt; + + i = sscanf( &aLine[2], "%d %d %d %d", &ccount, &m_Unit, &m_Convert, + &m_Width ); + + m_Fill = NO_FILL; + + if( i < 4 ) + { + aErrorMsg.Printf( _( "polyline only had %d parameters of the required 4" ), i ); + return false; + } + if( ccount <= 0 ) + { + aErrorMsg.Printf( _( "polyline count parameter %d is invalid" ), ccount ); + return false; + } + + p = strtok( &aLine[2], " \t\n" ); + p = strtok( NULL, " \t\n" ); + p = strtok( NULL, " \t\n" ); + p = strtok( NULL, " \t\n" ); + + for( i = 0; i < ccount; i++ ) + { + wxPoint point; + p = strtok( NULL, " \t\n" ); + if( p == NULL || sscanf( p, "%d", &pt.x ) != 1 ) + { + aErrorMsg.Printf( _( "polyline point %d X position not defined" ), i ); + return false; + } + p = strtok( NULL, " \t\n" ); + if( p == NULL || sscanf( p, "%d", &pt.y ) != 1 ) + { + aErrorMsg.Printf( _( "polyline point %d Y position not defined" ), i ); + return false; + } + AddPoint( pt ); + } + + if( ( p = strtok( NULL, " \t\n" ) ) != NULL ) + { + if( p[0] == 'F' ) + m_Fill = FILLED_SHAPE; + if( p[0] == 'f' ) + m_Fill = FILLED_WITH_BG_BODYCOLOR; + } + + return true; +} + + +LIB_DRAW_ITEM* LIB_POLYLINE::DoGenCopy() +{ + LIB_POLYLINE* newitem = new LIB_POLYLINE( GetParent() ); + + newitem->m_PolyPoints = m_PolyPoints; // Vector copy + newitem->m_Width = m_Width; + newitem->m_Unit = m_Unit; + newitem->m_Convert = m_Convert; + newitem->m_Flags = m_Flags; + newitem->m_Fill = m_Fill; + + return (LIB_DRAW_ITEM*) newitem; +} + + +int LIB_POLYLINE::DoCompare( const LIB_DRAW_ITEM& aOther ) const +{ + wxASSERT( aOther.Type() == COMPONENT_POLYLINE_DRAW_TYPE ); + + const LIB_POLYLINE* tmp = ( LIB_POLYLINE* ) &aOther; + + if( m_PolyPoints.size() != tmp->m_PolyPoints.size() ) + return m_PolyPoints.size() - tmp->m_PolyPoints.size(); + + for( size_t i = 0; i < m_PolyPoints.size(); i++ ) + { + if( m_PolyPoints[i].x != tmp->m_PolyPoints[i].x ) + return m_PolyPoints[i].x - tmp->m_PolyPoints[i].x; + if( m_PolyPoints[i].y != tmp->m_PolyPoints[i].y ) + return m_PolyPoints[i].y - tmp->m_PolyPoints[i].y; + } + + return 0; +} + + +void LIB_POLYLINE::DoOffset( const wxPoint& aOffset ) +{ + for( size_t i = 0; i < m_PolyPoints.size(); i++ ) + m_PolyPoints[i] += aOffset; +} + + +bool LIB_POLYLINE::DoTestInside( EDA_Rect& aRect ) +{ + for( size_t i = 0; i < m_PolyPoints.size(); i++ ) + { + if( aRect.Inside( m_PolyPoints[i].x, -m_PolyPoints[i].y ) ) + return true; + } + + return false; +} + + +void LIB_POLYLINE::DoMove( const wxPoint& aPosition ) +{ + DoOffset( aPosition - m_PolyPoints[0] ); +} + + +void LIB_POLYLINE::DoMirrorHorizontal( const wxPoint& aCenter ) +{ + size_t i, imax = m_PolyPoints.size(); + + for( i = 0; i < imax; i++ ) + { + m_PolyPoints[i].x -= aCenter.x; + m_PolyPoints[i].x *= -1; + m_PolyPoints[i].x += aCenter.x; + } +} + + +void LIB_POLYLINE::DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, + const int aTransform[2][2] ) +{ + wxASSERT( aPlotter != NULL ); + + size_t i; + + int* Poly = (int*) MyMalloc( sizeof(int) * 2 * GetCornerCount() ); + + if( Poly == NULL ) + return; + + for( i = 0; i < m_PolyPoints.size(); i++ ) + { + wxPoint pos = m_PolyPoints[i]; + pos = TransformCoordinate( aTransform, pos ) + aOffset; + Poly[i * 2] = pos.x; + Poly[i * 2 + 1] = pos.y; + } + + if( aFill && m_Fill == FILLED_WITH_BG_BODYCOLOR ) + { + aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); + aPlotter->poly( i, Poly, FILLED_WITH_BG_BODYCOLOR, 0 ); + } + + aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE ) ); + aPlotter->poly( i, Poly, m_Fill, GetPenSize() ); + MyFree( Poly ); +} + + +void LIB_POLYLINE::AddPoint( const wxPoint& point ) +{ + m_PolyPoints.push_back( point ); +} + + +/** Function GetPenSize + * @return the size of the "pen" that be used to draw or plot this item + */ +int LIB_POLYLINE::GetPenSize() +{ + return ( m_Width == 0 ) ? g_DrawDefaultLineThickness : m_Width; +} + + +void LIB_POLYLINE::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, + const wxPoint& aOffset, int aColor, int aDrawMode, + void* aData, const int aTransformMatrix[2][2] ) +{ + wxPoint pos1; + int color = ReturnLayerColor( LAYER_DEVICE ); + + // Buffer used to store current corners coordinates for drawings + static wxPoint* Buf_Poly_Drawings = NULL; + static unsigned Buf_Poly_Size = 0; + + if( aColor < 0 ) // Used normal color or selected color + { + if( m_Selected & IS_SELECTED ) + color = g_ItemSelectetColor; + } + else + color = aColor; + + // Set the size of the buffer od coordinates + if( Buf_Poly_Drawings == NULL ) + { + Buf_Poly_Size = m_PolyPoints.size(); + Buf_Poly_Drawings = (wxPoint*) MyMalloc( sizeof(wxPoint) * Buf_Poly_Size ); + } + else if( Buf_Poly_Size < m_PolyPoints.size() ) + { + Buf_Poly_Size = m_PolyPoints.size(); + Buf_Poly_Drawings = (wxPoint*) realloc( Buf_Poly_Drawings, + sizeof(wxPoint) * Buf_Poly_Size ); + } + + // This should probably throw an exception instead of displaying a warning message. + if( Buf_Poly_Drawings == NULL ) + { + wxLogWarning( wxT( "Cannot allocate memory to draw polylines." ) ); + return; + } + + for( unsigned ii = 0; ii < m_PolyPoints.size(); ii++ ) + { + Buf_Poly_Drawings[ii] = TransformCoordinate( aTransformMatrix, + m_PolyPoints[ii] ) + aOffset; + } + + FILL_T fill = aData ? NO_FILL : m_Fill; + if( aColor >= 0 ) + fill = NO_FILL; + + GRSetDrawMode( aDC, aDrawMode ); + + if( fill == FILLED_WITH_BG_BODYCOLOR ) + GRPoly( &aPanel->m_ClipBox, aDC, m_PolyPoints.size(), + Buf_Poly_Drawings, 1, GetPenSize( ), + (m_Flags & IS_MOVED) ? color : ReturnLayerColor( LAYER_DEVICE_BACKGROUND ), + ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); + else if( fill == FILLED_SHAPE ) + GRPoly( &aPanel->m_ClipBox, aDC, m_PolyPoints.size(), + Buf_Poly_Drawings, 1, GetPenSize( ), color, color ); + else + GRPoly( &aPanel->m_ClipBox, aDC, m_PolyPoints.size(), + Buf_Poly_Drawings, 0, GetPenSize( ), color, color ); + + /* Set to one (1) to draw bounding box around polyline to validate + * bounding box calculation. */ +#if 0 + EDA_Rect bBox = GetBoundingBox(); + bBox.Inflate( m_Width + 1, m_Width + 1 ); + GRRect( &aPanel->m_ClipBox, aDC, bBox.GetOrigin().x, bBox.GetOrigin().y, + bBox.GetEnd().x, bBox.GetEnd().y, 0, LIGHTMAGENTA ); +#endif +} + + +/** + * Function HitTest + * tests if the given wxPoint is within the bounds of this object. + * @param aRefPos A wxPoint to test + * @return true if a hit, else false + */ +bool LIB_POLYLINE::HitTest( const wxPoint& aRefPos ) +{ + int mindist = m_Width ? m_Width / 2 : g_DrawDefaultLineThickness / 2; + + // Have a minimal tolerance for hit test + if( mindist < MINIMUM_SELECTION_DISTANCE ) + mindist = MINIMUM_SELECTION_DISTANCE; + return HitTest( aRefPos, mindist, DefaultTransformMatrix ); +} + + +/** Function HitTest + * @return true if the point aPosRef is near a segment + * @param aPosRef = a wxPoint to test + * @param aThreshold = max distance to a segment + * @param aTransMat = the transform matrix + */ +bool LIB_POLYLINE::HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] ) +{ + wxPoint ref, start, end; + + for( unsigned ii = 1; ii < GetCornerCount(); ii++ ) + { + start = TransformCoordinate( aTransMat, m_PolyPoints[ii - 1] ); + end = TransformCoordinate( aTransMat, m_PolyPoints[ii] ); + + if( TestSegmentHit( aPosRef, start, end, aThreshold ) ) + return true; + } + + return false; +} + + +/** Function GetBoundingBox + * @return the boundary box for this, in library coordinates + */ +EDA_Rect LIB_POLYLINE::GetBoundingBox() +{ + EDA_Rect rect; + int xmin, xmax, ymin, ymax; + + xmin = xmax = m_PolyPoints[0].x; + ymin = ymax = m_PolyPoints[0].y; + + for( unsigned ii = 1; ii < GetCornerCount(); ii++ ) + { + xmin = MIN( xmin, m_PolyPoints[ii].x ); + xmax = MAX( xmax, m_PolyPoints[ii].x ); + ymin = MIN( ymin, m_PolyPoints[ii].y ); + ymax = MAX( ymax, m_PolyPoints[ii].y ); + } + + rect.SetOrigin( xmin, ymin * -1 ); + rect.SetEnd( xmax, ymax * -1 ); + rect.Inflate( m_Width / 2, m_Width / 2 ); + + return rect; +} + + +void LIB_POLYLINE::DisplayInfo( WinEDA_DrawFrame* aFrame ) +{ + wxString msg; + EDA_Rect bBox = GetBoundingBox(); + + LIB_DRAW_ITEM::DisplayInfo( aFrame ); + + msg = ReturnStringFromValue( g_UserUnit, m_Width, + EESCHEMA_INTERNAL_UNIT, true ); + + aFrame->AppendMsgPanel(_( "Line width" ), msg, BLUE ); + + msg.Printf( wxT( "(%d, %d, %d, %d)" ), bBox.GetOrigin().x, + bBox.GetOrigin().y, bBox.GetEnd().x, bBox.GetEnd().y ); + + aFrame->AppendMsgPanel( _( "Bounding box" ), msg, BROWN ); +} diff --git a/eeschema/lib_polyline.h b/eeschema/lib_polyline.h new file mode 100644 index 0000000000..898d803ed0 --- /dev/null +++ b/eeschema/lib_polyline.h @@ -0,0 +1,103 @@ +/**********************************************************/ +/* Graphic Body Item: Polygon and polyline (set of lines) */ +/**********************************************************/ + +#ifndef _LIB_POLYLINE_H_ +#define _LIB_POLYLINE_H_ + + +#include "lib_draw_item.h" + + +class LIB_POLYLINE : public LIB_DRAW_ITEM +{ +public: + int m_Width; /* Line width */ + std::vector m_PolyPoints; // list of points (>= 2) + int m_ModifyIndex; // Index of the polyline point to modify + +public: + LIB_POLYLINE(LIB_COMPONENT * aParent); + LIB_POLYLINE( const LIB_POLYLINE& aPolyline ); + ~LIB_POLYLINE() { } + + virtual wxString GetClass() const + { + return wxT( "LIB_POLYLINE" ); + } + + + /** + * Write polyline object out to a FILE in "*.lib" format. + * + * @param aFile - The FILE to write to. + * @return - true if success writing else false. + */ + virtual bool Save( FILE* aFile ); + virtual bool Load( char* aLine, wxString& aErrorMsg ); + + void AddPoint( const wxPoint& aPoint ); + + /** + * @return the number of corners + */ + unsigned GetCornerCount() const { return m_PolyPoints.size(); } + + /** + * Test if the given point is within the bounds of this object. + * + * @param aRefPos - A wxPoint to test + * @return - true if a hit, else false + */ + virtual bool HitTest( const wxPoint& aRefPos ); + + /** + * @param aPosRef = a wxPoint to test + * @param aThreshold = max distance to a segment + * @param aTransMat = the transform matrix + * @return true if the point aPosRef is near a segment + */ + virtual bool HitTest( wxPoint aPosRef, int aThreshold, + const int aTransMat[2][2] ); + + /** + * @return the boundary box for this, in library coordinates + */ + virtual EDA_Rect GetBoundingBox(); + + /** + * @return the size of the "pen" that be used to draw or plot this item + */ + virtual int GetPenSize( ); + + void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset, + int aColor, int aDrawMode, void* aData, + const int aTransformMatrix[2][2] ); + + virtual void DisplayInfo( WinEDA_DrawFrame* aFrame ); + +protected: + virtual LIB_DRAW_ITEM* DoGenCopy(); + + /** + * Provide the ployline segment draw object specific comparison. + * + * The sort order for each polyline segment point is as follows: + * - Line segment point horizontal (X) position. + * - Line segment point vertical (Y) position. + */ + virtual int DoCompare( const LIB_DRAW_ITEM& aOther ) const; + + virtual void DoOffset( const wxPoint& aOffset ); + virtual bool DoTestInside( EDA_Rect& aRect ); + virtual void DoMove( const wxPoint& aPosition ); + virtual wxPoint DoGetPosition() { return m_PolyPoints[0]; } + virtual void DoMirrorHorizontal( const wxPoint& aCenter ); + virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, + const int aTransform[2][2] ); + virtual int DoGetWidth() { return m_Width; } + virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; } +}; + + +#endif // _LIB_POLYLIN_H_ diff --git a/eeschema/lib_rectangle.cpp b/eeschema/lib_rectangle.cpp new file mode 100644 index 0000000000..58cb6ee4d1 --- /dev/null +++ b/eeschema/lib_rectangle.cpp @@ -0,0 +1,298 @@ +/*************************/ +/** class LIB_RECTANGLE **/ +/*************************/ + +#include "fctsys.h" +#include "gr_basic.h" +#include "common.h" +#include "class_drawpanel.h" +#include "plot_common.h" +#include "trigo.h" + +#include "general.h" +#include "protos.h" +#include "lib_rectangle.h" + + +LIB_RECTANGLE::LIB_RECTANGLE( LIB_COMPONENT* aParent ) : + LIB_DRAW_ITEM( COMPONENT_RECT_DRAW_TYPE, aParent ) +{ + m_Width = 0; + m_Fill = NO_FILL; + m_isFillable = true; + m_typeName = _( "Rectangle" ); + m_isHeightLocked = false; + m_isWidthLocked = false; + m_isStartPointSelected = false; +} + + +LIB_RECTANGLE::LIB_RECTANGLE( const LIB_RECTANGLE& aRect ) : + LIB_DRAW_ITEM( aRect ) +{ + m_Pos = aRect.m_Pos; + m_End = aRect.m_End; + m_Width = aRect.m_Width; + m_Fill = aRect.m_Fill; +} + + +bool LIB_RECTANGLE::Save( FILE* aFile ) +{ + if( fprintf( aFile, "S %d %d %d %d %d %d %d %c\n", m_Pos.x, m_Pos.y, + m_End.x, m_End.y, m_Unit, m_Convert, m_Width, fill_tab[m_Fill] ) < 0 ) + return false; + + return true; +} + + +bool LIB_RECTANGLE::Load( char* aLine, wxString& aErrorMsg ) +{ + int cnt; + char tmp[256]; + + cnt = sscanf( &aLine[2], "%d %d %d %d %d %d %d %s", &m_Pos.x, &m_Pos.y, + &m_End.x, &m_End.y, &m_Unit, &m_Convert, &m_Width, tmp ); + + if( cnt < 7 ) + { + aErrorMsg.Printf( _( "rectangle only had %d parameters of the required 7" ), cnt ); + return false; + } + + if( tmp[0] == 'F' ) + m_Fill = FILLED_SHAPE; + if( tmp[0] == 'f' ) + m_Fill = FILLED_WITH_BG_BODYCOLOR; + + return true; +} + + +LIB_DRAW_ITEM* LIB_RECTANGLE::DoGenCopy() +{ + LIB_RECTANGLE* newitem = new LIB_RECTANGLE( GetParent() ); + + newitem->m_Pos = m_Pos; + newitem->m_End = m_End; + newitem->m_Width = m_Width; + newitem->m_Unit = m_Unit; + newitem->m_Convert = m_Convert; + newitem->m_Flags = m_Flags; + newitem->m_Fill = m_Fill; + + return (LIB_DRAW_ITEM*) newitem; +} + + +int LIB_RECTANGLE::DoCompare( const LIB_DRAW_ITEM& aOther ) const +{ + wxASSERT( aOther.Type() == COMPONENT_RECT_DRAW_TYPE ); + + const LIB_RECTANGLE* tmp = ( LIB_RECTANGLE* ) &aOther; + + if( m_Pos.x != tmp->m_Pos.x ) + return m_Pos.x - tmp->m_Pos.x; + + if( m_Pos.y != tmp->m_Pos.y ) + return m_Pos.y - tmp->m_Pos.y; + + if( m_End.x != tmp->m_End.x ) + return m_End.x - tmp->m_End.x; + + if( m_End.y != tmp->m_End.y ) + return m_End.y - tmp->m_End.y; + + return 0; +} + + +void LIB_RECTANGLE::DoOffset( const wxPoint& aOffset ) +{ + m_Pos += aOffset; + m_End += aOffset; +} + + +bool LIB_RECTANGLE::DoTestInside( EDA_Rect& aRect ) +{ + return aRect.Inside( m_Pos.x, -m_Pos.y ) || aRect.Inside( m_End.x, -m_End.y ); +} + + +void LIB_RECTANGLE::DoMove( const wxPoint& aPosition ) +{ + wxPoint size = m_End - m_Pos; + m_Pos = aPosition; + m_End = aPosition + size; +} + + +void LIB_RECTANGLE::DoMirrorHorizontal( const wxPoint& aCenter ) +{ + m_Pos.x -= aCenter.x; + m_Pos.x *= -1; + m_Pos.x += aCenter.x; + m_End.x -= aCenter.x; + m_End.x *= -1; + m_End.x += aCenter.x; +} + + +void LIB_RECTANGLE::DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, + const int aTransform[2][2] ) +{ + wxASSERT( aPlotter != NULL ); + + wxPoint pos = TransformCoordinate( aTransform, m_Pos ) + aOffset; + wxPoint end = TransformCoordinate( aTransform, m_End ) + aOffset; + + if( aFill && m_Fill == FILLED_WITH_BG_BODYCOLOR ) + { + aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); + aPlotter->rect( pos, end, FILLED_WITH_BG_BODYCOLOR, 0 ); + } + + aPlotter->set_color( ReturnLayerColor( LAYER_DEVICE ) ); + aPlotter->rect( pos, end, m_Fill, GetPenSize() ); +} + + +/** Function GetPenSize + * @return the size of the "pen" that be used to draw or plot this item + */ +int LIB_RECTANGLE::GetPenSize() +{ + return ( m_Width == 0 ) ? g_DrawDefaultLineThickness : m_Width; +} + +void LIB_RECTANGLE::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, + const wxPoint& aOffset, int aColor, int aDrawMode, + void* aData, const int aTransformMatrix[2][2] ) +{ + wxPoint pos1, pos2; + + int color = ReturnLayerColor( LAYER_DEVICE ); + + if( aColor < 0 ) // Used normal color or selected color + { + if( m_Selected & IS_SELECTED ) + color = g_ItemSelectetColor; + } + else + color = aColor; + + pos1 = TransformCoordinate( aTransformMatrix, m_Pos ) + aOffset; + pos2 = TransformCoordinate( aTransformMatrix, m_End ) + aOffset; + + FILL_T fill = aData ? NO_FILL : m_Fill; + if( aColor >= 0 ) + fill = NO_FILL; + + GRSetDrawMode( aDC, aDrawMode ); + + if( fill == FILLED_WITH_BG_BODYCOLOR && !aData ) + GRFilledRect( &aPanel->m_ClipBox, aDC, pos1.x, pos1.y, pos2.x, pos2.y, GetPenSize( ), + (m_Flags & IS_MOVED) ? color : ReturnLayerColor( LAYER_DEVICE_BACKGROUND ), + ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); + else if( m_Fill == FILLED_SHAPE && !aData ) + GRFilledRect( &aPanel->m_ClipBox, aDC, pos1.x, pos1.y, pos2.x, pos2.y, + GetPenSize(), color, color ); + else + GRRect( &aPanel->m_ClipBox, aDC, pos1.x, pos1.y, pos2.x, pos2.y, GetPenSize(), color ); + + /* Set to one (1) to draw bounding box around rectangle to validate + * bounding box calculation. */ +#if 0 + EDA_Rect bBox = GetBoundingBox(); + bBox.Inflate( m_Width + 1, m_Width + 1 ); + GRRect( &aPanel->m_ClipBox, aDC, bBox.GetOrigin().x, bBox.GetOrigin().y, + bBox.GetEnd().x, bBox.GetEnd().y, 0, LIGHTMAGENTA ); +#endif +} + + +void LIB_RECTANGLE::DisplayInfo( WinEDA_DrawFrame* aFrame ) +{ + wxString msg; + + LIB_DRAW_ITEM::DisplayInfo( aFrame ); + + msg = ReturnStringFromValue( g_UserUnit, m_Width, EESCHEMA_INTERNAL_UNIT, true ); + + aFrame->AppendMsgPanel( _( "Line width" ), msg, BLUE ); +} + + +EDA_Rect LIB_RECTANGLE::GetBoundingBox() +{ + EDA_Rect rect; + + rect.SetOrigin( m_Pos.x, m_Pos.y * -1 ); + rect.SetEnd( m_End.x, m_End.y * -1 ); + rect.Inflate( m_Width / 2, m_Width / 2 ); + return rect; +} + + +/** + * Function HitTest + * tests if the given wxPoint is within the bounds of this object. + * @param aRefPoint A wxPoint to test in eeschema space + * @return true if a hit, else false + */ +bool LIB_RECTANGLE::HitTest( const wxPoint& aRefPoint ) +{ + int mindist = ( m_Width ? m_Width / 2 : g_DrawDefaultLineThickness / 2 ) + 1; + + // Have a minimal tolerance for hit test + if( mindist < MINIMUM_SELECTION_DISTANCE ) + mindist = MINIMUM_SELECTION_DISTANCE; + + return HitTest( aRefPoint, mindist, DefaultTransformMatrix ); +} + + +/** Function HitTest + * @return true if the point aPosRef is near this object + * @param aRefPoint = a wxPoint to test + * @param aThreshold = max distance to this object (usually the half thickness + * of a line) + * @param aTransMat = the transform matrix + */ +bool LIB_RECTANGLE::HitTest( wxPoint aRefPoint, int aThreshold, const int aTransMat[2][2] ) +{ + wxPoint actualStart = TransformCoordinate( aTransMat, m_Pos ); + wxPoint actualEnd = TransformCoordinate( aTransMat, m_End ); + + // locate lower segment + wxPoint start, end; + + start = actualStart; + end.x = actualEnd.x; + end.y = actualStart.y; + if( TestSegmentHit( aRefPoint, start, end, aThreshold ) ) + return true; + + // locate right segment + start.x = actualEnd.x; + end.y = actualEnd.y; + if( TestSegmentHit( aRefPoint, start, end, aThreshold ) ) + return true; + + // locate upper segment + start.y = actualEnd.y; + end.x = actualStart.x; + if( TestSegmentHit( aRefPoint, start, end, aThreshold ) ) + return true; + + // locate left segment + start = actualStart; + end.x = actualStart.x; + end.y = actualEnd.y; + if( TestSegmentHit( aRefPoint, start, end, aThreshold ) ) + return true; + + return false; +} diff --git a/eeschema/lib_rectangle.h b/eeschema/lib_rectangle.h new file mode 100644 index 0000000000..f51dcbe702 --- /dev/null +++ b/eeschema/lib_rectangle.h @@ -0,0 +1,96 @@ +/********************************/ +/* Graphic Body Item: Rectangle */ +/********************************/ + +#ifndef _LIB_RECTANGLE_H_ +#define _LIB_RECTANGLE_H_ + + +#include "lib_draw_item.h" + + +class LIB_RECTANGLE : public LIB_DRAW_ITEM +{ +public: + wxPoint m_End; /* Rectangle end point. */ + wxPoint m_Pos; /* Rectangle start point. */ + int m_Width; /* Line width */ + bool m_isWidthLocked; /* Flag: Keep width locked */ + bool m_isHeightLocked; /* Flag: Keep height locked */ + bool m_isStartPointSelected; /* Flag: is the upper left edge selected ? */ + +public: + LIB_RECTANGLE(LIB_COMPONENT * aParent); + LIB_RECTANGLE( const LIB_RECTANGLE& aRect ); + ~LIB_RECTANGLE() { } + virtual wxString GetClass() const + { + return wxT( "LIB_RECTANGLE" ); + } + + + /** + * Write rectangle object out to a FILE in "*.lib" format. + * + * @param aFile - The FILE to write to. + * @return - true if success writing else false. + */ + virtual bool Save( FILE* aFile ); + virtual bool Load( char* aLine, wxString& aErrorMsg ); + + /** + * Test if the given point is within the bounds of this object. + * + * @param aRefPos - A wxPoint to test + * @return - true if a hit, else false + */ + virtual bool HitTest( const wxPoint& aRefPos ); + + /** + * @param aPosRef - a wxPoint to test + * @param aThreshold - max distance to this object (usually the half + * thickness of a line) + * @param aTransMat - the transform matrix + * @return true if the point aPosRef is near this object + */ + virtual bool HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] ); + + /** + * @return the size of the "pen" that be used to draw or plot this item + */ + virtual int GetPenSize( ); + + void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset, + int aColor, int aDrawMode, void* aData, + const int aTransformMatrix[2][2] ); + + virtual EDA_Rect GetBoundingBox(); + virtual void DisplayInfo( WinEDA_DrawFrame* aFrame ); + +protected: + virtual LIB_DRAW_ITEM* DoGenCopy(); + + /** + * Provide the rectangle draw object specific comparison. + * + * The sort order is as follows: + * - Rectangle horizontal (X) start position. + * - Rectangle vertical (Y) start position. + * - Rectangle horizontal (X) end position. + * - Rectangle vertical (Y) end position. + */ + virtual int DoCompare( const LIB_DRAW_ITEM& aOther ) const; + + virtual void DoOffset( const wxPoint& aOffset ); + virtual bool DoTestInside( EDA_Rect& aRect ); + virtual void DoMove( const wxPoint& aPosition ); + virtual wxPoint DoGetPosition() { return m_Pos; } + virtual void DoMirrorHorizontal( const wxPoint& aCenter ); + virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, + const int aTransform[2][2] ); + virtual int DoGetWidth() { return m_Width; } + virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; } +}; + + +#endif // _LIB_REACTANGLE_H_ diff --git a/eeschema/libedit_onrightclick.cpp b/eeschema/libedit_onrightclick.cpp index 06e84aaf11..c820f357a2 100644 --- a/eeschema/libedit_onrightclick.cpp +++ b/eeschema/libedit_onrightclick.cpp @@ -19,19 +19,18 @@ #include "libeditframe.h" #include "class_libentry.h" #include "class_pin.h" +#include "lib_polyline.h" /* functions to add commands and submenus depending on the item */ static void AddMenusForBlock( wxMenu* PopMenu, WinEDA_LibeditFrame* frame ); -static void AddMenusForPin( wxMenu* PopMenu, LIB_PIN* Pin, - WinEDA_LibeditFrame* frame ); +static void AddMenusForPin( wxMenu* PopMenu, LIB_PIN* Pin, WinEDA_LibeditFrame* frame ); -bool WinEDA_LibeditFrame::OnRightClick( const wxPoint& MousePos, - wxMenu* PopMenu ) +bool WinEDA_LibeditFrame::OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu ) { LIB_DRAW_ITEM* DrawEntry = LocateItemUsingCursor(); - bool BlockActive = (GetScreen()->m_BlockLocate.m_Command != BLOCK_IDLE); + bool BlockActive = (GetScreen()->m_BlockLocate.m_Command != BLOCK_IDLE ); if( m_component == NULL ) return true; diff --git a/eeschema/protos.h b/eeschema/protos.h index 01ce0abd08..5c1ddab8e3 100644 --- a/eeschema/protos.h +++ b/eeschema/protos.h @@ -2,10 +2,18 @@ #ifndef __PROTOS_H__ #define __PROTOS_H__ +#include "block_commande.h" +#include "colors.h" + +#include + class EDA_BaseStruct; class WinEDA_DrawPanel; +class WinEDA_DrawFrame; class WinEDA_SchematicFrame; +class WinEDA_LibeditFrame; +class CMP_LIBRARY; class LIB_COMPONENT; class LIB_DRAW_ITEM; class SCH_COMPONENT; @@ -25,8 +33,7 @@ wxString ReturnDefaultFieldName( int aFieldNdx ); /* DATABASE.CPP */ /****************/ void DisplayCmpDoc( wxString& Name ); -wxString DataBaseGetName( WinEDA_DrawFrame* frame, wxString& Keys, - wxString& BufName ); +wxString DataBaseGetName( WinEDA_DrawFrame* frame, wxString& Keys, wxString& BufName ); /*********************/ /* DANGLING_ENDS.CPP */ @@ -41,13 +48,10 @@ void IncrementLabelMember( wxString& name ); /****************/ /* EDITPART.CPP */ /****************/ -void InstallCmpeditFrame( WinEDA_SchematicFrame* parent, wxPoint& pos, - SCH_COMPONENT* m_Cmp ); +void InstallCmpeditFrame( WinEDA_SchematicFrame* parent, wxPoint& pos, SCH_COMPONENT* m_Cmp ); -bool MapAngles( int* Angle1, - int* Angle2, - const int TransMat[2][2] ); +bool MapAngles( int* Angle1, int* Angle2, const int TransMat[2][2] ); /** @@ -57,23 +61,19 @@ bool MapAngles( int* Angle1, * @param aPosition = the position to transform * @return the new coordinate */ -wxPoint TransformCoordinate( const int aTransformMatrix[2][2], - const wxPoint& aPosition ); +wxPoint TransformCoordinate( const int aTransformMatrix[2][2], const wxPoint& aPosition ); void SnapLibItemPoint( int OrigX, int OrigY, int* ClosestX, int* ClosestY, SCH_COMPONENT* DrawLibItem ); -bool LibItemInBox( int x1, int y1, int x2, int y2, - SCH_COMPONENT* DrawLibItem ); +bool LibItemInBox( int x1, int y1, int x2, int y2, SCH_COMPONENT* DrawLibItem ); /************/ /* BLOCK.CPP */ /************/ -void DeleteStruct( WinEDA_DrawPanel* panel, - wxDC* DC, - SCH_ITEM* DrawStruct ); +void DeleteStruct( WinEDA_DrawPanel* panel, wxDC* DC, SCH_ITEM* DrawStruct ); // operations_on_item_lists.cpp /** function DuplicateStruct @@ -93,8 +93,7 @@ SCH_ITEM* DuplicateStruct( SCH_ITEM* DrawStruct, bool aClone = false ); SCH_COMPONENT* LocateSmallestComponent( SCH_SCREEN* Screen ); /* Find the item within block selection. */ -int PickItemsInBlock( BLOCK_SELECTOR& aBlock, - BASE_SCREEN* screen ); +int PickItemsInBlock( BLOCK_SELECTOR& aBlock, BASE_SCREEN* screen ); /* function PickStruct: * Search at location pos @@ -126,25 +125,21 @@ int PickItemsInBlock( BLOCK_SELECTOR& aBlock, * Pointer to the structure if only 1 item is selected. * NULL if no items are selects. */ -SCH_ITEM* PickStruct( const wxPoint& refpos, - BASE_SCREEN* screen, - int SearchMask ); +SCH_ITEM* PickStruct( const wxPoint& refpos, BASE_SCREEN* screen, int SearchMask ); SCH_SHEET_PIN* LocateSheetLabel( SCH_SHEET* Sheet, const wxPoint& pos ); -LIB_PIN* LocateAnyPin( SCH_ITEM* DrawList, - const wxPoint& RefPos, - SCH_COMPONENT** libpart = NULL ); +LIB_PIN* LocateAnyPin( SCH_ITEM* DrawList, + const wxPoint& RefPos, + SCH_COMPONENT** libpart = NULL ); -SCH_SHEET_PIN* LocateAnyPinSheet( const wxPoint& RefPos, - SCH_ITEM* DrawList ); +SCH_SHEET_PIN* LocateAnyPinSheet( const wxPoint& RefPos, SCH_ITEM* DrawList ); /***************/ /* EEREDRAW.CPP */ /***************/ -void DrawDanglingSymbol( WinEDA_DrawPanel* panel, wxDC* DC, - const wxPoint& pos, int Color ); +void DrawDanglingSymbol( WinEDA_DrawPanel* panel, wxDC* DC, const wxPoint& pos, int Color ); void DrawStructsInGhost( WinEDA_DrawPanel* aPanel, wxDC* aDC, @@ -168,8 +163,7 @@ void RedrawOneStruct( WinEDA_DrawPanel* panel, /**************/ void SeedLayers(); EDA_Colors ReturnLayerColor( int Layer ); -void DisplayColorSetupFrame( WinEDA_DrawFrame* parent, - const wxPoint& pos ); +void DisplayColorSetupFrame( WinEDA_DrawFrame* parent, const wxPoint& pos ); /**************/ @@ -210,9 +204,7 @@ void DeleteAllMarkers( int type ); /**************/ /* PINEDIT.CPP */ /**************/ -void InstallPineditFrame( WinEDA_LibeditFrame* parent, - wxDC* DC, - const wxPoint& pos ); +void InstallPineditFrame( WinEDA_LibeditFrame* parent, wxDC* DC, const wxPoint& pos ); /**************/ @@ -290,8 +282,7 @@ void SetaParent( EDA_BaseStruct* Struct, BASE_SCREEN* Screen ); /***************/ /* OPTIONS.CPP */ /***************/ -void DisplayOptionFrame( WinEDA_SchematicFrame* parent, - const wxPoint& framepos ); +void DisplayOptionFrame( WinEDA_SchematicFrame* parent, const wxPoint& framepos ); /****************/ /* CONTROLE.CPP */ diff --git a/eeschema/symbdraw.cpp b/eeschema/symbdraw.cpp index ccc74e3214..d19ed57df2 100644 --- a/eeschema/symbdraw.cpp +++ b/eeschema/symbdraw.cpp @@ -19,12 +19,13 @@ #include "libeditframe.h" #include "class_libentry.h" #include "dialog_lib_edit_draw_item.h" +#include "lib_arc.h" +#include "lib_circle.h" +#include "lib_polyline.h" +#include "lib_rectangle.h" #include -#define EraseItem( item ) item->Draw( Panel, DC, wxPoint( 0, 0 ), -1, g_XorMode, NULL, \ - DefaultTransformMatrix ) - static void SymbolDisplayDraw( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ); static void ComputeArc( LIB_ARC* DrawItem, wxPoint ArcCentre ); static void ComputeArcRadiusAngles( LIB_ARC* arc ); @@ -70,8 +71,7 @@ void WinEDA_LibeditFrame::EditGraphicSymbol( wxDC* DC, LIB_DRAW_ITEM* DrawItem ) dialog.SetWidthUnits( ReturnUnitSymbol( g_UserUnit ) ); - wxString val = ReturnStringFromValue( g_UserUnit, m_drawLineWidth, - m_InternalUnits ); + wxString val = ReturnStringFromValue( g_UserUnit, m_drawLineWidth, m_InternalUnits ); dialog.SetWidth( val ); dialog.SetApplyToAllUnits( !m_drawSpecificUnit ); dialog.EnableApplyToAllUnits( component && component->GetPartCount() > 1 ); @@ -85,8 +85,7 @@ void WinEDA_LibeditFrame::EditGraphicSymbol( wxDC* DC, LIB_DRAW_ITEM* DrawItem ) return; val = dialog.GetWidth(); - m_drawLineWidth = ReturnValueFromString( g_UserUnit, val, - m_InternalUnits ); + m_drawLineWidth = ReturnValueFromString( g_UserUnit, val, m_InternalUnits ); m_drawSpecificConvert = !dialog.GetApplyToAllConversions(); m_drawSpecificUnit = !dialog.GetApplyToAllUnits(); @@ -152,7 +151,7 @@ static void AbortSymbolTraceOn( WinEDA_DrawPanel* Panel, wxDC* DC ) // Restore old attributes, when the item was modified if( item->m_Flags == IS_RESIZED ) { - EraseItem( item ); + item->Draw( Panel, DC, wxPoint( 0, 0 ), -1, g_XorMode, NULL, DefaultTransformMatrix ); switch( item->Type() ) { @@ -202,8 +201,7 @@ static void AbortSymbolTraceOn( WinEDA_DrawPanel* Panel, wxDC* DC ) } -LIB_DRAW_ITEM* WinEDA_LibeditFrame::CreateGraphicItem( LIB_COMPONENT* LibEntry, - wxDC* DC ) +LIB_DRAW_ITEM* WinEDA_LibeditFrame::CreateGraphicItem( LIB_COMPONENT* LibEntry, wxDC* DC ) { DrawPanel->ManageCurseur = SymbolDisplayDraw; DrawPanel->ForceCloseManageCurseur = AbortSymbolTraceOn; @@ -261,18 +259,6 @@ LIB_DRAW_ITEM* WinEDA_LibeditFrame::CreateGraphicItem( LIB_COMPONENT* LibEntry, } break; - case COMPONENT_LINE_DRAW_TYPE: - { - LIB_SEGMENT* Segment = new LIB_SEGMENT( LibEntry ); - - m_drawItem = Segment; - Segment->m_Pos = GetScreen()->m_Curseur; - NEGATE( Segment->m_Pos.y ); - Segment->m_End = Segment->m_Pos; - Segment->m_Width = m_drawLineWidth; - } - break; - case ID_LIBEDIT_BODY_TEXT_BUTT: { LIB_TEXT* Text = new LIB_TEXT( LibEntry ); @@ -789,10 +775,6 @@ static void SymbolDisplayDraw( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ) } break; - case COMPONENT_LINE_DRAW_TYPE: - ( (LIB_SEGMENT*) item )->m_End = currentCursorPosition; - break; - case COMPONENT_GRAPHIC_TEXT_DRAW_TYPE: break; @@ -808,10 +790,9 @@ static void SymbolDisplayDraw( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ) } else { - item->Draw( panel, DC, wxPoint( 0, 0 ), -1, DrawMode, NULL, - DefaultTransformMatrix ); + item->Draw( panel, DC, wxPoint( 0, 0 ), -1, DrawMode, NULL, DefaultTransformMatrix ); - if( item->Type() == COMPONENT_ARC_DRAW_TYPE && item->m_Flags != IS_RESIZED ) + if( item->Type() == COMPONENT_ARC_DRAW_TYPE && item->m_Flags != IS_RESIZED ) { int Color = ReturnLayerColor( LAYER_DEVICE ); GRDashedLine( &panel->m_ClipBox, DC, arcState.startPoint.x, -arcState.startPoint.y, @@ -900,8 +881,7 @@ void WinEDA_LibeditFrame::EndDrawGraphicItem( wxDC* DC ) m_drawItem->Move( pos ); } - m_component->Draw( DrawPanel, DC, wxPoint( 0, 0 ), m_unit, m_convert, - GR_DEFAULT_DRAWMODE ); + m_component->Draw( DrawPanel, DC, wxPoint( 0, 0 ), m_unit, m_convert, GR_DEFAULT_DRAWMODE ); m_drawItem->m_Flags = 0; m_drawItem = NULL; @@ -924,10 +904,10 @@ static void ComputeArcRadiusAngles( LIB_ARC* arc ) arc->m_Radius = wxRound( EuclideanNorm( centerStartVector ) ); arc->m_t1 = (int) ( atan2( (double) centerStartVector.y, - (double) centerStartVector.x ) * 1800 / M_PI ); + (double) centerStartVector.x ) * 1800 / M_PI ); arc->m_t2 = (int) ( atan2( (double) centerEndVector.y, - (double) centerEndVector.x ) * 1800 / M_PI ); + (double) centerEndVector.x ) * 1800 / M_PI ); NORMALIZE_ANGLE( arc->m_t1 ); NORMALIZE_ANGLE( arc->m_t2 ); // angles = 0 .. 3600 @@ -943,8 +923,7 @@ static void ComputeArcRadiusAngles( LIB_ARC* arc ) wxString msg; int angle = arc->m_t2 - arc->m_t1; msg.Printf( _( "Arc %.1f deg" ), (float) angle / 10 ); - WinEDA_SchematicFrame* frame = - (WinEDA_SchematicFrame*) wxGetApp().GetTopWindow(); + WinEDA_SchematicFrame* frame = (WinEDA_SchematicFrame*) wxGetApp().GetTopWindow(); frame->m_LibeditFrame->PrintMsg( msg ); while( (arc->m_t2 - arc->m_t1) >= 1800 ) @@ -1002,8 +981,7 @@ static void ComputeArc( LIB_ARC* DrawItem, wxPoint ArcCentre ) dx = arcState.startPoint.x - DrawItem->m_Pos.x; dy = arcState.startPoint.y - DrawItem->m_Pos.y; - DrawItem->m_Radius = (int) sqrt( ( (double) dx * dx ) + - ( (double) dy * dy ) ); + DrawItem->m_Radius = (int) sqrt( ( (double) dx * dx ) + ( (double) dy * dy ) ); DrawItem->m_t1 = (int) ( atan2( (double) dy, (double) dx ) * 1800 / M_PI ); @@ -1031,8 +1009,7 @@ static void ComputeArc( LIB_ARC* DrawItem, wxPoint ArcCentre ) wxString msg; angle = DrawItem->m_t2 - DrawItem->m_t1; msg.Printf( _( "Arc %.1f deg" ), (float) angle / 10 ); - WinEDA_SchematicFrame* frame = - (WinEDA_SchematicFrame*) wxGetApp().GetTopWindow(); + WinEDA_SchematicFrame* frame = (WinEDA_SchematicFrame*) wxGetApp().GetTopWindow(); frame->m_LibeditFrame->PrintMsg( msg ); while( (DrawItem->m_t2 - DrawItem->m_t1) >= 1800 ) @@ -1074,12 +1051,12 @@ static wxPoint ComputeCircumCenter( wxPoint A, wxPoint B, wxPoint C ) D = 1e-7; circumCenterX = ( (Ay * Ay + Ax * Ax) * (By - Cy) + - (By * By + Bx * Bx) * (Cy - Ay) + - (Cy * Cy + Cx * Cx) * (Ay - By) ) / D; + (By * By + Bx * Bx) * (Cy - Ay) + + (Cy * Cy + Cx * Cx) * (Ay - By) ) / D; circumCenterY = ( (Ay * Ay + Ax * Ax) * (Cx - Bx) + - (By * By + Bx * Bx) * (Ax - Cx) + - (Cy * Cy + Cx * Cx) * (Bx - Ax) ) / D; + (By * By + Bx * Bx) * (Ax - Cx) + + (Cy * Cy + Cx * Cx) * (Bx - Ax) ) / D; circumCenter.x = (int) circumCenterX; circumCenter.y = (int) circumCenterY; diff --git a/include/bezier_curves.h b/include/bezier_curves.h index 75330747c4..9b589bff3b 100644 --- a/include/bezier_curves.h +++ b/include/bezier_curves.h @@ -3,6 +3,9 @@ #include +#include + + /** * Function Bezier2Poly * convert a Bezier curve to a polyline diff --git a/include/common.h b/include/common.h index 2d53cea399..3df729b4af 100644 --- a/include/common.h +++ b/include/common.h @@ -6,6 +6,7 @@ #ifndef __INCLUDE__COMMON_H__ #define __INCLUDE__COMMON_H__ 1 +#include "wx/wx.h" #include "wx/confbase.h" #include "wx/fileconf.h" diff --git a/include/plot_common.h b/include/plot_common.h index 5acb874999..399e968036 100644 --- a/include/plot_common.h +++ b/include/plot_common.h @@ -11,6 +11,10 @@ #include #include "drawtxt.h" + +class Ki_PageDescr; + + /** * Enum PlotFormat * must be kept in order of the radio buttons in the plot panel/window.