Commit fc0864be authored by Wayne Stambaugh's avatar Wayne Stambaugh

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.
parent 443534e7
......@@ -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
......
......@@ -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
......
......@@ -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"
......
......@@ -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"
......
......@@ -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 <boost/foreach.hpp>
......@@ -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;
......
......@@ -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 <map>
......
......@@ -6,7 +6,7 @@
#define CLASS_LIBENTRY_FIELDS_H
#include "program.h"
#include "classes_body_items.h"
#include "lib_draw_item.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 */
......
......@@ -15,6 +15,7 @@
#include "protos.h"
#include "class_library.h"
#include "dialog_schematic_find.h"
#include "lib_rectangle.h"
#include <wx/tokenzr.h>
......
/************************/
/* 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<wxPoint> 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 );
}
......@@ -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"
......
......@@ -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"
......
......@@ -5,6 +5,16 @@
#ifndef _GENERAL_H_
#define _GENERAL_H_
#include <wx/string.h>
#include <wx/gdicmn.h>
#include "block_commande.h"
#include "program.h"
class SCH_ITEM;
class SCH_SHEET;
#define EESCHEMA_VERSION 2
......
/*******************/
/** 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 );
}
/**************************/
/* 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_
/**********************/
/** 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<wxPoint> 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 );
}
#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<wxPoint> m_BezierPoints; // list of parameter (3|4)
std::vector<wxPoint> 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_
/*************************/
/** 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 );
}
/*****************************/
/* 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_
/*********************/
/* 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 );
}
......@@ -4,8 +4,8 @@
/* Definitions of graphic items used to create shapes in component libraries.
*/
#ifndef CLASSES_BODY_ITEMS_H
#define CLASSES_BODY_ITEMS_H
#ifndef _LIB_DRAW_ITEM_H_
#define _LIB_DRAW_ITEM_H_
#include "base_struct.h"
......@@ -18,6 +18,9 @@ class LIB_DRAW_ITEM;
class LIB_PIN;
extern const int fill_tab[];
#define MINIMUM_SELECTION_DISTANCE 15 // Minimum selection distance in mils
......@@ -48,6 +51,8 @@ typedef std::vector< LIB_PIN* > LIB_PIN_LIST;
*/
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
......@@ -61,9 +66,14 @@ public:
* 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. */
/**
* 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()
......@@ -72,10 +82,49 @@ public:
}
LIB_DRAW_ITEM( KICAD_T aType, LIB_COMPONENT * aParent );
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
*
......@@ -137,8 +186,7 @@ public:
* @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;
virtual bool HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] ) = 0;
/**
* @return the boundary box for this, in library coordinates
......@@ -298,179 +346,6 @@ protected:
};
/**************************/
/* 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. */
......@@ -568,363 +443,4 @@ protected:
};
/********************************/
/* 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<wxPoint> 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<wxPoint> m_BezierPoints; // list of parameter (3|4)
std::vector<wxPoint> 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
#endif // _LIB_DRAW_ITEM_H_
/************************/
/** 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 );
}
/**********************************************************/
/* 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<wxPoint> 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_
/*************************/
/** 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;
}
/********************************/
/* 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_
......@@ -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;
......
......@@ -2,10 +2,18 @@
#ifndef __PROTOS_H__
#define __PROTOS_H__
#include "block_commande.h"
#include "colors.h"
#include <wx/wx.h>
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 */
......
......@@ -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 <boost/foreach.hpp>
#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;
......
......@@ -3,6 +3,9 @@
#include <vector>
#include <wx/gdicmn.h>
/**
* Function Bezier2Poly
* convert a Bezier curve to a polyline
......
......@@ -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"
......
......@@ -11,6 +11,10 @@
#include <vector>
#include "drawtxt.h"
class Ki_PageDescr;
/**
* Enum PlotFormat
* must be kept in order of the radio buttons in the plot panel/window.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment