Import svg import code from experimental trunk: start point
This commit is contained in:
parent
157519d722
commit
74a9d5401a
|
@ -181,11 +181,25 @@ if( KICAD_SCRIPTING AND KICAD_SCRIPTING_ACTION_MENU )
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if( 1)
|
||||||
set( PCBNEW_IMPORT_DXF
|
set( PCBNEW_IMPORT_DXF
|
||||||
import_dxf/dialog_dxf_import.cpp
|
import_dxf/dialog_dxf_import.cpp
|
||||||
import_dxf/dialog_dxf_import_base.cpp
|
import_dxf/dialog_dxf_import_base.cpp
|
||||||
import_dxf/dxf2brd_items.cpp
|
import_dxf/dxf2brd_items.cpp
|
||||||
)
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set( PCBNEW_IMPORT_GFX
|
||||||
|
import_gfx/dialog_import_gfx_base.cpp
|
||||||
|
import_gfx/dialog_import_gfx.cpp
|
||||||
|
import_gfx/graphics_import_mgr.cpp
|
||||||
|
import_gfx/graphics_importer.cpp
|
||||||
|
import_gfx/graphics_importer_pcbnew.cpp
|
||||||
|
import_gfx/graphics_importer_buffer.cpp
|
||||||
|
import_gfx/dxf_import_plugin.cpp
|
||||||
|
import_gfx/svg_import_plugin.cpp
|
||||||
|
import_gfx/nanosvg.cpp
|
||||||
|
)
|
||||||
|
|
||||||
set( PCBNEW_EXPORTERS
|
set( PCBNEW_EXPORTERS
|
||||||
exporters/export_d356.cpp
|
exporters/export_d356.cpp
|
||||||
|
@ -209,6 +223,7 @@ set( PCBNEW_CLASS_SRCS
|
||||||
${PCBNEW_DIALOGS}
|
${PCBNEW_DIALOGS}
|
||||||
${PCBNEW_EXPORTERS}
|
${PCBNEW_EXPORTERS}
|
||||||
${PCBNEW_IMPORT_DXF}
|
${PCBNEW_IMPORT_DXF}
|
||||||
|
${PCBNEW_IMPORT_GFX}
|
||||||
|
|
||||||
autorouter/rect_placement/rect_placement.cpp
|
autorouter/rect_placement/rect_placement.cpp
|
||||||
autorouter/spread_footprints.cpp
|
autorouter/spread_footprints.cpp
|
||||||
|
@ -653,6 +668,7 @@ endif ()
|
||||||
|
|
||||||
set( PCBNEW_KIFACE_LIBRARIES
|
set( PCBNEW_KIFACE_LIBRARIES
|
||||||
3d-viewer
|
3d-viewer
|
||||||
|
connectivity
|
||||||
pcbcommon
|
pcbcommon
|
||||||
pnsrouter
|
pnsrouter
|
||||||
pcad2kicadpcb
|
pcad2kicadpcb
|
||||||
|
@ -663,7 +679,6 @@ set( PCBNEW_KIFACE_LIBRARIES
|
||||||
gal
|
gal
|
||||||
lib_dxf
|
lib_dxf
|
||||||
idf3
|
idf3
|
||||||
connectivity
|
|
||||||
${wxWidgets_LIBRARIES}
|
${wxWidgets_LIBRARIES}
|
||||||
${GITHUB_PLUGIN_LIBRARIES}
|
${GITHUB_PLUGIN_LIBRARIES}
|
||||||
${GDI_PLUS_LIBRARIES}
|
${GDI_PLUS_LIBRARIES}
|
||||||
|
|
|
@ -0,0 +1,325 @@
|
||||||
|
/**
|
||||||
|
* @file dialog_gfx_import.cpp
|
||||||
|
* @brief Dialog to import a vector graphics file on a given board layer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||||
|
* Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dialog_import_gfx.h"
|
||||||
|
#include <kiface_i.h>
|
||||||
|
#include <convert_to_biu.h>
|
||||||
|
#include <confirm.h>
|
||||||
|
|
||||||
|
#include <pcb_base_frame.h>
|
||||||
|
#include <class_board.h>
|
||||||
|
#include <class_module.h>
|
||||||
|
#include <class_edge_mod.h>
|
||||||
|
#include <class_text_mod.h>
|
||||||
|
#include <class_pcb_text.h>
|
||||||
|
#include <pcb_layer_box_selector.h>
|
||||||
|
|
||||||
|
#include <import_gfx/graphics_importer_pcbnew.h>
|
||||||
|
|
||||||
|
// Keys to store setup in config
|
||||||
|
#define IMPORT_GFX_LAYER_OPTION_KEY "GfxImportBrdLayer"
|
||||||
|
#define IMPORT_GFX_COORD_ORIGIN_KEY "GfxImportCoordOrigin"
|
||||||
|
#define IMPORT_GFX_LAST_FILE_KEY "GfxImportLastFile"
|
||||||
|
#define IMPORT_GFX_GRID_UNITS_KEY "GfxImportGridUnits"
|
||||||
|
#define IMPORT_GFX_GRID_OFFSET_X_KEY "GfxImportGridOffsetX"
|
||||||
|
#define IMPORT_GFX_GRID_OFFSET_Y_KEY "GfxImportGridOffsetY"
|
||||||
|
|
||||||
|
|
||||||
|
// Static members of DIALOG_IMPORT_GFX, to remember the user's choices during the session
|
||||||
|
wxString DIALOG_IMPORT_GFX::m_filename;
|
||||||
|
int DIALOG_IMPORT_GFX::m_offsetSelection = 0;
|
||||||
|
LAYER_NUM DIALOG_IMPORT_GFX::m_layer = Dwgs_User;
|
||||||
|
|
||||||
|
|
||||||
|
DIALOG_IMPORT_GFX::DIALOG_IMPORT_GFX( PCB_BASE_FRAME* aParent, bool aUseModuleItems )
|
||||||
|
: DIALOG_IMPORT_GFX_BASE( aParent )
|
||||||
|
{
|
||||||
|
m_parent = aParent;
|
||||||
|
|
||||||
|
if( aUseModuleItems )
|
||||||
|
m_importer.reset( new GRAPHICS_IMPORTER_MODULE( m_parent->GetBoard()->m_Modules ) );
|
||||||
|
else
|
||||||
|
m_importer.reset( new GRAPHICS_IMPORTER_BOARD( m_parent->GetBoard() ) );
|
||||||
|
|
||||||
|
m_config = Kiface().KifaceSettings();
|
||||||
|
m_gridUnits = 0;
|
||||||
|
m_gridOffsetX = 0.0;
|
||||||
|
m_gridOffsetY = 0.0;
|
||||||
|
|
||||||
|
if( m_config )
|
||||||
|
{
|
||||||
|
m_layer = m_config->Read( IMPORT_GFX_LAYER_OPTION_KEY, (long)Dwgs_User );
|
||||||
|
m_offsetSelection = m_config->Read( IMPORT_GFX_COORD_ORIGIN_KEY, (long)0 );
|
||||||
|
m_filename = m_config->Read( IMPORT_GFX_LAST_FILE_KEY, wxEmptyString );
|
||||||
|
m_config->Read( IMPORT_GFX_GRID_UNITS_KEY, &m_gridUnits, 0 );
|
||||||
|
m_config->Read( IMPORT_GFX_GRID_OFFSET_X_KEY, &m_gridOffsetX, 0.0 );
|
||||||
|
m_config->Read( IMPORT_GFX_GRID_OFFSET_Y_KEY, &m_gridOffsetY, 0.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_PCBGridUnits->SetSelection( m_gridUnits );
|
||||||
|
wxString tmpStr;
|
||||||
|
tmpStr << m_gridOffsetX;
|
||||||
|
m_PCBXCoord->SetValue( tmpStr );
|
||||||
|
tmpStr = "";
|
||||||
|
tmpStr << m_gridOffsetY;
|
||||||
|
m_PCBYCoord->SetValue( tmpStr );
|
||||||
|
|
||||||
|
m_textCtrlFileName->SetValue( m_filename );
|
||||||
|
m_rbOffsetOption->SetSelection( m_offsetSelection );
|
||||||
|
|
||||||
|
// Configure the layers list selector
|
||||||
|
m_SelLayerBox->SetLayersHotkeys( false ); // Do not display hotkeys
|
||||||
|
m_SelLayerBox->SetNotAllowedLayerSet( LSET::AllCuMask() ); // Do not use copper layers
|
||||||
|
m_SelLayerBox->SetBoardFrame( m_parent );
|
||||||
|
m_SelLayerBox->Resync();
|
||||||
|
|
||||||
|
if( m_SelLayerBox->SetLayerSelection( m_layer ) < 0 )
|
||||||
|
{
|
||||||
|
m_layer = Dwgs_User;
|
||||||
|
m_SelLayerBox->SetLayerSelection( m_layer );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_sdbSizer1OK->SetDefault();
|
||||||
|
GetSizer()->Fit( this );
|
||||||
|
GetSizer()->SetSizeHints( this );
|
||||||
|
Centre();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DIALOG_IMPORT_GFX::~DIALOG_IMPORT_GFX()
|
||||||
|
{
|
||||||
|
m_offsetSelection = m_rbOffsetOption->GetSelection();
|
||||||
|
m_layer = m_SelLayerBox->GetLayerSelection();
|
||||||
|
|
||||||
|
if( m_config )
|
||||||
|
{
|
||||||
|
m_config->Write( IMPORT_GFX_LAYER_OPTION_KEY, (long)m_layer );
|
||||||
|
m_config->Write( IMPORT_GFX_COORD_ORIGIN_KEY, m_offsetSelection );
|
||||||
|
m_config->Write( IMPORT_GFX_LAST_FILE_KEY, m_filename );
|
||||||
|
|
||||||
|
m_config->Write( IMPORT_GFX_GRID_UNITS_KEY, GetPCBGridUnits() );
|
||||||
|
m_config->Write( IMPORT_GFX_GRID_OFFSET_X_KEY, m_PCBXCoord->GetValue() );
|
||||||
|
m_config->Write( IMPORT_GFX_GRID_OFFSET_Y_KEY, m_PCBYCoord->GetValue() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DIALOG_IMPORT_GFX::OnBrowseFiles( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
wxString path;
|
||||||
|
wxString filename;
|
||||||
|
|
||||||
|
if( !m_filename.IsEmpty() )
|
||||||
|
{
|
||||||
|
wxFileName fn( m_filename );
|
||||||
|
path = fn.GetPath();
|
||||||
|
filename = fn.GetFullName();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate the list of handled file formats
|
||||||
|
wxString wildcardsDesc;
|
||||||
|
wxString allWildcards;
|
||||||
|
|
||||||
|
for( auto pluginType : GRAPHICS_IMPORT_MGR::GFX_FILE_TYPES )
|
||||||
|
{
|
||||||
|
auto plugin = GRAPHICS_IMPORT_MGR::GetPlugin( pluginType );
|
||||||
|
const auto wildcards = plugin->GetWildcards();
|
||||||
|
|
||||||
|
wildcardsDesc += "|" + plugin->GetName() + " (" + wildcards + ")|" + wildcards;
|
||||||
|
allWildcards += wildcards + ";";
|
||||||
|
}
|
||||||
|
|
||||||
|
wildcardsDesc = "All supported formats|" + allWildcards + wildcardsDesc;
|
||||||
|
|
||||||
|
wxFileDialog dlg( m_parent, _( "Open File" ), path, filename,
|
||||||
|
wildcardsDesc, wxFD_OPEN|wxFD_FILE_MUST_EXIST );
|
||||||
|
|
||||||
|
if( dlg.ShowModal() != wxID_OK )
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxString fileName = dlg.GetPath();
|
||||||
|
|
||||||
|
if( fileName.IsEmpty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_filename = fileName;
|
||||||
|
m_textCtrlFileName->SetValue( fileName );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DIALOG_IMPORT_GFX::OnOKClick( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
m_filename = m_textCtrlFileName->GetValue();
|
||||||
|
|
||||||
|
if( m_filename.IsEmpty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
double offsetX = 0;
|
||||||
|
double offsetY = 0;
|
||||||
|
|
||||||
|
m_offsetSelection = m_rbOffsetOption->GetSelection();
|
||||||
|
|
||||||
|
switch( m_offsetSelection )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
offsetX = m_parent->GetPageSizeIU().x * MM_PER_IU / 2;
|
||||||
|
offsetY = m_parent->GetPageSizeIU().y * MM_PER_IU / 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
offsetY = m_parent->GetPageSizeIU().y * MM_PER_IU / 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
offsetY = m_parent->GetPageSizeIU().y * MM_PER_IU;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
GetPCBGridOffsets( offsetX, offsetY );
|
||||||
|
|
||||||
|
if( GetPCBGridUnits() )
|
||||||
|
{
|
||||||
|
offsetX *= 25.4;
|
||||||
|
offsetY *= 25.4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set coordinates offset for import (offset is given in mm)
|
||||||
|
//m_importer.SetOffset( offsetX, offsetY );
|
||||||
|
m_layer = m_SelLayerBox->GetLayerSelection();
|
||||||
|
m_importer->SetLayer( PCB_LAYER_ID( m_layer ) );
|
||||||
|
auto plugin = GRAPHICS_IMPORT_MGR::GetPluginByExt( wxFileName( m_filename ).GetExt() );
|
||||||
|
|
||||||
|
if( plugin )
|
||||||
|
{
|
||||||
|
m_importer->SetScale( 1e6 ); // @todo: add a setting in the dialog and apply it here
|
||||||
|
m_importer->SetLineWidth( 0.1 ); // @todo add a setting in the dialog and apply it here
|
||||||
|
m_importer->SetPlugin( std::move( plugin ) );
|
||||||
|
|
||||||
|
if( m_importer->Load( m_filename ) )
|
||||||
|
m_importer->Import( 1.0, 1.0 ); // @todo
|
||||||
|
|
||||||
|
EndModal( wxID_OK );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DisplayError( this, _( "There is no plugin to handle this file type" ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DIALOG_IMPORT_GFX::onChangeHeight( wxUpdateUIEvent &event)
|
||||||
|
{
|
||||||
|
double heightInput;
|
||||||
|
|
||||||
|
heightInput = DoubleValueFromString(UNSCALED_UNITS,m_tcHeight->GetValue());
|
||||||
|
|
||||||
|
if(m_cbKeepAspectRatio->GetValue())
|
||||||
|
{
|
||||||
|
// @todo: implement scaling of Y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool InvokeDialogImportGfxBoard( PCB_BASE_FRAME* aCaller )
|
||||||
|
{
|
||||||
|
DIALOG_IMPORT_GFX dlg( aCaller );
|
||||||
|
bool success = ( dlg.ShowModal() == wxID_OK );
|
||||||
|
|
||||||
|
if( success )
|
||||||
|
{
|
||||||
|
PICKED_ITEMS_LIST picklist;
|
||||||
|
BOARD* board = aCaller->GetBoard();
|
||||||
|
auto& items = dlg.GetImportedItems();
|
||||||
|
|
||||||
|
for( auto it = items.begin(); it != items.end(); ++it )
|
||||||
|
{
|
||||||
|
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( it->release() );
|
||||||
|
board->Add( item );
|
||||||
|
|
||||||
|
ITEM_PICKER itemWrapper( item, UR_NEW );
|
||||||
|
picklist.PushItem( itemWrapper );
|
||||||
|
}
|
||||||
|
|
||||||
|
aCaller->SaveCopyInUndoList( picklist, UR_NEW, wxPoint( 0, 0 ) );
|
||||||
|
aCaller->OnModify();
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool InvokeDialogImportGfxModule( PCB_BASE_FRAME* aCaller, MODULE* aModule )
|
||||||
|
{
|
||||||
|
wxASSERT( aModule );
|
||||||
|
|
||||||
|
DIALOG_IMPORT_GFX dlg( aCaller, true );
|
||||||
|
bool success = ( dlg.ShowModal() == wxID_OK );
|
||||||
|
|
||||||
|
if( success )
|
||||||
|
{
|
||||||
|
aCaller->SaveCopyInUndoList( aModule, UR_CHANGED );
|
||||||
|
aCaller->OnModify();
|
||||||
|
auto& list = dlg.GetImportedItems();
|
||||||
|
|
||||||
|
for( auto it = list.begin(); it != list.end(); ++it )
|
||||||
|
{
|
||||||
|
aModule->Add( static_cast<BOARD_ITEM*>( it->release() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DIALOG_IMPORT_GFX::OriginOptionOnUpdateUI( wxUpdateUIEvent& event )
|
||||||
|
{
|
||||||
|
bool enable = m_rbOffsetOption->GetSelection() == 4;
|
||||||
|
|
||||||
|
m_PCBGridUnits->Enable( enable );
|
||||||
|
m_PCBXCoord->Enable( enable );
|
||||||
|
m_PCBYCoord->Enable( enable );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int DIALOG_IMPORT_GFX::GetPCBGridUnits( void )
|
||||||
|
{
|
||||||
|
return m_PCBGridUnits->GetSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DIALOG_IMPORT_GFX::GetPCBGridOffsets( double &aXOffset, double &aYOffset )
|
||||||
|
{
|
||||||
|
aXOffset = DoubleValueFromString( UNSCALED_UNITS, m_PCBXCoord->GetValue() );
|
||||||
|
aYOffset = DoubleValueFromString( UNSCALED_UNITS, m_PCBYCoord->GetValue() );
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||||
|
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dialog_import_gfx_base.h"
|
||||||
|
#include <import_gfx/graphics_importer_pcbnew.h>
|
||||||
|
|
||||||
|
class PCB_BASE_FRAME;
|
||||||
|
|
||||||
|
class DIALOG_IMPORT_GFX : public DIALOG_IMPORT_GFX_BASE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DIALOG_IMPORT_GFX( PCB_BASE_FRAME* aParent, bool aUseModuleItems = false );
|
||||||
|
~DIALOG_IMPORT_GFX();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetImportedItems()
|
||||||
|
*
|
||||||
|
* Returns a list of items imported from a vector graphics file.
|
||||||
|
*/
|
||||||
|
std::list<std::unique_ptr<EDA_ITEM>>& GetImportedItems()
|
||||||
|
{
|
||||||
|
return m_importer->GetItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PCB_BASE_FRAME* m_parent;
|
||||||
|
wxConfigBase* m_config; // Current config
|
||||||
|
std::unique_ptr<GRAPHICS_IMPORTER_PCBNEW> m_importer;
|
||||||
|
int m_gridUnits;
|
||||||
|
double m_gridOffsetX;
|
||||||
|
double m_gridOffsetY;
|
||||||
|
double m_newHeight;
|
||||||
|
double m_newWidth;
|
||||||
|
|
||||||
|
static wxString m_filename;
|
||||||
|
static int m_offsetSelection;
|
||||||
|
static LAYER_NUM m_layer;
|
||||||
|
|
||||||
|
// Virtual event handlers
|
||||||
|
void OnCancelClick( wxCommandEvent& event ) override { event.Skip(); }
|
||||||
|
void OnOKClick( wxCommandEvent& event ) override;
|
||||||
|
void OnBrowseFiles( wxCommandEvent& event ) override;
|
||||||
|
void OriginOptionOnUpdateUI( wxUpdateUIEvent& event ) override;
|
||||||
|
void onChangeHeight( wxUpdateUIEvent& event ) override;
|
||||||
|
int GetPCBGridUnits( void );
|
||||||
|
void GetPCBGridOffsets( double &aXOffset, double &aYOffset );
|
||||||
|
};
|
|
@ -0,0 +1,216 @@
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// C++ code generated with wxFormBuilder (version Jul 11 2018)
|
||||||
|
// http://www.wxformbuilder.org/
|
||||||
|
//
|
||||||
|
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "pcb_layer_box_selector.h"
|
||||||
|
|
||||||
|
#include "dialog_import_gfx_base.h"
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
DIALOG_IMPORT_GFX_BASE::DIALOG_IMPORT_GFX_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
|
||||||
|
{
|
||||||
|
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
|
||||||
|
|
||||||
|
wxBoxSizer* bSizerMain;
|
||||||
|
bSizerMain = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
|
wxBoxSizer* bSizerFile;
|
||||||
|
bSizerFile = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
|
||||||
|
m_staticText37 = new wxStaticText( this, wxID_ANY, _("File:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
m_staticText37->Wrap( -1 );
|
||||||
|
bSizerFile->Add( m_staticText37, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||||
|
|
||||||
|
m_textCtrlFileName = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
m_textCtrlFileName->SetMinSize( wxSize( 300,-1 ) );
|
||||||
|
|
||||||
|
bSizerFile->Add( m_textCtrlFileName, 1, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxTOP, 5 );
|
||||||
|
|
||||||
|
m_buttonBrowse = new wxButton( this, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
bSizerFile->Add( m_buttonBrowse, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxTOP, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
bSizerMain->Add( bSizerFile, 0, wxALL|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
wxBoxSizer* bSizer10;
|
||||||
|
bSizer10 = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
|
wxBoxSizer* bSizer5;
|
||||||
|
bSizer5 = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
|
||||||
|
m_staticText3 = new wxStaticText( this, wxID_ANY, _("Units:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
m_staticText3->Wrap( -1 );
|
||||||
|
bSizer5->Add( m_staticText3, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||||
|
|
||||||
|
wxString m_PCBGridUnitsChoices[] = { _("mm"), _("inch") };
|
||||||
|
int m_PCBGridUnitsNChoices = sizeof( m_PCBGridUnitsChoices ) / sizeof( wxString );
|
||||||
|
m_PCBGridUnits = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_PCBGridUnitsNChoices, m_PCBGridUnitsChoices, 0 );
|
||||||
|
m_PCBGridUnits->SetSelection( 0 );
|
||||||
|
m_PCBGridUnits->SetToolTip( _("Select PCB grid units") );
|
||||||
|
|
||||||
|
bSizer5->Add( m_PCBGridUnits, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
bSizer10->Add( bSizer5, 0, wxALL|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
wxBoxSizer* bSizer3;
|
||||||
|
bSizer3 = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
|
||||||
|
wxString m_rbOffsetOptionChoices[] = { _("Center of page"), _("Upper left corner of page"), _("Center left side of page"), _("Lower left corner of page"), _("User defined position") };
|
||||||
|
int m_rbOffsetOptionNChoices = sizeof( m_rbOffsetOptionChoices ) / sizeof( wxString );
|
||||||
|
m_rbOffsetOption = new wxRadioBox( this, wxID_ORIGIN_SELECT, _("Place origin (0,0) point:"), wxDefaultPosition, wxDefaultSize, m_rbOffsetOptionNChoices, m_rbOffsetOptionChoices, 1, wxRA_SPECIFY_COLS );
|
||||||
|
m_rbOffsetOption->SetSelection( 0 );
|
||||||
|
bSizer3->Add( m_rbOffsetOption, 0, wxALL|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
wxBoxSizer* bSizer4;
|
||||||
|
bSizer4 = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
|
wxBoxSizer* bSizer6;
|
||||||
|
bSizer6 = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
|
||||||
|
m_staticText4 = new wxStaticText( this, wxID_ANY, _("X Position:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
m_staticText4->Wrap( -1 );
|
||||||
|
bSizer6->Add( m_staticText4, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||||
|
|
||||||
|
m_PCBXCoord = new wxTextCtrl( this, wxID_ANY, _("0.0"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
#ifdef __WXGTK__
|
||||||
|
if ( !m_PCBXCoord->HasFlag( wxTE_MULTILINE ) )
|
||||||
|
{
|
||||||
|
m_PCBXCoord->SetMaxLength( 10 );
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
m_PCBXCoord->SetMaxLength( 10 );
|
||||||
|
#endif
|
||||||
|
m_PCBXCoord->SetToolTip( _("DXF origin on PCB Grid, X Coordinate") );
|
||||||
|
|
||||||
|
bSizer6->Add( m_PCBXCoord, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
bSizer4->Add( bSizer6, 1, wxEXPAND, 5 );
|
||||||
|
|
||||||
|
wxBoxSizer* bSizer7;
|
||||||
|
bSizer7 = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
|
||||||
|
m_staticText5 = new wxStaticText( this, wxID_ANY, _("Y Position:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
m_staticText5->Wrap( -1 );
|
||||||
|
bSizer7->Add( m_staticText5, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||||
|
|
||||||
|
m_PCBYCoord = new wxTextCtrl( this, wxID_ANY, _("0.0"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
#ifdef __WXGTK__
|
||||||
|
if ( !m_PCBYCoord->HasFlag( wxTE_MULTILINE ) )
|
||||||
|
{
|
||||||
|
m_PCBYCoord->SetMaxLength( 10 );
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
m_PCBYCoord->SetMaxLength( 10 );
|
||||||
|
#endif
|
||||||
|
m_PCBYCoord->SetToolTip( _("DXF origin on PCB Grid, Y Coordinate") );
|
||||||
|
|
||||||
|
bSizer7->Add( m_PCBYCoord, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
bSizer4->Add( bSizer7, 1, wxEXPAND, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
bSizer3->Add( bSizer4, 1, wxALIGN_CENTER_VERTICAL, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
bSizer10->Add( bSizer3, 0, wxALL|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
wxBoxSizer* bSizer101;
|
||||||
|
bSizer101 = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
|
wxBoxSizer* bSizer11;
|
||||||
|
bSizer11 = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
|
||||||
|
m_staticText6 = new wxStaticText( this, wxID_ANY, _("Height:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
m_staticText6->Wrap( -1 );
|
||||||
|
bSizer11->Add( m_staticText6, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||||
|
|
||||||
|
m_tcHeight = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
bSizer11->Add( m_tcHeight, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||||
|
|
||||||
|
m_staticText7 = new wxStaticText( this, wxID_ANY, _("Width:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
m_staticText7->Wrap( -1 );
|
||||||
|
bSizer11->Add( m_staticText7, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||||
|
|
||||||
|
m_tcWidth = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
m_tcWidth->Enable( false );
|
||||||
|
|
||||||
|
bSizer11->Add( m_tcWidth, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
bSizer101->Add( bSizer11, 0, wxALL|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
wxBoxSizer* bSizer15;
|
||||||
|
bSizer15 = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
|
m_cbKeepAspectRatio = new wxCheckBox( this, wxID_ANY, _("Keep aspect ratio"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
m_cbKeepAspectRatio->SetValue(true);
|
||||||
|
bSizer15->Add( m_cbKeepAspectRatio, 0, wxALL, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
bSizer101->Add( bSizer15, 0, wxALL|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
bSizer10->Add( bSizer101, 0, wxALL|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
bSizerMain->Add( bSizer10, 1, wxALL|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
wxBoxSizer* bSizer8;
|
||||||
|
bSizer8 = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
|
||||||
|
m_staticTextBrdlayer = new wxStaticText( this, wxID_ANY, _("Layer:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||||
|
m_staticTextBrdlayer->Wrap( -1 );
|
||||||
|
bSizer8->Add( m_staticTextBrdlayer, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT|wxTOP, 5 );
|
||||||
|
|
||||||
|
m_SelLayerBox = new PCB_LAYER_BOX_SELECTOR( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 );
|
||||||
|
bSizer8->Add( m_SelLayerBox, 1, wxALL|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
bSizerMain->Add( bSizer8, 0, wxALL|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
m_staticline8 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||||
|
bSizerMain->Add( m_staticline8, 0, wxALL|wxEXPAND, 5 );
|
||||||
|
|
||||||
|
m_sdbSizer1 = new wxStdDialogButtonSizer();
|
||||||
|
m_sdbSizer1OK = new wxButton( this, wxID_OK );
|
||||||
|
m_sdbSizer1->AddButton( m_sdbSizer1OK );
|
||||||
|
m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL );
|
||||||
|
m_sdbSizer1->AddButton( m_sdbSizer1Cancel );
|
||||||
|
m_sdbSizer1->Realize();
|
||||||
|
|
||||||
|
bSizerMain->Add( m_sdbSizer1, 0, wxALIGN_RIGHT|wxBOTTOM|wxLEFT|wxRIGHT, 5 );
|
||||||
|
|
||||||
|
|
||||||
|
this->SetSizer( bSizerMain );
|
||||||
|
this->Layout();
|
||||||
|
bSizerMain->Fit( this );
|
||||||
|
|
||||||
|
this->Centre( wxBOTH );
|
||||||
|
|
||||||
|
// Connect Events
|
||||||
|
m_buttonBrowse->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_GFX_BASE::OnBrowseFiles ), NULL, this );
|
||||||
|
m_rbOffsetOption->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_IMPORT_GFX_BASE::OriginOptionOnUpdateUI ), NULL, this );
|
||||||
|
m_tcHeight->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_IMPORT_GFX_BASE::onChangeHeight ), NULL, this );
|
||||||
|
m_cbKeepAspectRatio->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_IMPORT_GFX_BASE::onKeepAspectRatioUpdate ), NULL, this );
|
||||||
|
m_sdbSizer1Cancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_GFX_BASE::OnCancelClick ), NULL, this );
|
||||||
|
m_sdbSizer1OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_GFX_BASE::OnOKClick ), NULL, this );
|
||||||
|
}
|
||||||
|
|
||||||
|
DIALOG_IMPORT_GFX_BASE::~DIALOG_IMPORT_GFX_BASE()
|
||||||
|
{
|
||||||
|
// Disconnect Events
|
||||||
|
m_buttonBrowse->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_GFX_BASE::OnBrowseFiles ), NULL, this );
|
||||||
|
m_rbOffsetOption->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_IMPORT_GFX_BASE::OriginOptionOnUpdateUI ), NULL, this );
|
||||||
|
m_tcHeight->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_IMPORT_GFX_BASE::onChangeHeight ), NULL, this );
|
||||||
|
m_cbKeepAspectRatio->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( DIALOG_IMPORT_GFX_BASE::onKeepAspectRatioUpdate ), NULL, this );
|
||||||
|
m_sdbSizer1Cancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_GFX_BASE::OnCancelClick ), NULL, this );
|
||||||
|
m_sdbSizer1OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMPORT_GFX_BASE::OnOKClick ), NULL, this );
|
||||||
|
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,87 @@
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// C++ code generated with wxFormBuilder (version Jul 11 2018)
|
||||||
|
// http://www.wxformbuilder.org/
|
||||||
|
//
|
||||||
|
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef __DIALOG_IMPORT_GFX_BASE_H__
|
||||||
|
#define __DIALOG_IMPORT_GFX_BASE_H__
|
||||||
|
|
||||||
|
#include <wx/artprov.h>
|
||||||
|
#include <wx/xrc/xmlres.h>
|
||||||
|
#include <wx/intl.h>
|
||||||
|
class PCB_LAYER_BOX_SELECTOR;
|
||||||
|
|
||||||
|
#include "dialog_shim.h"
|
||||||
|
#include <wx/string.h>
|
||||||
|
#include <wx/stattext.h>
|
||||||
|
#include <wx/gdicmn.h>
|
||||||
|
#include <wx/font.h>
|
||||||
|
#include <wx/colour.h>
|
||||||
|
#include <wx/settings.h>
|
||||||
|
#include <wx/textctrl.h>
|
||||||
|
#include <wx/bitmap.h>
|
||||||
|
#include <wx/image.h>
|
||||||
|
#include <wx/icon.h>
|
||||||
|
#include <wx/button.h>
|
||||||
|
#include <wx/sizer.h>
|
||||||
|
#include <wx/choice.h>
|
||||||
|
#include <wx/radiobox.h>
|
||||||
|
#include <wx/valtext.h>
|
||||||
|
#include <wx/checkbox.h>
|
||||||
|
#include <wx/bmpcbox.h>
|
||||||
|
#include <wx/statline.h>
|
||||||
|
#include <wx/dialog.h>
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define wxID_ORIGIN_SELECT 1000
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// Class DIALOG_IMPORT_GFX_BASE
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
class DIALOG_IMPORT_GFX_BASE : public DIALOG_SHIM
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
protected:
|
||||||
|
wxStaticText* m_staticText37;
|
||||||
|
wxTextCtrl* m_textCtrlFileName;
|
||||||
|
wxButton* m_buttonBrowse;
|
||||||
|
wxStaticText* m_staticText3;
|
||||||
|
wxChoice* m_PCBGridUnits;
|
||||||
|
wxRadioBox* m_rbOffsetOption;
|
||||||
|
wxStaticText* m_staticText4;
|
||||||
|
wxTextCtrl* m_PCBXCoord;
|
||||||
|
wxStaticText* m_staticText5;
|
||||||
|
wxTextCtrl* m_PCBYCoord;
|
||||||
|
wxStaticText* m_staticText6;
|
||||||
|
wxTextCtrl* m_tcHeight;
|
||||||
|
wxStaticText* m_staticText7;
|
||||||
|
wxTextCtrl* m_tcWidth;
|
||||||
|
wxCheckBox* m_cbKeepAspectRatio;
|
||||||
|
wxStaticText* m_staticTextBrdlayer;
|
||||||
|
PCB_LAYER_BOX_SELECTOR* m_SelLayerBox;
|
||||||
|
wxStaticLine* m_staticline8;
|
||||||
|
wxStdDialogButtonSizer* m_sdbSizer1;
|
||||||
|
wxButton* m_sdbSizer1OK;
|
||||||
|
wxButton* m_sdbSizer1Cancel;
|
||||||
|
|
||||||
|
// Virtual event handlers, overide them in your derived class
|
||||||
|
virtual void OnBrowseFiles( wxCommandEvent& event ) { event.Skip(); }
|
||||||
|
virtual void OriginOptionOnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); }
|
||||||
|
virtual void onChangeHeight( wxUpdateUIEvent& event ) { event.Skip(); }
|
||||||
|
virtual void onKeepAspectRatioUpdate( wxUpdateUIEvent& event ) { event.Skip(); }
|
||||||
|
virtual void OnCancelClick( wxCommandEvent& event ) { event.Skip(); }
|
||||||
|
virtual void OnOKClick( wxCommandEvent& event ) { event.Skip(); }
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DIALOG_IMPORT_GFX_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Import vector graphics file"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
||||||
|
~DIALOG_IMPORT_GFX_BASE();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__DIALOG_IMPORT_GFX_BASE_H__
|
|
@ -0,0 +1,976 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||||
|
* Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
// The DXF reader lib (libdxfrw) comes from LibreCAD project, a 2D CAD program
|
||||||
|
// libdxfrw can be found on http://sourceforge.net/projects/libdxfrw/
|
||||||
|
// or (latest sources) on
|
||||||
|
// https://github.com/LibreCAD/LibreCAD/tree/master/libraries/libdxfrw/src
|
||||||
|
//
|
||||||
|
// There is no doc to use it, but have a look to
|
||||||
|
// https://github.com/LibreCAD/LibreCAD/blob/master/librecad/src/lib/filters/rs_filterdxf.cpp
|
||||||
|
// and https://github.com/LibreCAD/LibreCAD/blob/master/librecad/src/lib/filters/rs_filterdxf.h
|
||||||
|
// Each time a dxf entity is read, a "call back" fuction is called
|
||||||
|
// like void DXF_IMPORT_PLUGIN::addLine( const DRW_Line& data ) when a line is read.
|
||||||
|
// this function just add the BOARD entity from dxf parameters (start and end point ...)
|
||||||
|
|
||||||
|
|
||||||
|
#include "dxf_import_plugin.h"
|
||||||
|
#include <wx/arrstr.h>
|
||||||
|
#include <wx/regex.h>
|
||||||
|
|
||||||
|
#include <trigo.h>
|
||||||
|
#include <macros.h>
|
||||||
|
#include <class_board.h>
|
||||||
|
#include <class_drawsegment.h>
|
||||||
|
#include <class_edge_mod.h>
|
||||||
|
#include <class_pcb_text.h>
|
||||||
|
#include <class_text_mod.h>
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
// minimum bulge value before resorting to a line segment;
|
||||||
|
// the value 0.0218 is equivalent to about 5 degrees arc,
|
||||||
|
#define MIN_BULGE 0.0218
|
||||||
|
|
||||||
|
DXF_IMPORT_PLUGIN::DXF_IMPORT_PLUGIN() : DL_CreationAdapter()
|
||||||
|
{
|
||||||
|
m_xOffset = 0.0; // X coord offset for conversion (in mm)
|
||||||
|
m_yOffset = 0.0; // Y coord offset for conversion (in mm)
|
||||||
|
m_DXF2mm = 1.0; // The scale factor to convert DXF units to mm
|
||||||
|
m_version = 0; // the dxf version, not yet used
|
||||||
|
m_defaultThickness = 0.2; // default thickness (in mm)
|
||||||
|
m_brdLayer = Dwgs_User; // The default import layer
|
||||||
|
m_importAsfootprintGraphicItems = true;
|
||||||
|
m_minX = std::numeric_limits<int>::max();
|
||||||
|
m_maxX = std::numeric_limits<int>::min();
|
||||||
|
m_minY = std::numeric_limits<int>::max();
|
||||||
|
m_maxY = std::numeric_limits<int>::min();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DXF_IMPORT_PLUGIN::~DXF_IMPORT_PLUGIN()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool DXF_IMPORT_PLUGIN::Load( const wxString& aFileName )
|
||||||
|
{
|
||||||
|
//dxfRW dxf( aFileName.ToUTF8() );
|
||||||
|
//return dxf.read( this, true );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool DXF_IMPORT_PLUGIN::Import( float aXScale, float aYScale )
|
||||||
|
{
|
||||||
|
//wxCHECK( m_importer, false );
|
||||||
|
//m_internalImporter.ImportTo( *m_importer );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int DXF_IMPORT_PLUGIN::GetImageWidth() const {
|
||||||
|
return m_maxX - m_minX;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int DXF_IMPORT_PLUGIN::GetImageHeight() const {
|
||||||
|
return m_maxY - m_minY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// coordinate conversions from dxf to internal units
|
||||||
|
int DXF_IMPORT_PLUGIN::mapX( double aDxfCoordX )
|
||||||
|
{
|
||||||
|
return Millimeter2iu( m_xOffset + ( aDxfCoordX * m_DXF2mm ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int DXF_IMPORT_PLUGIN::mapY( double aDxfCoordY )
|
||||||
|
{
|
||||||
|
return Millimeter2iu( m_yOffset - ( aDxfCoordY * m_DXF2mm ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int DXF_IMPORT_PLUGIN::mapDim( double aDxfValue )
|
||||||
|
{
|
||||||
|
return Millimeter2iu( aDxfValue * m_DXF2mm );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int DXF_IMPORT_PLUGIN::mapWidth( double aDxfWidth )
|
||||||
|
{
|
||||||
|
// Always return the default line width
|
||||||
|
#if 0
|
||||||
|
// mapWidth returns the aDxfValue if aDxfWidth > 0 m_defaultThickness
|
||||||
|
if( aDxfWidth > 0.0 )
|
||||||
|
return Millimeter2iu( aDxfWidth * m_DXF2mm );
|
||||||
|
#endif
|
||||||
|
return Millimeter2iu( m_defaultThickness );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DXF_IMPORT_PLUGIN::ImportDxfFile( const wxString& aFile )
|
||||||
|
{
|
||||||
|
LOCALE_IO locale;
|
||||||
|
|
||||||
|
DL_Dxf dxf_reader;
|
||||||
|
std::string filename = TO_UTF8( aFile );
|
||||||
|
bool success = true;
|
||||||
|
|
||||||
|
if( !dxf_reader.in( filename, this ) ) // if file open failed
|
||||||
|
success = false;
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::reportMsg( const char* aMessage )
|
||||||
|
{
|
||||||
|
// Add message to keep trace of not handled dxf entities
|
||||||
|
m_messages += aMessage;
|
||||||
|
m_messages += '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::addSpline( const DL_SplineData& aData )
|
||||||
|
{
|
||||||
|
// Called when starting reading a spline
|
||||||
|
m_curr_entity.Clear();
|
||||||
|
m_curr_entity.m_EntityParseStatus = 1;
|
||||||
|
m_curr_entity.m_EntityFlag = aData.flags;
|
||||||
|
m_curr_entity.m_EntityType = DL_ENTITY_SPLINE;
|
||||||
|
m_curr_entity.m_SplineDegree = aData.degree;
|
||||||
|
m_curr_entity.m_SplineTangentStartX = aData.tangentStartX;
|
||||||
|
m_curr_entity.m_SplineTangentStartY = aData.tangentStartY;
|
||||||
|
m_curr_entity.m_SplineTangentEndX = aData.tangentEndX;
|
||||||
|
m_curr_entity.m_SplineTangentEndY = aData.tangentEndY;
|
||||||
|
m_curr_entity.m_SplineKnotsCount = aData.nKnots;
|
||||||
|
m_curr_entity.m_SplineControlCount = aData.nControl;
|
||||||
|
m_curr_entity.m_SplineFitCount = aData.nFit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::addControlPoint( const DL_ControlPointData& aData )
|
||||||
|
{
|
||||||
|
// Called for every spline control point, when reading a spline entity
|
||||||
|
m_curr_entity.m_SplineControlPointList.push_back( SPLINE_CTRL_POINT( aData.x , aData.y, aData.w ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::addFitPoint( const DL_FitPointData& aData )
|
||||||
|
{
|
||||||
|
// Called for every spline fit point, when reading a spline entity
|
||||||
|
// we store only the X,Y coord values in a wxRealPoint
|
||||||
|
m_curr_entity.m_SplineFitPointList.push_back( wxRealPoint( aData.x, aData.y ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::addKnot( const DL_KnotData& aData)
|
||||||
|
{
|
||||||
|
// Called for every spline knot value, when reading a spline entity
|
||||||
|
m_curr_entity.m_SplineKnotsList.push_back( aData.k );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::addLayer( const DL_LayerData& aData )
|
||||||
|
{
|
||||||
|
// Not yet useful in Pcbnew.
|
||||||
|
#if 0
|
||||||
|
wxString name = wxString::FromUTF8( aData.name.c_str() );
|
||||||
|
wxLogMessage( name );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::addLine( const DL_LineData& aData )
|
||||||
|
{
|
||||||
|
DRAWSEGMENT* segm = ( m_importAsfootprintGraphicItems ) ?
|
||||||
|
static_cast< DRAWSEGMENT* >( new EDGE_MODULE( NULL ) ) : new DRAWSEGMENT;
|
||||||
|
|
||||||
|
segm->SetLayer( ToLAYER_ID( m_brdLayer ) );
|
||||||
|
wxPoint start( mapX( aData.x1 ), mapY( aData.y1 ) );
|
||||||
|
segm->SetStart( start );
|
||||||
|
wxPoint end( mapX( aData.x2 ), mapY( aData.y2 ) );
|
||||||
|
segm->SetEnd( end );
|
||||||
|
segm->SetWidth( mapWidth( attributes.getWidth() ) );
|
||||||
|
m_newItemsList.push_back( segm );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::addPolyline(const DL_PolylineData& aData )
|
||||||
|
{
|
||||||
|
// Convert DXF Polylines into a series of KiCad Lines and Arcs.
|
||||||
|
// A Polyline (as opposed to a LWPolyline) may be a 3D line or
|
||||||
|
// even a 3D Mesh. The only type of Polyline which is guaranteed
|
||||||
|
// to import correctly is a 2D Polyline in X and Y, which is what
|
||||||
|
// we assume of all Polylines. The width used is the width of the Polyline.
|
||||||
|
// per-vertex line widths, if present, are ignored.
|
||||||
|
|
||||||
|
m_curr_entity.Clear();
|
||||||
|
m_curr_entity.m_EntityParseStatus = 1;
|
||||||
|
m_curr_entity.m_EntityFlag = aData.flags;
|
||||||
|
m_curr_entity.m_EntityType = DL_ENTITY_POLYLINE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::addVertex( const DL_VertexData& aData )
|
||||||
|
{
|
||||||
|
if( m_curr_entity.m_EntityParseStatus == 0 )
|
||||||
|
return; // Error
|
||||||
|
|
||||||
|
int lineWidth = mapWidth( attributes.getWidth() );
|
||||||
|
|
||||||
|
const DL_VertexData* vertex = &aData;
|
||||||
|
|
||||||
|
if( m_curr_entity.m_EntityParseStatus == 1 ) // This is the first vertex of an entity
|
||||||
|
{
|
||||||
|
m_curr_entity.m_LastCoordinate.x = m_xOffset + vertex->x * m_DXF2mm;
|
||||||
|
m_curr_entity.m_LastCoordinate.y = m_yOffset - vertex->y * m_DXF2mm;
|
||||||
|
m_curr_entity.m_PolylineStart = m_curr_entity.m_LastCoordinate;
|
||||||
|
m_curr_entity.m_BulgeVertex = vertex->bulge;
|
||||||
|
m_curr_entity.m_EntityParseStatus = 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxRealPoint seg_end( m_xOffset + vertex->x * m_DXF2mm,
|
||||||
|
m_yOffset - vertex->y * m_DXF2mm );
|
||||||
|
|
||||||
|
if( std::abs( m_curr_entity.m_BulgeVertex ) < MIN_BULGE )
|
||||||
|
insertLine( m_curr_entity.m_LastCoordinate, seg_end, lineWidth );
|
||||||
|
else
|
||||||
|
insertArc( m_curr_entity.m_LastCoordinate, seg_end, m_curr_entity.m_BulgeVertex, lineWidth );
|
||||||
|
|
||||||
|
m_curr_entity.m_LastCoordinate = seg_end;
|
||||||
|
m_curr_entity.m_BulgeVertex = vertex->bulge;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::endEntity()
|
||||||
|
{
|
||||||
|
if( m_curr_entity.m_EntityType == DL_ENTITY_POLYLINE ||
|
||||||
|
m_curr_entity.m_EntityType == DL_ENTITY_LWPOLYLINE )
|
||||||
|
{
|
||||||
|
// Polyline flags bit 0 indicates closed (1) or open (0) polyline
|
||||||
|
if( m_curr_entity.m_EntityFlag & 1 )
|
||||||
|
{
|
||||||
|
int lineWidth = mapWidth( attributes.getWidth() );
|
||||||
|
|
||||||
|
if( std::abs( m_curr_entity.m_BulgeVertex ) < MIN_BULGE )
|
||||||
|
insertLine( m_curr_entity.m_LastCoordinate, m_curr_entity.m_PolylineStart, lineWidth );
|
||||||
|
else
|
||||||
|
insertArc( m_curr_entity.m_LastCoordinate, m_curr_entity.m_PolylineStart,
|
||||||
|
m_curr_entity.m_BulgeVertex, lineWidth );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_curr_entity.m_EntityType == DL_ENTITY_SPLINE )
|
||||||
|
{
|
||||||
|
int lineWidth = mapWidth( attributes.getWidth() );
|
||||||
|
insertSpline( lineWidth );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_curr_entity.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::addCircle( const DL_CircleData& aData )
|
||||||
|
{
|
||||||
|
DRAWSEGMENT* segm = ( m_importAsfootprintGraphicItems ) ?
|
||||||
|
static_cast< DRAWSEGMENT* >( new EDGE_MODULE( NULL ) ) : new DRAWSEGMENT;
|
||||||
|
|
||||||
|
segm->SetLayer( ToLAYER_ID( m_brdLayer ) );
|
||||||
|
segm->SetShape( S_CIRCLE );
|
||||||
|
wxPoint center( mapX( aData.cx ), mapY( aData.cy ) );
|
||||||
|
segm->SetCenter( center );
|
||||||
|
wxPoint circle_start( mapX( aData.cx + aData.radius ), mapY( aData.cy ) );
|
||||||
|
segm->SetArcStart( circle_start );
|
||||||
|
segm->SetWidth( mapWidth( attributes.getWidth() ) );
|
||||||
|
m_newItemsList.push_back( segm );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Import Arc entities.
|
||||||
|
*/
|
||||||
|
void DXF_IMPORT_PLUGIN::addArc( const DL_ArcData& aData )
|
||||||
|
{
|
||||||
|
DRAWSEGMENT* segm = ( m_importAsfootprintGraphicItems ) ?
|
||||||
|
static_cast< DRAWSEGMENT* >( new EDGE_MODULE( NULL ) ) : new DRAWSEGMENT;
|
||||||
|
|
||||||
|
segm->SetLayer( ToLAYER_ID( m_brdLayer ) );
|
||||||
|
segm->SetShape( S_ARC );
|
||||||
|
|
||||||
|
// Init arc centre:
|
||||||
|
wxPoint center( mapX( aData.cx ), mapY( aData.cy ) );
|
||||||
|
segm->SetCenter( center );
|
||||||
|
|
||||||
|
// Init arc start point
|
||||||
|
double arcStartx = aData.radius;
|
||||||
|
double arcStarty = 0;
|
||||||
|
|
||||||
|
// aData.anglex is in degrees. Our internal units are 0.1 degree
|
||||||
|
// so convert DXF angles to our units
|
||||||
|
#define DXF2ANGLEUI 10
|
||||||
|
double startangle = aData.angle1 * DXF2ANGLEUI;
|
||||||
|
double endangle = aData.angle2 * DXF2ANGLEUI;
|
||||||
|
|
||||||
|
RotatePoint( &arcStartx, &arcStarty, -startangle );
|
||||||
|
wxPoint arcStart( mapX( arcStartx + aData.cx ),
|
||||||
|
mapY( arcStarty + aData.cy ) );
|
||||||
|
segm->SetArcStart( arcStart );
|
||||||
|
|
||||||
|
// calculate arc angle (arcs are CCW, and should be < 0 in Pcbnew)
|
||||||
|
double angle = -( endangle - startangle );
|
||||||
|
|
||||||
|
if( angle > 0.0 )
|
||||||
|
angle -= 3600.0;
|
||||||
|
|
||||||
|
segm->SetAngle( angle );
|
||||||
|
|
||||||
|
segm->SetWidth( mapWidth( attributes.getWidth() ) );
|
||||||
|
m_newItemsList.push_back( segm );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::addText( const DL_TextData& aData )
|
||||||
|
{
|
||||||
|
BOARD_ITEM* brdItem;
|
||||||
|
EDA_TEXT* textItem;
|
||||||
|
|
||||||
|
if( m_importAsfootprintGraphicItems )
|
||||||
|
{
|
||||||
|
TEXTE_MODULE* modText = new TEXTE_MODULE( NULL );
|
||||||
|
brdItem = static_cast< BOARD_ITEM* >( modText );
|
||||||
|
textItem = static_cast< EDA_TEXT* >( modText );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TEXTE_PCB* pcbText = new TEXTE_PCB( NULL );
|
||||||
|
brdItem = static_cast< BOARD_ITEM* >( pcbText );
|
||||||
|
textItem = static_cast< EDA_TEXT* >( pcbText );
|
||||||
|
}
|
||||||
|
|
||||||
|
brdItem->SetLayer( ToLAYER_ID( m_brdLayer ) );
|
||||||
|
|
||||||
|
wxPoint refPoint( mapX( aData.ipx ), mapY( aData.ipy ) );
|
||||||
|
wxPoint secPoint( mapX( aData.apx ), mapY( aData.apy ) );
|
||||||
|
|
||||||
|
if( aData.vJustification != 0 || aData.hJustification != 0 || aData.hJustification == 4 )
|
||||||
|
{
|
||||||
|
if( aData.hJustification != 3 && aData.hJustification != 5 )
|
||||||
|
{
|
||||||
|
wxPoint tmp = secPoint;
|
||||||
|
secPoint = refPoint;
|
||||||
|
refPoint = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( aData.vJustification )
|
||||||
|
{
|
||||||
|
case 0: //DRW_Text::VBaseLine:
|
||||||
|
textItem->SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: //DRW_Text::VBottom:
|
||||||
|
textItem->SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: //DRW_Text::VMiddle:
|
||||||
|
textItem->SetVertJustify( GR_TEXT_VJUSTIFY_CENTER );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: //DRW_Text::VTop:
|
||||||
|
textItem->SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( aData.hJustification )
|
||||||
|
{
|
||||||
|
case 0: //DRW_Text::HLeft:
|
||||||
|
textItem->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: //DRW_Text::HCenter:
|
||||||
|
textItem->SetHorizJustify( GR_TEXT_HJUSTIFY_CENTER );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: //DRW_Text::HRight:
|
||||||
|
textItem->SetHorizJustify( GR_TEXT_HJUSTIFY_RIGHT );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: //DRW_Text::HAligned:
|
||||||
|
// no equivalent options in text pcb.
|
||||||
|
textItem->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: //DRW_Text::HMiddle:
|
||||||
|
// no equivalent options in text pcb.
|
||||||
|
textItem->SetHorizJustify( GR_TEXT_HJUSTIFY_CENTER );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: //DRW_Text::HFit:
|
||||||
|
// no equivalent options in text pcb.
|
||||||
|
textItem->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
wxString sty = wxString::FromUTF8( aData.style.c_str() );
|
||||||
|
sty = sty.ToLower();
|
||||||
|
|
||||||
|
if( aData.textgen == 2 )
|
||||||
|
{
|
||||||
|
// Text dir = left to right;
|
||||||
|
} else if( aData.textgen == 4 )
|
||||||
|
{
|
||||||
|
// Text dir = top to bottom;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wxString text = toNativeString( wxString::FromUTF8( aData.text.c_str() ) );
|
||||||
|
|
||||||
|
textItem->SetTextPos( refPoint );
|
||||||
|
textItem->SetTextAngle( aData.angle * 10 );
|
||||||
|
|
||||||
|
// The 0.8 factor gives a better height/width ratio with our font
|
||||||
|
textItem->SetTextWidth( mapDim( aData.height * 0.8 ) );
|
||||||
|
textItem->SetTextHeight( mapDim( aData.height ) );
|
||||||
|
textItem->SetThickness( mapWidth( aData.height * DEFAULT_TEXT_WIDTH ) ); // Gives a reasonable text thickness
|
||||||
|
textItem->SetText( text );
|
||||||
|
|
||||||
|
m_newItemsList.push_back( static_cast< BOARD_ITEM* >( brdItem ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::addMText( const DL_MTextData& aData )
|
||||||
|
{
|
||||||
|
wxString text = toNativeString( wxString::FromUTF8( aData.text.c_str() ) );
|
||||||
|
wxString attrib, tmp;
|
||||||
|
|
||||||
|
/* Some texts start by '\' and have formating chars (font name, font option...)
|
||||||
|
* ending with ';'
|
||||||
|
* Here are some mtext formatting codes:
|
||||||
|
* Format code Purpose
|
||||||
|
* \0...\o Turns overline on and off
|
||||||
|
* \L...\l Turns underline on and off
|
||||||
|
* \~ Inserts a nonbreaking space
|
||||||
|
\\ Inserts a backslash
|
||||||
|
\\\{...\} Inserts an opening and closing brace
|
||||||
|
\\ \File name; Changes to the specified font file
|
||||||
|
\\ \Hvalue; Changes to the text height specified in drawing units
|
||||||
|
\\ \Hvaluex; Changes the text height to a multiple of the current text height
|
||||||
|
\\ \S...^...; Stacks the subsequent text at the \, #, or ^ symbol
|
||||||
|
\\ \Tvalue; Adjusts the space between characters, from.75 to 4 times
|
||||||
|
\\ \Qangle; Changes obliquing angle
|
||||||
|
\\ \Wvalue; Changes width factor to produce wide text
|
||||||
|
\\ \A Sets the alignment value; valid values: 0, 1, 2 (bottom, center, top) while( text.StartsWith( wxT("\\") ) )
|
||||||
|
*/
|
||||||
|
while( text.StartsWith( wxT( "\\" ) ) )
|
||||||
|
{
|
||||||
|
attrib << text.BeforeFirst( ';' );
|
||||||
|
tmp = text.AfterFirst( ';' );
|
||||||
|
text = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOARD_ITEM* brdItem;
|
||||||
|
EDA_TEXT* textItem;
|
||||||
|
|
||||||
|
if( m_importAsfootprintGraphicItems )
|
||||||
|
{
|
||||||
|
TEXTE_MODULE* modText = new TEXTE_MODULE( NULL );
|
||||||
|
brdItem = static_cast< BOARD_ITEM* >( modText );
|
||||||
|
textItem = static_cast< EDA_TEXT* >( modText );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TEXTE_PCB* pcbText = new TEXTE_PCB( NULL );
|
||||||
|
brdItem = static_cast< BOARD_ITEM* >( pcbText );
|
||||||
|
textItem = static_cast< EDA_TEXT* >( pcbText );
|
||||||
|
}
|
||||||
|
|
||||||
|
brdItem->SetLayer( ToLAYER_ID( m_brdLayer ) );
|
||||||
|
wxPoint textpos( mapX( aData.ipx ), mapY( aData.ipy ) );
|
||||||
|
|
||||||
|
textItem->SetTextPos( textpos );
|
||||||
|
textItem->SetTextAngle( aData.angle * 10 );
|
||||||
|
|
||||||
|
// The 0.8 factor gives a better height/width ratio with our font
|
||||||
|
textItem->SetTextWidth( mapDim( aData.height * 0.8 ) );
|
||||||
|
textItem->SetTextHeight( mapDim( aData.height ) );
|
||||||
|
textItem->SetThickness( mapWidth( aData.height * DEFAULT_TEXT_WIDTH ) ); // Gives a reasonable text thickness
|
||||||
|
textItem->SetText( text );
|
||||||
|
|
||||||
|
// Initialize text justifications:
|
||||||
|
if( aData.attachmentPoint <= 3 )
|
||||||
|
{
|
||||||
|
textItem->SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
|
||||||
|
}
|
||||||
|
else if( aData.attachmentPoint <= 6 )
|
||||||
|
{
|
||||||
|
textItem->SetVertJustify( GR_TEXT_VJUSTIFY_CENTER );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
textItem->SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aData.attachmentPoint % 3 == 1 )
|
||||||
|
{
|
||||||
|
textItem->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
|
||||||
|
}
|
||||||
|
else if( aData.attachmentPoint % 3 == 2 )
|
||||||
|
{
|
||||||
|
textItem->SetHorizJustify( GR_TEXT_HJUSTIFY_CENTER );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
textItem->SetHorizJustify( GR_TEXT_HJUSTIFY_RIGHT );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 // These setting have no meaning in Pcbnew
|
||||||
|
if( data.alignH == 1 )
|
||||||
|
{
|
||||||
|
// Text is left to right;
|
||||||
|
}
|
||||||
|
else if( data.alignH == 3 )
|
||||||
|
{
|
||||||
|
// Text is top to bottom;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// use ByStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aData.alignV == 1 )
|
||||||
|
{
|
||||||
|
// use AtLeast;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// useExact;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_newItemsList.push_back( static_cast< BOARD_ITEM* >( brdItem ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::setVariableInt( const std::string& key, int value, int code )
|
||||||
|
{
|
||||||
|
// Called for every int variable in the DXF file (e.g. "$INSUNITS").
|
||||||
|
|
||||||
|
if( key == "$DWGCODEPAGE" )
|
||||||
|
{
|
||||||
|
m_codePage = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( key == "$INSUNITS" ) // Drawing units
|
||||||
|
{
|
||||||
|
switch( value )
|
||||||
|
{
|
||||||
|
case 1: // inches
|
||||||
|
m_DXF2mm = 25.4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // feet
|
||||||
|
m_DXF2mm = 304.8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: // mm
|
||||||
|
m_DXF2mm = 1.0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: // centimeters
|
||||||
|
m_DXF2mm = 10.0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6: // meters
|
||||||
|
m_DXF2mm = 1000.0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8: // microinches
|
||||||
|
m_DXF2mm = 2.54e-5;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 9: // mils
|
||||||
|
m_DXF2mm = 0.0254;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 10: // yards
|
||||||
|
m_DXF2mm = 914.4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 11: // Angstroms
|
||||||
|
m_DXF2mm = 1.0e-7;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 12: // nanometers
|
||||||
|
m_DXF2mm = 1.0e-6;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 13: // micrometers
|
||||||
|
m_DXF2mm = 1.0e-3;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 14: // decimeters
|
||||||
|
m_DXF2mm = 100.0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// use the default of 1.0 for:
|
||||||
|
// 0: Unspecified Units
|
||||||
|
// 3: miles
|
||||||
|
// 7: kilometers
|
||||||
|
// 15: decameters
|
||||||
|
// 16: hectometers
|
||||||
|
// 17: gigameters
|
||||||
|
// 18: AU
|
||||||
|
// 19: lightyears
|
||||||
|
// 20: parsecs
|
||||||
|
m_DXF2mm = 1.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::setVariableString( const std::string& key, const std::string& value,
|
||||||
|
int code )
|
||||||
|
{
|
||||||
|
// Called for every string variable in the DXF file (e.g. "$ACADVER").
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString DXF_IMPORT_PLUGIN::toDxfString( const wxString& aStr )
|
||||||
|
{
|
||||||
|
wxString res;
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
|
for( unsigned i = 0; i<aStr.length(); ++i )
|
||||||
|
{
|
||||||
|
int c = aStr[i];
|
||||||
|
|
||||||
|
if( c > 175 || c < 11 )
|
||||||
|
{
|
||||||
|
res.append( aStr.Mid( j, i - j ) );
|
||||||
|
j = i;
|
||||||
|
|
||||||
|
switch( c )
|
||||||
|
{
|
||||||
|
case 0x0A:
|
||||||
|
res += wxT( "\\P" );
|
||||||
|
break;
|
||||||
|
|
||||||
|
// diameter:
|
||||||
|
#ifdef __WINDOWS_
|
||||||
|
// windows, as always, is special.
|
||||||
|
case 0x00D8:
|
||||||
|
#else
|
||||||
|
case 0x2205:
|
||||||
|
#endif
|
||||||
|
res += wxT( "%%C" );
|
||||||
|
break;
|
||||||
|
|
||||||
|
// degree:
|
||||||
|
case 0x00B0:
|
||||||
|
res += wxT( "%%D" );
|
||||||
|
break;
|
||||||
|
|
||||||
|
// plus/minus
|
||||||
|
case 0x00B1:
|
||||||
|
res += wxT( "%%P" );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
j--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res.append( aStr.Mid( j ) );
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString DXF_IMPORT_PLUGIN::toNativeString( const wxString& aData )
|
||||||
|
{
|
||||||
|
wxString res;
|
||||||
|
|
||||||
|
// Ignore font tags:
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
|
for( unsigned i = 0; i < aData.length(); ++i )
|
||||||
|
{
|
||||||
|
if( aData[ i ] == 0x7B ) // is '{' ?
|
||||||
|
{
|
||||||
|
if( aData[ i + 1 ] == 0x5c && aData[ i + 2 ] == 0x66 ) // is "\f" ?
|
||||||
|
{
|
||||||
|
// found font tag, append parsed part
|
||||||
|
res.append( aData.Mid( j, i - j ) );
|
||||||
|
|
||||||
|
// skip to ';'
|
||||||
|
for( unsigned k = i + 3; k < aData.length(); ++k )
|
||||||
|
{
|
||||||
|
if( aData[ k ] == 0x3B )
|
||||||
|
{
|
||||||
|
i = j = ++k;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add to '}'
|
||||||
|
for( unsigned k = i; k < aData.length(); ++k )
|
||||||
|
{
|
||||||
|
if( aData[ k ] == 0x7D )
|
||||||
|
{
|
||||||
|
res.append( aData.Mid( i, k - i ) );
|
||||||
|
i = j = ++k;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res.append( aData.Mid( j ) );
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
wxRegEx regexp;
|
||||||
|
// Line feed:
|
||||||
|
regexp.Compile( wxT( "\\\\P" ) );
|
||||||
|
regexp.Replace( &res, wxT( "\n" ) );
|
||||||
|
|
||||||
|
// Space:
|
||||||
|
regexp.Compile( wxT( "\\\\~" ) );
|
||||||
|
regexp.Replace( &res, wxT( " " ) );
|
||||||
|
|
||||||
|
// diameter:
|
||||||
|
regexp.Compile( wxT( "%%[cC]" ) );
|
||||||
|
#ifdef __WINDOWS__
|
||||||
|
// windows, as always, is special.
|
||||||
|
regexp.Replace( &res, wxChar( 0xD8 ) );
|
||||||
|
#else
|
||||||
|
// Empty_set, diameter is 0x2300
|
||||||
|
regexp.Replace( &res, wxChar( 0x2205 ) );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// degree:
|
||||||
|
regexp.Compile( wxT( "%%[dD]" ) );
|
||||||
|
regexp.Replace( &res, wxChar( 0x00B0 ) );
|
||||||
|
// plus/minus
|
||||||
|
regexp.Compile( wxT( "%%[pP]" ) );
|
||||||
|
regexp.Replace( &res, wxChar( 0x00B1 ) );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::addTextStyle( const DL_StyleData& aData )
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::insertLine( const wxRealPoint& aSegStart,
|
||||||
|
const wxRealPoint& aSegEnd, int aWidth )
|
||||||
|
{
|
||||||
|
DRAWSEGMENT* segm = ( m_importAsfootprintGraphicItems ) ?
|
||||||
|
static_cast< DRAWSEGMENT* >( new EDGE_MODULE( NULL ) ) : new DRAWSEGMENT;
|
||||||
|
wxPoint segment_startpoint( Millimeter2iu( aSegStart.x ), Millimeter2iu( aSegStart.y ) );
|
||||||
|
wxPoint segment_endpoint( Millimeter2iu( aSegEnd.x ), Millimeter2iu( aSegEnd.y ) );
|
||||||
|
|
||||||
|
segm->SetLayer( ToLAYER_ID( m_brdLayer ) );
|
||||||
|
segm->SetStart( segment_startpoint );
|
||||||
|
segm->SetEnd( segment_endpoint );
|
||||||
|
segm->SetWidth( aWidth );
|
||||||
|
|
||||||
|
m_newItemsList.push_back( segm );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::insertArc( const wxRealPoint& aSegStart, const wxRealPoint& aSegEnd,
|
||||||
|
double aBulge, int aWidth )
|
||||||
|
{
|
||||||
|
DRAWSEGMENT* segm = ( m_importAsfootprintGraphicItems ) ?
|
||||||
|
static_cast< DRAWSEGMENT* >( new EDGE_MODULE( NULL ) ) : new DRAWSEGMENT;
|
||||||
|
|
||||||
|
wxPoint segment_startpoint( Millimeter2iu( aSegStart.x ), Millimeter2iu( aSegStart.y ) );
|
||||||
|
wxPoint segment_endpoint( Millimeter2iu( aSegEnd.x ), Millimeter2iu( aSegEnd.y ) );
|
||||||
|
|
||||||
|
// ensure aBulge represents an angle from +/- ( 0 .. approx 359.8 deg )
|
||||||
|
if( aBulge < -2000.0 )
|
||||||
|
aBulge = -2000.0;
|
||||||
|
else if( aBulge > 2000.0 )
|
||||||
|
aBulge = 2000.0;
|
||||||
|
|
||||||
|
double ang = 4.0 * atan( aBulge );
|
||||||
|
|
||||||
|
// reflect the Y values to put everything in a RHCS
|
||||||
|
wxRealPoint sp( aSegStart.x, -aSegStart.y );
|
||||||
|
wxRealPoint ep( aSegEnd.x, -aSegEnd.y );
|
||||||
|
// angle from end->start
|
||||||
|
double offAng = atan2( ep.y - sp.y, ep.x - sp.x );
|
||||||
|
// length of subtended segment = 1/2 distance between the 2 points
|
||||||
|
double d = 0.5 * sqrt( (sp.x - ep.x) * (sp.x - ep.x) + (sp.y - ep.y) * (sp.y - ep.y) );
|
||||||
|
// midpoint of the subtended segment
|
||||||
|
double xm = ( sp.x + ep.x ) * 0.5;
|
||||||
|
double ym = ( sp.y + ep.y ) * 0.5;
|
||||||
|
double radius = d / sin( ang * 0.5 );
|
||||||
|
|
||||||
|
if( radius < 0.0 )
|
||||||
|
radius = -radius;
|
||||||
|
|
||||||
|
// calculate the height of the triangle with base d and hypotenuse r
|
||||||
|
double dh2 = radius * radius - d * d;
|
||||||
|
|
||||||
|
// this should only ever happen due to rounding errors when r == d
|
||||||
|
if( dh2 < 0.0 )
|
||||||
|
dh2 = 0.0;
|
||||||
|
|
||||||
|
double h = sqrt( dh2 );
|
||||||
|
|
||||||
|
if( ang < 0.0 )
|
||||||
|
offAng -= M_PI_2;
|
||||||
|
else
|
||||||
|
offAng += M_PI_2;
|
||||||
|
|
||||||
|
// for angles greater than 180 deg we need to flip the
|
||||||
|
// direction in which the arc center is found relative
|
||||||
|
// to the midpoint of the subtended segment.
|
||||||
|
if( ang < -M_PI )
|
||||||
|
offAng += M_PI;
|
||||||
|
else if( ang > M_PI )
|
||||||
|
offAng -= M_PI;
|
||||||
|
|
||||||
|
// center point
|
||||||
|
double cx = h * cos( offAng ) + xm;
|
||||||
|
double cy = h * sin( offAng ) + ym;
|
||||||
|
|
||||||
|
segm->SetLayer( ToLAYER_ID( m_brdLayer ) );
|
||||||
|
segm->SetShape( S_ARC );
|
||||||
|
segm->SetCenter( wxPoint( Millimeter2iu( cx ), Millimeter2iu( -cy ) ) );
|
||||||
|
|
||||||
|
if( ang < 0.0 )
|
||||||
|
{
|
||||||
|
segm->SetArcStart( wxPoint( Millimeter2iu( ep.x ), Millimeter2iu( -ep.y ) ) );
|
||||||
|
segm->SetAngle( RAD2DECIDEG( ang ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
segm->SetArcStart( wxPoint( Millimeter2iu( sp.x ), Millimeter2iu( -sp.y ) ) );
|
||||||
|
segm->SetAngle( RAD2DECIDEG( -ang ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
segm->SetWidth( aWidth );
|
||||||
|
|
||||||
|
m_newItemsList.push_back( segm );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include "tinyspline_lib/tinysplinecpp.h"
|
||||||
|
|
||||||
|
void DXF_IMPORT_PLUGIN::insertSpline( int aWidth )
|
||||||
|
{
|
||||||
|
#if 0 // Debug only
|
||||||
|
wxLogMessage("spl deg %d kn %d ctr %d fit %d",
|
||||||
|
m_curr_entity.m_SplineDegree,
|
||||||
|
m_curr_entity.m_SplineKnotsList.size(),
|
||||||
|
m_curr_entity.m_SplineControlPointList.size(),
|
||||||
|
m_curr_entity.m_SplineFitPointList.size() );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Very basic conversion to segments
|
||||||
|
unsigned imax = m_curr_entity.m_SplineControlPointList.size();
|
||||||
|
|
||||||
|
if( imax < 2 ) // malformed spline
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if 0 // set to 1 to approximate the spline by segments between 2 control points
|
||||||
|
wxPoint startpoint( mapX( m_curr_entity.m_SplineControlPointList[0].m_x ),
|
||||||
|
mapY( m_curr_entity.m_SplineControlPointList[0].m_y ) );
|
||||||
|
|
||||||
|
for( unsigned int ii = 1; ii < imax; ++ii )
|
||||||
|
{
|
||||||
|
wxPoint endpoint( mapX( m_curr_entity.m_SplineControlPointList[ii].m_x ),
|
||||||
|
mapY( m_curr_entity.m_SplineControlPointList[ii].m_y ) );
|
||||||
|
|
||||||
|
if( startpoint != endpoint )
|
||||||
|
{
|
||||||
|
DRAWSEGMENT* segm = ( m_importAsfootprintGraphicItems ) ?
|
||||||
|
static_cast< DRAWSEGMENT* >( new EDGE_MODULE( NULL ) ) :
|
||||||
|
new DRAWSEGMENT;
|
||||||
|
segm->SetLayer( ToLAYER_ID( m_brdLayer ) );
|
||||||
|
segm->SetStart( startpoint );
|
||||||
|
segm->SetEnd( endpoint );
|
||||||
|
segm->SetWidth( aWidth );
|
||||||
|
m_newItemsList.push_back( segm );
|
||||||
|
startpoint = endpoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else // Use bezier curves, supported by pcbnew, to approximate the spline
|
||||||
|
tinyspline::BSpline dxfspline( m_curr_entity.m_SplineControlPointList.size(),
|
||||||
|
/* coord dim */ 2, m_curr_entity.m_SplineDegree );
|
||||||
|
std::vector<double> ctrlp;
|
||||||
|
|
||||||
|
for( unsigned ii = 0; ii < imax; ++ii )
|
||||||
|
{
|
||||||
|
ctrlp.push_back( m_curr_entity.m_SplineControlPointList[ii].m_x );
|
||||||
|
ctrlp.push_back( m_curr_entity.m_SplineControlPointList[ii].m_y );
|
||||||
|
}
|
||||||
|
|
||||||
|
dxfspline.setCtrlp( ctrlp );
|
||||||
|
dxfspline.setKnots( m_curr_entity.m_SplineKnotsList );
|
||||||
|
tinyspline::BSpline beziers( dxfspline.toBeziers() );
|
||||||
|
|
||||||
|
std::vector<double> coords = beziers.ctrlp();
|
||||||
|
|
||||||
|
// Each Bezier curve uses 4 vertices (a start point, 2 control points and a end point).
|
||||||
|
// So we can have more than one Bezier curve ( there are one curve each four vertices)
|
||||||
|
for( unsigned ii = 0; ii < coords.size(); ii += 8 )
|
||||||
|
{
|
||||||
|
DRAWSEGMENT* segm = ( m_importAsfootprintGraphicItems ) ?
|
||||||
|
static_cast< DRAWSEGMENT* >( new EDGE_MODULE( NULL ) ) :
|
||||||
|
new DRAWSEGMENT;
|
||||||
|
segm->SetLayer( ToLAYER_ID( m_brdLayer ) );
|
||||||
|
segm->SetShape( S_CURVE );
|
||||||
|
segm->SetStart( wxPoint( mapX( coords[ii] ), mapY( coords[ii+1] ) ) );
|
||||||
|
segm->SetBezControl1( wxPoint( mapX( coords[ii+2] ), mapY( coords[ii+3] ) ) );
|
||||||
|
segm->SetBezControl2( wxPoint( mapX( coords[ii+4] ), mapY( coords[ii+5] ) ) );
|
||||||
|
segm->SetEnd( wxPoint( mapX( coords[ii+6] ), mapY( coords[ii+7] ) ) );
|
||||||
|
segm->SetWidth( aWidth );
|
||||||
|
segm->RebuildBezierToSegmentsPointsList( aWidth );
|
||||||
|
m_newItemsList.push_back( segm );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,335 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||||
|
* Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DXF2BRD_ITEMS_H
|
||||||
|
#define DXF2BRD_ITEMS_H
|
||||||
|
|
||||||
|
#include "graphics_import_plugin.h"
|
||||||
|
#include "graphics_importer_buffer.h"
|
||||||
|
|
||||||
|
#include "dl_dxf.h"
|
||||||
|
#include "dl_creationadapter.h"
|
||||||
|
#include "wx/wx.h"
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
class BOARD;
|
||||||
|
class BOARD_ITEM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper class to store a spline control point (in X,Y plane only)
|
||||||
|
*/
|
||||||
|
struct SPLINE_CTRL_POINT
|
||||||
|
{
|
||||||
|
double m_x;
|
||||||
|
double m_y;
|
||||||
|
double m_weight;
|
||||||
|
|
||||||
|
SPLINE_CTRL_POINT( double a_x, double a_y, double a_weight )
|
||||||
|
: m_x( a_x ), m_y( a_y ), m_weight( a_weight )
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper class to parse a DXF entity (polyline and spline)
|
||||||
|
*/
|
||||||
|
class DXF2BRD_ENTITY_DATA
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int m_EntityType; // the DXF type of entity
|
||||||
|
int m_EntityParseStatus; // Inside a entity: status od parsing:
|
||||||
|
// 0 = no entity
|
||||||
|
// 1 = first item of entity
|
||||||
|
// 2 = entity in progress
|
||||||
|
int m_EntityFlag; // a info flag to parse entities
|
||||||
|
|
||||||
|
wxRealPoint m_LastCoordinate; // the last vertex coordinate read (unit = mm)
|
||||||
|
wxRealPoint m_PolylineStart; // The first point of the polyline entity, when reading a polyline (unit = mm)
|
||||||
|
double m_BulgeVertex; // the last vertex bulge value read
|
||||||
|
|
||||||
|
// for spline parsing: parameters
|
||||||
|
unsigned int m_SplineDegree;
|
||||||
|
unsigned int m_SplineKnotsCount;
|
||||||
|
unsigned int m_SplineControlCount;
|
||||||
|
unsigned int m_SplineFitCount;
|
||||||
|
double m_SplineTangentStartX; // tangeant dir X for the start point
|
||||||
|
double m_SplineTangentStartY; // tangeant dir Y for the start point
|
||||||
|
double m_SplineTangentEndX; // tangeant dir X for the end point
|
||||||
|
double m_SplineTangentEndY; // tangeant dir Y for the end point
|
||||||
|
|
||||||
|
// for spline parsing: buffers to store control points, fit points and knot
|
||||||
|
std::vector<double> m_SplineKnotsList; // knots list, code 40
|
||||||
|
// control points list coordinates, code 10, 20 & 30 (only X and Y cood and Weight)
|
||||||
|
std::vector<SPLINE_CTRL_POINT> m_SplineControlPointList;
|
||||||
|
// fit points list, code 11, 21 & 31 (only X and Y cood)
|
||||||
|
std::vector<wxRealPoint> m_SplineFitPointList;
|
||||||
|
|
||||||
|
DXF2BRD_ENTITY_DATA() { Clear(); };
|
||||||
|
|
||||||
|
// Reset the entity parameters
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
m_EntityType = DL_UNKNOWN;
|
||||||
|
m_EntityParseStatus = 0;
|
||||||
|
m_EntityFlag = 0;
|
||||||
|
m_SplineDegree = 1;
|
||||||
|
m_SplineKnotsCount = 0;
|
||||||
|
m_SplineControlCount = 0;
|
||||||
|
m_SplineFitCount = 0;
|
||||||
|
m_SplineTangentStartX = 0.0;
|
||||||
|
m_SplineTangentStartY = 0.0;
|
||||||
|
m_SplineTangentEndX = 0.0;
|
||||||
|
m_SplineTangentEndY = 0.0;
|
||||||
|
m_SplineKnotsList.clear();
|
||||||
|
m_SplineControlPointList.clear();
|
||||||
|
m_SplineFitPointList.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class import DXF ASCII files and convert basic entities to board entities.
|
||||||
|
* It depends on the dxflib library.
|
||||||
|
*/
|
||||||
|
class DXF_IMPORT_PLUGIN : public GRAPHICS_IMPORT_PLUGIN, public DL_CreationAdapter
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::list<BOARD_ITEM*> m_newItemsList; // The list of new items added to the board
|
||||||
|
double m_xOffset; // X coord offset for conversion (in mm)
|
||||||
|
double m_yOffset; // Y coord offset for conversion (in mm)
|
||||||
|
double m_defaultThickness; // default line thickness for conversion (in mm)
|
||||||
|
double m_DXF2mm; // The scale factor to convert DXF units to mm
|
||||||
|
int m_brdLayer; // The board layer to place imported DXF items
|
||||||
|
int m_version; // the dxf version, not used here
|
||||||
|
std::string m_codePage; // The code page, not used here
|
||||||
|
bool m_importAsfootprintGraphicItems; // Use module items instead of board items when true.
|
||||||
|
// true when the items are imported in the footprint editor
|
||||||
|
std::string m_messages; // messages generated during dxf file parsing.
|
||||||
|
// Each message ends by '\n'
|
||||||
|
DXF2BRD_ENTITY_DATA m_curr_entity; // the current entity parameters when parsing a DXF entity
|
||||||
|
|
||||||
|
int m_minX, m_maxX;
|
||||||
|
int m_minY, m_maxY;
|
||||||
|
|
||||||
|
GRAPHICS_IMPORTER_BUFFER m_internalImporter;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
DXF_IMPORT_PLUGIN();
|
||||||
|
~DXF_IMPORT_PLUGIN();
|
||||||
|
|
||||||
|
const wxString GetName() const override
|
||||||
|
{
|
||||||
|
return "AutoCAD DXF";
|
||||||
|
}
|
||||||
|
|
||||||
|
const wxArrayString GetFileExtensions() const override
|
||||||
|
{
|
||||||
|
return wxArrayString( 1, { "dxf" } );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Load( const wxString& aFileName ) override;
|
||||||
|
bool Import( float aXScale, float aYScale ) override;
|
||||||
|
|
||||||
|
unsigned int GetImageWidth() const override;
|
||||||
|
unsigned int GetImageHeight() const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows the import DXF items converted to board graphic items or footprint
|
||||||
|
* graphic items.
|
||||||
|
* @param aImportAsFootprintGraphic = true to import in a footprint, false to import on a board
|
||||||
|
*/
|
||||||
|
void ImportAsFootprintGraphic( bool aImportAsFootprintGraphic )
|
||||||
|
{
|
||||||
|
m_importAsfootprintGraphicItems = aImportAsFootprintGraphic;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the default line width when importing dxf items like lines to Pcbnew.
|
||||||
|
* because dxf files have no line width explicit parameter, it will be most
|
||||||
|
* of time the line width of imported lines
|
||||||
|
* @param aWidth = line width in mm
|
||||||
|
*/
|
||||||
|
void SetDefaultLineWidthMM( double aWidth )
|
||||||
|
{
|
||||||
|
m_defaultThickness = aWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the coordinate offset between the imported dxf items
|
||||||
|
* and Pcbnew.
|
||||||
|
* because dxf files have the Y axis from bottom to top;
|
||||||
|
* aOffsetX = 0, and aOffsetY = - vertical page size to import a full page
|
||||||
|
* @param aOffsetX = the X offset in mm
|
||||||
|
* @param aOffsetY = the Y offset in mm
|
||||||
|
*/
|
||||||
|
void SetOffset( double aOffsetX, double aOffsetY )
|
||||||
|
{
|
||||||
|
m_xOffset = aOffsetX;
|
||||||
|
m_yOffset = aOffsetY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the layer number to import dxf items.
|
||||||
|
* the layer should be a techicanl layer, not a copper layer
|
||||||
|
*/
|
||||||
|
void SetBrdLayer( int aBrdLayer ) { m_brdLayer = aBrdLayer; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the method used for communicate
|
||||||
|
* with this filter.
|
||||||
|
*
|
||||||
|
* @param aFile = the full filename.
|
||||||
|
*/
|
||||||
|
bool ImportDxfFile( const wxString& aFile );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the list of new BOARD_ITEM
|
||||||
|
*/
|
||||||
|
const std::list<BOARD_ITEM*>& GetItemsList() const
|
||||||
|
{
|
||||||
|
return m_newItemsList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the list of messages in one string. Each message ends by '\n'
|
||||||
|
*/
|
||||||
|
std::string& GetMessages() { return m_messages; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// report message to keep trace of not supported dxf entities:
|
||||||
|
void reportMsg( const char* aMessage );
|
||||||
|
|
||||||
|
// coordinate conversions from dxf to internal units
|
||||||
|
int mapX( double aDxfCoordX );
|
||||||
|
int mapY( double aDxfCoordY );
|
||||||
|
int mapDim( double aDxfValue );
|
||||||
|
// mapWidth returns ( in internal units) the aDxfValue if aDxfWidth > 0
|
||||||
|
// or m_defaultThickness
|
||||||
|
int mapWidth( double aDxfWidth );
|
||||||
|
|
||||||
|
// Functions to aid in the creation of a Polyline
|
||||||
|
void insertLine( const wxRealPoint& aSegStart, const wxRealPoint& aSegEnd, int aWidth );
|
||||||
|
void insertArc( const wxRealPoint& aSegStart, const wxRealPoint& aSegEnd,
|
||||||
|
double aBulge, int aWidth );
|
||||||
|
// Add a dxf spline (stored in m_curr_entity) to the board, after conversion to segments
|
||||||
|
void insertSpline( int aWidth );
|
||||||
|
|
||||||
|
// Methods from DL_CreationAdapter:
|
||||||
|
// They are something like"call back" fonctions,
|
||||||
|
// called when the corresponding object is read in dxf file
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called for every string variable in the DXF file (e.g. "$ACADVER").
|
||||||
|
*/
|
||||||
|
virtual void setVariableString( const std::string& key, const std::string& value,
|
||||||
|
int code ) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called for every int variable in the DXF file (e.g. "$ACADMAINTVER").
|
||||||
|
*/
|
||||||
|
virtual void setVariableInt( const std::string& key, int value, int code ) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called for every double variable in the DXF file (e.g. "$DIMEXO").
|
||||||
|
*/
|
||||||
|
virtual void setVariableDouble( const std::string& key, double value, int code ) override {}
|
||||||
|
|
||||||
|
virtual void addLayer( const DL_LayerData& aData ) override;
|
||||||
|
virtual void addLine( const DL_LineData& aData) override;
|
||||||
|
virtual void addCircle( const DL_CircleData& aData ) override;
|
||||||
|
virtual void addArc( const DL_ArcData& aData ) override;
|
||||||
|
//virtual void addLWPolyline( const DRW_LWPolyline& aData ) override;
|
||||||
|
virtual void addText( const DL_TextData& aData ) override;
|
||||||
|
virtual void addPolyline( const DL_PolylineData& aData ) override;
|
||||||
|
|
||||||
|
/** Called for every polyline vertex */
|
||||||
|
virtual void addVertex( const DL_VertexData& aData ) override;
|
||||||
|
virtual void addMText( const DL_MTextData& aData) override;
|
||||||
|
virtual void addTextStyle( const DL_StyleData& aData ) override;
|
||||||
|
|
||||||
|
virtual void endEntity() override;
|
||||||
|
|
||||||
|
/** Called for every spline */
|
||||||
|
virtual void addSpline( const DL_SplineData& aData ) override;
|
||||||
|
|
||||||
|
/** Called for every spline control point */
|
||||||
|
virtual void addControlPoint( const DL_ControlPointData& aData ) override;
|
||||||
|
|
||||||
|
/** Called for every spline fit point */
|
||||||
|
virtual void addFitPoint( const DL_FitPointData& aData ) override;
|
||||||
|
|
||||||
|
/** Called for every spline knot value */
|
||||||
|
virtual void addKnot( const DL_KnotData& aData ) override;
|
||||||
|
|
||||||
|
// Not yet handled DXF entities:
|
||||||
|
virtual void addDimAlign( const DL_DimensionData&,
|
||||||
|
const DL_DimAlignedData& ) override { reportMsg( "DL_Dimension not managed" ); }
|
||||||
|
virtual void addDimLinear( const DL_DimensionData&,
|
||||||
|
const DL_DimLinearData& ) override { reportMsg( "DL_Dimension not managed" ); }
|
||||||
|
virtual void addDimRadial( const DL_DimensionData&,
|
||||||
|
const DL_DimRadialData& ) override { reportMsg( "DL_Dimension not managed" ); }
|
||||||
|
virtual void addDimDiametric( const DL_DimensionData&,
|
||||||
|
const DL_DimDiametricData& ) override { reportMsg( "DL_Dimension not managed" ); }
|
||||||
|
virtual void addDimAngular( const DL_DimensionData&,
|
||||||
|
const DL_DimAngularData& ) override { reportMsg( "DL_Dimension not managed" ); }
|
||||||
|
virtual void addDimAngular3P( const DL_DimensionData&,
|
||||||
|
const DL_DimAngular3PData& ) override { reportMsg( "DL_Dimension not managed" ); }
|
||||||
|
virtual void addDimOrdinate( const DL_DimensionData&,
|
||||||
|
const DL_DimOrdinateData& ) override { reportMsg( "DL_Dimension not managed" ); }
|
||||||
|
virtual void addLeader( const DL_LeaderData& ) override { reportMsg( "DL_Leader not managed" ); }
|
||||||
|
virtual void addLeaderVertex( const DL_LeaderVertexData& ) override { reportMsg( "DL_LeaderVertex not managed" ); }
|
||||||
|
|
||||||
|
virtual void addHatch( const DL_HatchData& ) override { reportMsg( "DL_Hatch not managed" ); }
|
||||||
|
|
||||||
|
virtual void addTrace( const DL_TraceData& ) override { reportMsg( "DL_Trace not managed" ); }
|
||||||
|
virtual void add3dFace( const DL_3dFaceData& ) override { reportMsg( "DL_3dFace not managed" ); }
|
||||||
|
virtual void addSolid( const DL_SolidData& ) override { reportMsg( "DL_Solid not managed" ); }
|
||||||
|
|
||||||
|
virtual void addImage( const DL_ImageData& ) override { reportMsg( "DL_ImageDa not managed" ); }
|
||||||
|
virtual void linkImage( const DL_ImageDefData& ) override { reportMsg( "DL_ImageDef not managed" ); }
|
||||||
|
virtual void addHatchLoop( const DL_HatchLoopData& ) override { reportMsg( "DL_HatchLoop not managed" ); }
|
||||||
|
virtual void addHatchEdge( const DL_HatchEdgeData& ) override { reportMsg( "DL_HatchEdge not managed" ); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a native unicode string into a DXF encoded string.
|
||||||
|
*
|
||||||
|
* DXF endoding includes the following special sequences:
|
||||||
|
* - %%%c for a diameter sign
|
||||||
|
* - %%%d for a degree sign
|
||||||
|
* - %%%p for a plus/minus sign
|
||||||
|
*/
|
||||||
|
static wxString toDxfString( const wxString& aStr );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a DXF encoded string into a native Unicode string.
|
||||||
|
*/
|
||||||
|
static wxString toNativeString( const wxString& aData );
|
||||||
|
|
||||||
|
void writeLine();
|
||||||
|
void writeMtext();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DXF2BRD_ITEMS_H
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 CERN
|
||||||
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "graphics_import_mgr.h"
|
||||||
|
|
||||||
|
#include "dxf_import_plugin.h"
|
||||||
|
#include "svg_import_plugin.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
unique_ptr<GRAPHICS_IMPORT_PLUGIN> GRAPHICS_IMPORT_MGR::GetPlugin( GFX_FILE_T aType )
|
||||||
|
{
|
||||||
|
unique_ptr<GRAPHICS_IMPORT_PLUGIN> ret;
|
||||||
|
|
||||||
|
switch( aType )
|
||||||
|
{
|
||||||
|
case DXF:
|
||||||
|
ret.reset( new DXF_IMPORT_PLUGIN() );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SVG:
|
||||||
|
ret.reset( new SVG_IMPORT_PLUGIN() );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw std::runtime_error( "Unhandled graphics format" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unique_ptr<GRAPHICS_IMPORT_PLUGIN> GRAPHICS_IMPORT_MGR::GetPluginByExt( const wxString& aExtension )
|
||||||
|
{
|
||||||
|
for( auto fileType : GFX_FILE_TYPES )
|
||||||
|
{
|
||||||
|
auto plugin = GetPlugin( fileType );
|
||||||
|
auto fileExtensions = plugin->GetFileExtensions();
|
||||||
|
|
||||||
|
for( const auto& fileExt : fileExtensions )
|
||||||
|
{
|
||||||
|
if( aExtension.IsSameAs( fileExt, false ) )
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return unique_ptr<GRAPHICS_IMPORT_PLUGIN>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const vector<GRAPHICS_IMPORT_MGR::GFX_FILE_T> GRAPHICS_IMPORT_MGR::GFX_FILE_TYPES = { DXF, SVG };
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 CERN
|
||||||
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRAPHICS_IMPORT_MGR_H
|
||||||
|
#define GRAPHICS_IMPORT_MGR_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class GRAPHICS_IMPORT_PLUGIN;
|
||||||
|
class wxString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Class to manage vector graphics importers.
|
||||||
|
*/
|
||||||
|
class GRAPHICS_IMPORT_MGR
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
///> List of handled file types.
|
||||||
|
enum GFX_FILE_T {
|
||||||
|
DXF,
|
||||||
|
SVG
|
||||||
|
};
|
||||||
|
|
||||||
|
///> Vector containing all GFX_FILE_T values.
|
||||||
|
static const std::vector<GFX_FILE_T> GFX_FILE_TYPES;
|
||||||
|
|
||||||
|
///> Returns a plugin that handles a specific file extension.
|
||||||
|
static std::unique_ptr<GRAPHICS_IMPORT_PLUGIN> GetPluginByExt( const wxString& aExtension );
|
||||||
|
|
||||||
|
///> Returns a plugin instance for a specific file type.
|
||||||
|
static std::unique_ptr<GRAPHICS_IMPORT_PLUGIN> GetPlugin( GFX_FILE_T aType );
|
||||||
|
|
||||||
|
private:
|
||||||
|
GRAPHICS_IMPORT_MGR()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* GRAPHICS_IMPORT_MGR_H */
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 CERN
|
||||||
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRAPHICS_IMPORT_PLUGIN_H
|
||||||
|
#define GRAPHICS_IMPORT_PLUGIN_H
|
||||||
|
|
||||||
|
#include <wx/arrstr.h>
|
||||||
|
|
||||||
|
class GRAPHICS_IMPORTER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interface for vector graphics import plugins.
|
||||||
|
*/
|
||||||
|
class GRAPHICS_IMPORT_PLUGIN
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~GRAPHICS_IMPORT_PLUGIN()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the receiver of the imported shapes.
|
||||||
|
*/
|
||||||
|
void SetImporter( GRAPHICS_IMPORTER* aImporter )
|
||||||
|
{
|
||||||
|
m_importer = aImporter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @breif Returns the plugin name.
|
||||||
|
*
|
||||||
|
* This string will be used as the description in the file dialog.
|
||||||
|
*/
|
||||||
|
virtual const wxString GetName() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a string array of the file extensions handled by this plugin.
|
||||||
|
*/
|
||||||
|
virtual const wxArrayString GetFileExtensions() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a list of wildcards that contains the file extensions
|
||||||
|
* handled by this plugin, separated with a coma.
|
||||||
|
*/
|
||||||
|
wxString GetWildcards() const
|
||||||
|
{
|
||||||
|
wxString ret;
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
|
for( const auto& extension : GetFileExtensions() )
|
||||||
|
{
|
||||||
|
if( first )
|
||||||
|
first = false;
|
||||||
|
else
|
||||||
|
ret += ", ";
|
||||||
|
|
||||||
|
ret += "*." + extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Loads file for import.
|
||||||
|
*
|
||||||
|
* It is necessary to have the GRAPHICS_IMPORTER object set before.
|
||||||
|
*/
|
||||||
|
virtual bool Load( const wxString& aFileName ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return image height from original imported file.
|
||||||
|
*
|
||||||
|
* @return Original Image height in internal units.
|
||||||
|
*/
|
||||||
|
virtual unsigned int GetImageHeight() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return image width from original imported file.
|
||||||
|
*
|
||||||
|
* @return Original Image width in internal units.
|
||||||
|
*/
|
||||||
|
virtual unsigned int GetImageWidth() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Actually imports the file.
|
||||||
|
*
|
||||||
|
* It is necessary to have loaded the file beforehand.
|
||||||
|
*/
|
||||||
|
virtual bool Import( float aXScale, float aYScale ) = 0;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
///> Importer used to create objects representing the imported shapes.
|
||||||
|
GRAPHICS_IMPORTER* m_importer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* GRAPHICS_IMPORT_PLUGIN_H */
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 CERN
|
||||||
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "graphics_importer.h"
|
||||||
|
#include "graphics_import_plugin.h"
|
||||||
|
|
||||||
|
GRAPHICS_IMPORTER::GRAPHICS_IMPORTER() :
|
||||||
|
m_lineWidth( DEFAULT_LINE_WIDTH_DFX ), m_scale( 1.0 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool GRAPHICS_IMPORTER::Load( const wxString &aFileName )
|
||||||
|
{
|
||||||
|
m_items.clear();
|
||||||
|
|
||||||
|
if( !m_plugin )
|
||||||
|
{
|
||||||
|
wxASSERT_MSG( false, "Plugin has to be set before load." );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_plugin->SetImporter( this );
|
||||||
|
|
||||||
|
return m_plugin->Load( aFileName );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GRAPHICS_IMPORTER::Import( float aXScale, float aYScale)
|
||||||
|
{
|
||||||
|
if( !m_plugin )
|
||||||
|
{
|
||||||
|
wxASSERT_MSG( false, "Plugin has to be set before import." );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_plugin->SetImporter( this );
|
||||||
|
|
||||||
|
return m_plugin->Import( aXScale, aYScale );
|
||||||
|
}
|
|
@ -0,0 +1,235 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 CERN
|
||||||
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRAPHICS_IMPORTER_H
|
||||||
|
#define GRAPHICS_IMPORTER_H
|
||||||
|
|
||||||
|
#include "graphics_import_mgr.h"
|
||||||
|
#include "graphics_import_plugin.h"
|
||||||
|
|
||||||
|
#include <eda_text.h>
|
||||||
|
#include <math/vector2d.h>
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class EDA_ITEM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interface that creates objects representing shapes for a given data model.
|
||||||
|
*/
|
||||||
|
class GRAPHICS_IMPORTER
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GRAPHICS_IMPORTER();
|
||||||
|
|
||||||
|
virtual ~GRAPHICS_IMPORTER()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the import plugin used to obtain shapes from a file.
|
||||||
|
*/
|
||||||
|
void SetPlugin( std::unique_ptr<GRAPHICS_IMPORT_PLUGIN> aPlugin )
|
||||||
|
{
|
||||||
|
m_plugin = std::move( aPlugin );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Load file and get its basic data
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool Load( const wxString &aFileName );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Imports shapes from loaded file.
|
||||||
|
*
|
||||||
|
* It is important to have the file loaded before importing.
|
||||||
|
*/
|
||||||
|
bool Import( float aXScale, float aYScale);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get original image Wigth.
|
||||||
|
*
|
||||||
|
* @return Width of the loaded image in internal units.
|
||||||
|
*/
|
||||||
|
unsigned int GetImageWidth() const
|
||||||
|
{
|
||||||
|
return m_originalWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get original image Height
|
||||||
|
*
|
||||||
|
* @return Height of the loaded image in internal units.
|
||||||
|
*/
|
||||||
|
unsigned int GetImageHeight() const
|
||||||
|
{
|
||||||
|
return m_originalHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the line width for the imported outlines.
|
||||||
|
*/
|
||||||
|
void SetLineWidth( double aWidth )
|
||||||
|
{
|
||||||
|
m_lineWidth = (unsigned int)( aWidth * m_scale );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the line width used for importing the outlines.
|
||||||
|
*/
|
||||||
|
unsigned int GetLineWidth() const
|
||||||
|
{
|
||||||
|
return m_lineWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets scale affecting the imported shapes, for the X direction.
|
||||||
|
*/
|
||||||
|
void SetXScale( double aScale )
|
||||||
|
{
|
||||||
|
m_xScale = aScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets scale affecting the imported shapes, for the Y direction.
|
||||||
|
*/
|
||||||
|
void SetYScale( double aScale )
|
||||||
|
{
|
||||||
|
m_yScale = aScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the scale factor affecting the imported shapes.
|
||||||
|
*/
|
||||||
|
double GetScale() const
|
||||||
|
{
|
||||||
|
return m_scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief set the scale factor affecting the imported shapes.
|
||||||
|
* it allows conversion between imported shapes units and internal units
|
||||||
|
*/
|
||||||
|
void SetScale( double aScale )
|
||||||
|
{
|
||||||
|
m_scale = aScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @breif Returns the list of objects representing the imported shapes.
|
||||||
|
*/
|
||||||
|
std::list<std::unique_ptr<EDA_ITEM>>& GetItems()
|
||||||
|
{
|
||||||
|
return m_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
///> Default line thickness (in internal units)
|
||||||
|
static constexpr unsigned int DEFAULT_LINE_WIDTH_DFX = 1;
|
||||||
|
|
||||||
|
// Methods to be implemented by derived graphics importers
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates an object representing a line segment.
|
||||||
|
* @param aOrigin is the segment origin point expressed in internal units.
|
||||||
|
* @param aEnd is the segment end point expressed in internal units.
|
||||||
|
*/
|
||||||
|
virtual void AddLine( const VECTOR2D& aOrigin, const VECTOR2D& aEnd ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates an object representing a circle.
|
||||||
|
* @param aCenter is the circle center point expressed in internal units.
|
||||||
|
* @param aRadius is the circle radius expressed in internal units.
|
||||||
|
*/
|
||||||
|
virtual void AddCircle( const VECTOR2D& aCenter, unsigned int aRadius ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates an object representing an arc.
|
||||||
|
* @param aCenter is the arc center point expressed in internal units.
|
||||||
|
* @param aStart is the arc arm end point expressed in internal units.
|
||||||
|
* Its length is the arc radius.
|
||||||
|
* @param aAgnle is the arc angle expressed in decidegrees.
|
||||||
|
*/
|
||||||
|
virtual void AddArc( const VECTOR2D& aCenter, const VECTOR2D& aStart, double aAngle ) = 0;
|
||||||
|
|
||||||
|
virtual void AddPolygon( const std::vector< VECTOR2D >& aVertices ) = 0;
|
||||||
|
|
||||||
|
//virtual void AddArc( const VECTOR2D& aOrigin, double aStartAngle, double aEndAngle ) = 0;
|
||||||
|
//
|
||||||
|
/**
|
||||||
|
* @brief Creates an object representing a text.
|
||||||
|
* @param aOrigin is the text position.
|
||||||
|
* @param aText is the displayed text.
|
||||||
|
* @param aHeight is the text height expressed in internal units.
|
||||||
|
* @param aWidth is the text width expressed in internal units.
|
||||||
|
* @param aOrientation is the text orientation angle expressed in decidegrees.
|
||||||
|
* @param aHJustify is the text horizontal justification.
|
||||||
|
* @param aVJustify is the text vertical justification.
|
||||||
|
*/
|
||||||
|
virtual void AddText( const VECTOR2D& aOrigin, const wxString& aText,
|
||||||
|
unsigned int aHeight, unsigned aWidth, double aOrientation,
|
||||||
|
EDA_TEXT_HJUSTIFY_T aHJustify, EDA_TEXT_VJUSTIFY_T aVJustify ) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
///> Adds an item to the imported shapes list.
|
||||||
|
void addItem( std::unique_ptr<EDA_ITEM> aItem )
|
||||||
|
{
|
||||||
|
m_items.emplace_back( std::move( aItem ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
///> List of imported items
|
||||||
|
std::list<std::unique_ptr<EDA_ITEM>> m_items;
|
||||||
|
|
||||||
|
///> Plugin used to load a file
|
||||||
|
std::unique_ptr<GRAPHICS_IMPORT_PLUGIN> m_plugin;
|
||||||
|
|
||||||
|
///> Total image width
|
||||||
|
unsigned int m_originalWidth;
|
||||||
|
|
||||||
|
///> Total image Height;
|
||||||
|
unsigned int m_originalHeight;
|
||||||
|
|
||||||
|
///> Default line thickness for the imported graphics
|
||||||
|
unsigned int m_lineWidth;
|
||||||
|
|
||||||
|
///> Scale factor applied to the imported graphics, X direction
|
||||||
|
double m_xScale;
|
||||||
|
|
||||||
|
///> Scale factor applied to the imported graphics, Y direction
|
||||||
|
double m_yScale;
|
||||||
|
|
||||||
|
///> Scale factor applied to the imported graphics
|
||||||
|
double m_scale;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* GRAPHICS_IMPORTER_H */
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 CERN
|
||||||
|
* @author Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "graphics_importer_buffer.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
static std::unique_ptr<T> make_shape( const Args&... aArguments )
|
||||||
|
{
|
||||||
|
return std::unique_ptr<T>( new T( aArguments... ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void GRAPHICS_IMPORTER_BUFFER::AddLine( const VECTOR2D& aStart, const VECTOR2D& aEnd )
|
||||||
|
{
|
||||||
|
m_shapes.push_back( make_shape< IMPORTED_LINE >( aStart, aEnd ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GRAPHICS_IMPORTER_BUFFER::AddCircle( const VECTOR2D& aCenter, unsigned int aRadius )
|
||||||
|
{
|
||||||
|
m_shapes.push_back( make_shape< IMPORTED_CIRCLE >( aCenter, aRadius ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GRAPHICS_IMPORTER_BUFFER::AddArc( const VECTOR2D& aCenter, const VECTOR2D& aStart,
|
||||||
|
double aAngle )
|
||||||
|
{
|
||||||
|
m_shapes.push_back( make_shape< IMPORTED_ARC >( aCenter, aStart, aAngle ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GRAPHICS_IMPORTER_BUFFER::AddPolygon( const std::vector< VECTOR2D >& aVertices )
|
||||||
|
{
|
||||||
|
m_shapes.push_back( make_shape< IMPORTED_POLYGON >( aVertices ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GRAPHICS_IMPORTER_BUFFER::AddText( const VECTOR2D& aOrigin, const wxString& aText,
|
||||||
|
unsigned int aHeight, unsigned aWidth, double aOrientation,
|
||||||
|
EDA_TEXT_HJUSTIFY_T aHJustify, EDA_TEXT_VJUSTIFY_T aVJustify )
|
||||||
|
{
|
||||||
|
m_shapes.push_back( make_shape< IMPORTED_TEXT >( aOrigin, aText, aHeight, aWidth, aOrientation,
|
||||||
|
aHJustify, aVJustify ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void GRAPHICS_IMPORTER_BUFFER::ImportTo( GRAPHICS_IMPORTER& aImporter )
|
||||||
|
{
|
||||||
|
for( auto& shape : m_shapes )
|
||||||
|
shape->ImportTo( aImporter );
|
||||||
|
}
|
|
@ -0,0 +1,167 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 CERN
|
||||||
|
* @author Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRAPHICS_IMPORTER_BUFFER_H
|
||||||
|
#define GRAPHICS_IMPORTER_BUFFER_H
|
||||||
|
|
||||||
|
#include "graphics_importer.h"
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
class IMPORTED_SHAPE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void ImportTo( GRAPHICS_IMPORTER& aImporter ) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class IMPORTED_LINE : public IMPORTED_SHAPE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IMPORTED_LINE( const VECTOR2D& aStart, const VECTOR2D& aEnd )
|
||||||
|
: m_start( aStart ), m_end( aEnd )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImportTo( GRAPHICS_IMPORTER& aImporter ) const override
|
||||||
|
{
|
||||||
|
aImporter.AddLine( m_start, m_end );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const VECTOR2D m_start;
|
||||||
|
const VECTOR2D m_end;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class IMPORTED_CIRCLE : public IMPORTED_SHAPE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IMPORTED_CIRCLE( const VECTOR2D& aCenter, double aRadius )
|
||||||
|
: m_center( aCenter ), m_radius( aRadius )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImportTo( GRAPHICS_IMPORTER& aImporter ) const override
|
||||||
|
{
|
||||||
|
aImporter.AddCircle( m_center, m_radius );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const VECTOR2D m_center;
|
||||||
|
double m_radius;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class IMPORTED_ARC : public IMPORTED_SHAPE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IMPORTED_ARC( const VECTOR2D& aCenter, const VECTOR2D& aStart, double aAngle )
|
||||||
|
: m_center( aCenter ), m_start( aStart ), m_angle( aAngle )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImportTo( GRAPHICS_IMPORTER& aImporter ) const override
|
||||||
|
{
|
||||||
|
aImporter.AddArc( m_center, m_start, m_angle );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const VECTOR2D m_center;
|
||||||
|
const VECTOR2D m_start;
|
||||||
|
double m_angle;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class IMPORTED_POLYGON : public IMPORTED_SHAPE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IMPORTED_POLYGON( const std::vector< VECTOR2D >& aVertices )
|
||||||
|
: m_vertices( aVertices )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImportTo( GRAPHICS_IMPORTER& aImporter ) const override
|
||||||
|
{
|
||||||
|
aImporter.AddPolygon( m_vertices );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::vector< VECTOR2D > m_vertices;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class IMPORTED_TEXT : public IMPORTED_SHAPE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IMPORTED_TEXT( const VECTOR2D& aOrigin, const wxString& aText,
|
||||||
|
unsigned int aHeight, unsigned aWidth, double aOrientation,
|
||||||
|
EDA_TEXT_HJUSTIFY_T aHJustify, EDA_TEXT_VJUSTIFY_T aVJustify )
|
||||||
|
: m_origin( aOrigin ), m_text( aText ),
|
||||||
|
m_height( aHeight ), m_width( aWidth ),
|
||||||
|
m_orientation( aOrientation ),
|
||||||
|
m_hJustify( aHJustify ), m_vJustify( aVJustify )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImportTo( GRAPHICS_IMPORTER& aImporter ) const override
|
||||||
|
{
|
||||||
|
aImporter.AddText( m_origin, m_text, m_height, m_width, m_orientation,
|
||||||
|
m_hJustify, m_vJustify );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const VECTOR2D& m_origin;
|
||||||
|
const wxString& m_text;
|
||||||
|
unsigned int m_height;
|
||||||
|
unsigned int m_width;
|
||||||
|
double m_orientation;
|
||||||
|
EDA_TEXT_HJUSTIFY_T m_hJustify;
|
||||||
|
EDA_TEXT_VJUSTIFY_T m_vJustify;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class GRAPHICS_IMPORTER_BUFFER : public GRAPHICS_IMPORTER
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void AddLine( const VECTOR2D& aStart, const VECTOR2D& aEnd ) override;
|
||||||
|
|
||||||
|
void AddCircle( const VECTOR2D& aCenter, unsigned int aRadius ) override;
|
||||||
|
|
||||||
|
void AddArc( const VECTOR2D& aCenter, const VECTOR2D& aStart, double aAngle ) override;
|
||||||
|
|
||||||
|
void AddPolygon( const std::vector< VECTOR2D >& aVertices ) override;
|
||||||
|
|
||||||
|
void AddText( const VECTOR2D& aOrigin, const wxString& aText,
|
||||||
|
unsigned int aHeight, unsigned aWidth, double aOrientation,
|
||||||
|
EDA_TEXT_HJUSTIFY_T aHJustify, EDA_TEXT_VJUSTIFY_T aVJustify ) override;
|
||||||
|
|
||||||
|
void ImportTo( GRAPHICS_IMPORTER& aImporter );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
///> List of imported shapes
|
||||||
|
std::list< std::unique_ptr< IMPORTED_SHAPE > > m_shapes;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* GRAPHICS_IMPORTER_BUFFER */
|
|
@ -0,0 +1,154 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 CERN
|
||||||
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "graphics_importer_pcbnew.h"
|
||||||
|
|
||||||
|
#include <class_board.h>
|
||||||
|
#include <class_edge_mod.h>
|
||||||
|
#include <class_pcb_text.h>
|
||||||
|
#include <class_text_mod.h>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
static std::vector<wxPoint> convertPoints( const std::vector<VECTOR2D>& aPoints,
|
||||||
|
double aScaleFactor );
|
||||||
|
|
||||||
|
|
||||||
|
static wxPoint Round( const VECTOR2D& aVec )
|
||||||
|
{
|
||||||
|
return wxPoint( (int) aVec.x, (int) aVec.y );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GRAPHICS_IMPORTER_PCBNEW::AddLine( const VECTOR2D& aOrigin, const VECTOR2D& aEnd )
|
||||||
|
{
|
||||||
|
unique_ptr<DRAWSEGMENT> line( createDrawing() );
|
||||||
|
line->SetShape( S_SEGMENT );
|
||||||
|
line->SetLayer( GetLayer() );
|
||||||
|
line->SetWidth( GetLineWidth() );
|
||||||
|
line->SetStart( Round ( aOrigin * GetScale() ) );
|
||||||
|
line->SetEnd( Round ( aEnd * GetScale() ) );
|
||||||
|
addItem( std::move( line ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GRAPHICS_IMPORTER_PCBNEW::AddCircle( const VECTOR2D& aCenter, unsigned int aRadius )
|
||||||
|
{
|
||||||
|
unique_ptr<DRAWSEGMENT> circle( createDrawing() );
|
||||||
|
circle->SetShape( S_CIRCLE );
|
||||||
|
circle->SetLayer( GetLayer() );
|
||||||
|
circle->SetWidth( GetLineWidth() );
|
||||||
|
circle->SetCenter( Round ( aCenter * GetScale() ) );
|
||||||
|
circle->SetArcStart( Round ( VECTOR2D( aCenter.x + aRadius, aCenter.y ) * GetScale() ) );
|
||||||
|
addItem( std::move( circle ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GRAPHICS_IMPORTER_PCBNEW::AddArc( const VECTOR2D& aCenter, const VECTOR2D& aStart, double aAngle )
|
||||||
|
{
|
||||||
|
unique_ptr<DRAWSEGMENT> arc( createDrawing() );
|
||||||
|
arc->SetShape( S_ARC );
|
||||||
|
arc->SetLayer( GetLayer() );
|
||||||
|
arc->SetWidth( GetLineWidth() );
|
||||||
|
arc->SetCenter( Round ( aCenter * GetScale() ) );
|
||||||
|
arc->SetArcStart( Round ( aStart * GetScale() ) );
|
||||||
|
arc->SetAngle( aAngle );
|
||||||
|
addItem( std::move( arc ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GRAPHICS_IMPORTER_PCBNEW::AddPolygon( const std::vector< VECTOR2D >& aVertices )
|
||||||
|
{
|
||||||
|
std::vector< wxPoint > convertedVertices = convertPoints( aVertices, GetScale() );
|
||||||
|
unique_ptr<DRAWSEGMENT> polygon( createDrawing() );
|
||||||
|
polygon->SetShape( S_POLYGON );
|
||||||
|
polygon->SetLayer( GetLayer() );
|
||||||
|
polygon->SetPolyPoints( convertedVertices );
|
||||||
|
addItem( std::move( polygon ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GRAPHICS_IMPORTER_PCBNEW::AddText( const VECTOR2D& aOrigin, const wxString& aText,
|
||||||
|
unsigned int aHeight, unsigned aWidth, double aOrientation,
|
||||||
|
EDA_TEXT_HJUSTIFY_T aHJustify, EDA_TEXT_VJUSTIFY_T aVJustify )
|
||||||
|
{
|
||||||
|
unique_ptr<BOARD_ITEM> boardItem;
|
||||||
|
EDA_TEXT* textItem;
|
||||||
|
tie( boardItem, textItem ) = createText();
|
||||||
|
boardItem->SetLayer( GetLayer() );
|
||||||
|
textItem->SetThickness( GetLineWidth() );
|
||||||
|
textItem->SetTextPos( Round ( aOrigin * GetScale() ) );
|
||||||
|
textItem->SetTextAngle( aOrientation );
|
||||||
|
textItem->SetTextWidth( (double)aWidth * GetScale() );
|
||||||
|
textItem->SetTextHeight( (double)aHeight * GetScale() );
|
||||||
|
textItem->SetVertJustify( aVJustify );
|
||||||
|
textItem->SetHorizJustify( aHJustify );
|
||||||
|
textItem->SetText( aText );
|
||||||
|
addItem( std::move( boardItem ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unique_ptr<DRAWSEGMENT> GRAPHICS_IMPORTER_BOARD::createDrawing()
|
||||||
|
{
|
||||||
|
return unique_ptr<DRAWSEGMENT>( new DRAWSEGMENT( m_board ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pair<unique_ptr<BOARD_ITEM>, EDA_TEXT*> GRAPHICS_IMPORTER_BOARD::createText()
|
||||||
|
{
|
||||||
|
TEXTE_PCB* text = new TEXTE_PCB( m_board );
|
||||||
|
return make_pair( unique_ptr<BOARD_ITEM>( text ), static_cast<EDA_TEXT*>( text ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unique_ptr<DRAWSEGMENT> GRAPHICS_IMPORTER_MODULE::createDrawing()
|
||||||
|
{
|
||||||
|
return unique_ptr<DRAWSEGMENT>( new EDGE_MODULE( m_module ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pair<unique_ptr<BOARD_ITEM>, EDA_TEXT*> GRAPHICS_IMPORTER_MODULE::createText()
|
||||||
|
{
|
||||||
|
TEXTE_MODULE* text = new TEXTE_MODULE( m_module );
|
||||||
|
return make_pair( unique_ptr<BOARD_ITEM>( text ), static_cast<EDA_TEXT*>( text ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static std::vector< wxPoint > convertPoints( const std::vector<VECTOR2D>& aPoints,
|
||||||
|
double aScaleFactor )
|
||||||
|
{
|
||||||
|
std::vector<wxPoint> convertedPoints;
|
||||||
|
convertedPoints.reserve( aPoints.size() );
|
||||||
|
|
||||||
|
for( const VECTOR2D& precisePoint : aPoints )
|
||||||
|
{
|
||||||
|
auto scaledX = precisePoint.x * aScaleFactor;
|
||||||
|
auto scaledY = precisePoint.y * aScaleFactor;
|
||||||
|
|
||||||
|
convertedPoints.emplace_back( scaledX, scaledY );
|
||||||
|
}
|
||||||
|
|
||||||
|
return convertedPoints;
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 CERN
|
||||||
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRAPHICS_IMPORTER_PCBNEW_H
|
||||||
|
#define GRAPHICS_IMPORTER_PCBNEW_H
|
||||||
|
|
||||||
|
#include "graphics_importer.h"
|
||||||
|
|
||||||
|
#include <layers_id_colors_and_visibility.h>
|
||||||
|
|
||||||
|
class BOARD_ITEM;
|
||||||
|
class BOARD;
|
||||||
|
class MODULE;
|
||||||
|
class DRAWSEGMENT;
|
||||||
|
class EDA_TEXT;
|
||||||
|
|
||||||
|
class GRAPHICS_IMPORTER_PCBNEW : public GRAPHICS_IMPORTER
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GRAPHICS_IMPORTER_PCBNEW()
|
||||||
|
: m_layer( Dwgs_User )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the target layer for the imported shapes.
|
||||||
|
* @param aLayer is the layer to be used by the imported shapes.
|
||||||
|
*/
|
||||||
|
void SetLayer( PCB_LAYER_ID aLayer )
|
||||||
|
{
|
||||||
|
m_layer = aLayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the target layer for the imported shapes.
|
||||||
|
*/
|
||||||
|
PCB_LAYER_ID GetLayer() const
|
||||||
|
{
|
||||||
|
return m_layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddLine( const VECTOR2D& aOrigin, const VECTOR2D& aEnd ) override;
|
||||||
|
|
||||||
|
void AddCircle( const VECTOR2D& aOrigin, unsigned int aRadius ) override;
|
||||||
|
|
||||||
|
void AddArc( const VECTOR2D& aCenter, const VECTOR2D& aStart, double aAngle ) override;
|
||||||
|
|
||||||
|
void AddPolygon( const std::vector< VECTOR2D >& aVertices ) override;
|
||||||
|
|
||||||
|
void AddText( const VECTOR2D& aOrigin, const wxString& aText,
|
||||||
|
unsigned int aHeight, unsigned aWidth, double aOrientation,
|
||||||
|
EDA_TEXT_HJUSTIFY_T aHJustify, EDA_TEXT_VJUSTIFY_T aVJustify ) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
///> Create an object representing a graphical shape.
|
||||||
|
virtual std::unique_ptr<DRAWSEGMENT> createDrawing() = 0;
|
||||||
|
|
||||||
|
///> Create an object representing a text. Both pointers point to different parts of the
|
||||||
|
///> same object, the EDA_TEXT pointer is simply for convenience.
|
||||||
|
virtual std::pair<std::unique_ptr<BOARD_ITEM>, EDA_TEXT*> createText() = 0;
|
||||||
|
|
||||||
|
///> Target layer for the imported shapes.
|
||||||
|
PCB_LAYER_ID m_layer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class GRAPHICS_IMPORTER_BOARD : public GRAPHICS_IMPORTER_PCBNEW
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GRAPHICS_IMPORTER_BOARD( BOARD* aBoard )
|
||||||
|
: m_board( aBoard )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::unique_ptr<DRAWSEGMENT> createDrawing() override;
|
||||||
|
std::pair<std::unique_ptr<BOARD_ITEM>, EDA_TEXT*> createText() override;
|
||||||
|
|
||||||
|
BOARD* m_board;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class GRAPHICS_IMPORTER_MODULE : public GRAPHICS_IMPORTER_PCBNEW
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GRAPHICS_IMPORTER_MODULE( MODULE* aModule )
|
||||||
|
: m_module( aModule )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::unique_ptr<DRAWSEGMENT> createDrawing() override;
|
||||||
|
std::pair<std::unique_ptr<BOARD_ITEM>, EDA_TEXT*> createText() override;
|
||||||
|
|
||||||
|
MODULE* m_module;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* GRAPHICS_IMPORTER_PCBNEW */
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#define NANOSVG_IMPLEMENTATION
|
||||||
|
#include "nanosvg.h"
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,245 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 CERN
|
||||||
|
* @author Janito V. Ferreira Filho
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "svg_import_plugin.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <wx/gdicmn.h>
|
||||||
|
#include <math/vector2d.h>
|
||||||
|
|
||||||
|
#include "convert_to_biu.h"
|
||||||
|
#include "graphics_importer.h"
|
||||||
|
|
||||||
|
static VECTOR2D calculateBezierBoundingBoxExtremity( const float* aCurvePoints,
|
||||||
|
std::function< const float&( const float&, const float& ) > comparator );
|
||||||
|
static float calculateBezierSegmentationThreshold( const float* aCurvePoints );
|
||||||
|
static void segmentBezierCurve( const VECTOR2D& aStart, const VECTOR2D& aEnd, float aOffset,
|
||||||
|
float aStep, const float* aCurvePoints, float aSegmentationThreshold,
|
||||||
|
std::vector< VECTOR2D >& aGeneratedPoints );
|
||||||
|
static void createNewBezierCurveSegments( const VECTOR2D& aStart, const VECTOR2D& aMiddle,
|
||||||
|
const VECTOR2D& aEnd, float aOffset, float aStep, const float* aCurvePoints,
|
||||||
|
float aSegmentationThreshold, std::vector< VECTOR2D >& aGeneratedPoints );
|
||||||
|
static VECTOR2D getBezierPoint( const float* aCurvePoints, float aStep );
|
||||||
|
static VECTOR2D getPoint( const float* aPointCoordinates );
|
||||||
|
static VECTOR2D getPointInLine( const VECTOR2D& aLineStart, const VECTOR2D& aLineEnd,
|
||||||
|
float aDistance );
|
||||||
|
static float distanceFromPointToLine( const VECTOR2D& aPoint, const VECTOR2D& aLineStart,
|
||||||
|
const VECTOR2D& aLineEnd );
|
||||||
|
|
||||||
|
bool SVG_IMPORT_PLUGIN::Load( const wxString& aFileName )
|
||||||
|
{
|
||||||
|
wxCHECK( m_importer, false );
|
||||||
|
|
||||||
|
m_parsedImage = nsvgParseFromFile( aFileName.c_str(), "mm", 96 );
|
||||||
|
|
||||||
|
wxCHECK( m_parsedImage, false );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SVG_IMPORT_PLUGIN::Import(float aXScale, float aYScale)
|
||||||
|
{
|
||||||
|
for( NSVGshape* shape = m_parsedImage->shapes; shape != NULL; shape = shape->next )
|
||||||
|
{
|
||||||
|
m_importer->SetLineWidth( shape->strokeWidth );
|
||||||
|
|
||||||
|
for( NSVGpath* path = shape->paths; path != NULL; path = path->next )
|
||||||
|
DrawPath( path->pts, path->npts, path->closed );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SVG_IMPORT_PLUGIN::DrawPath( const float* aPoints, int aNumPoints, bool aClosedPath )
|
||||||
|
{
|
||||||
|
std::vector< VECTOR2D > collectedPathPoints;
|
||||||
|
|
||||||
|
if( aNumPoints > 0 )
|
||||||
|
DrawCubicBezierPath( aPoints, aNumPoints, collectedPathPoints );
|
||||||
|
|
||||||
|
if( aClosedPath )
|
||||||
|
DrawPolygon( collectedPathPoints );
|
||||||
|
else
|
||||||
|
DrawLineSegments( collectedPathPoints );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SVG_IMPORT_PLUGIN::DrawCubicBezierPath( const float* aPoints, int aNumPoints,
|
||||||
|
std::vector< VECTOR2D >& aGeneratedPoints )
|
||||||
|
{
|
||||||
|
const int pointsPerSegment = 4;
|
||||||
|
const int curveSpecificPointsPerSegment = 3;
|
||||||
|
const int curveSpecificCoordinatesPerSegment = 2 * curveSpecificPointsPerSegment;
|
||||||
|
const float* currentPoints = aPoints;
|
||||||
|
int remainingPoints = aNumPoints;
|
||||||
|
|
||||||
|
while( remainingPoints >= pointsPerSegment )
|
||||||
|
{
|
||||||
|
DrawCubicBezierCurve( currentPoints, aGeneratedPoints );
|
||||||
|
currentPoints += curveSpecificCoordinatesPerSegment;
|
||||||
|
remainingPoints -= curveSpecificPointsPerSegment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SVG_IMPORT_PLUGIN::DrawCubicBezierCurve( const float* aPoints,
|
||||||
|
std::vector< VECTOR2D >& aGeneratedPoints )
|
||||||
|
{
|
||||||
|
auto start = getBezierPoint( aPoints, 0.f );
|
||||||
|
auto end = getBezierPoint( aPoints, 1.f );
|
||||||
|
auto segmentationThreshold = calculateBezierSegmentationThreshold( aPoints );
|
||||||
|
|
||||||
|
aGeneratedPoints.push_back( start );
|
||||||
|
segmentBezierCurve( start, end, 0.f, 0.5f, aPoints, segmentationThreshold, aGeneratedPoints );
|
||||||
|
aGeneratedPoints.push_back( end );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SVG_IMPORT_PLUGIN::DrawPolygon( const std::vector< VECTOR2D >& aPoints )
|
||||||
|
{
|
||||||
|
m_importer->AddPolygon( aPoints );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SVG_IMPORT_PLUGIN::DrawLineSegments( const std::vector< VECTOR2D >& aPoints )
|
||||||
|
{
|
||||||
|
unsigned int numLineStartPoints = aPoints.size() - 1;
|
||||||
|
|
||||||
|
for( unsigned int pointIndex = 0; pointIndex < numLineStartPoints; ++pointIndex )
|
||||||
|
m_importer->AddLine( aPoints[ pointIndex ], aPoints[ pointIndex + 1 ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static VECTOR2D getPoint( const float* aPointCoordinates )
|
||||||
|
{
|
||||||
|
return VECTOR2D( aPointCoordinates[0], aPointCoordinates[1] );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static VECTOR2D getBezierPoint( const float* aPoints, float aStep )
|
||||||
|
{
|
||||||
|
const int coordinatesPerPoint = 2;
|
||||||
|
|
||||||
|
auto firstCubicPoint = getPoint( aPoints );
|
||||||
|
auto secondCubicPoint = getPoint( aPoints + 1 * coordinatesPerPoint );
|
||||||
|
auto thirdCubicPoint = getPoint( aPoints + 2 * coordinatesPerPoint );
|
||||||
|
auto fourthCubicPoint = getPoint( aPoints + 3 * coordinatesPerPoint );
|
||||||
|
|
||||||
|
auto firstQuadraticPoint = getPointInLine( firstCubicPoint, secondCubicPoint, aStep );
|
||||||
|
auto secondQuadraticPoint = getPointInLine( secondCubicPoint, thirdCubicPoint, aStep );
|
||||||
|
auto thirdQuadraticPoint = getPointInLine( thirdCubicPoint, fourthCubicPoint, aStep );
|
||||||
|
|
||||||
|
auto firstLinearPoint = getPointInLine( firstQuadraticPoint, secondQuadraticPoint, aStep );
|
||||||
|
auto secondLinearPoint = getPointInLine( secondQuadraticPoint, thirdQuadraticPoint, aStep );
|
||||||
|
|
||||||
|
return getPointInLine( firstLinearPoint, secondLinearPoint, aStep );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static VECTOR2D getPointInLine( const VECTOR2D& aLineStart, const VECTOR2D& aLineEnd,
|
||||||
|
float aDistance )
|
||||||
|
{
|
||||||
|
return aLineStart + ( aLineEnd - aLineStart ) * aDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static float calculateBezierSegmentationThreshold( const float* aCurvePoints )
|
||||||
|
{
|
||||||
|
using comparatorFunction = const float&(*)( const float&, const float& );
|
||||||
|
|
||||||
|
auto minimumComparator = static_cast< comparatorFunction >( &std::min );
|
||||||
|
auto maximumComparator = static_cast< comparatorFunction >( &std::max );
|
||||||
|
|
||||||
|
VECTOR2D minimum = calculateBezierBoundingBoxExtremity( aCurvePoints, minimumComparator );
|
||||||
|
VECTOR2D maximum = calculateBezierBoundingBoxExtremity( aCurvePoints, maximumComparator );
|
||||||
|
VECTOR2D boundingBoxDimensions = maximum - minimum;
|
||||||
|
|
||||||
|
return 0.001 * std::max( boundingBoxDimensions.x, boundingBoxDimensions.y );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static VECTOR2D calculateBezierBoundingBoxExtremity( const float* aCurvePoints,
|
||||||
|
std::function< const float&( const float&, const float& ) > comparator )
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
x = aCurvePoints[0];
|
||||||
|
y = aCurvePoints[1];
|
||||||
|
|
||||||
|
for( int pointIndex = 1; pointIndex < 3; ++pointIndex )
|
||||||
|
{
|
||||||
|
x = comparator( x, aCurvePoints[ 2 * pointIndex ] );
|
||||||
|
y = comparator( y, aCurvePoints[ 2 * pointIndex + 1 ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
return VECTOR2D( x, y );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void segmentBezierCurve( const VECTOR2D& aStart, const VECTOR2D& aEnd, float aOffset,
|
||||||
|
float aStep, const float* aCurvePoints, float aSegmentationThreshold,
|
||||||
|
std::vector< VECTOR2D >& aGeneratedPoints )
|
||||||
|
{
|
||||||
|
VECTOR2D middle = getBezierPoint( aCurvePoints, aOffset + aStep );
|
||||||
|
float distanceToPreviousSegment = distanceFromPointToLine( middle, aStart, aEnd );
|
||||||
|
|
||||||
|
if( distanceToPreviousSegment > aSegmentationThreshold )
|
||||||
|
{
|
||||||
|
createNewBezierCurveSegments( aStart, middle, aEnd, aOffset, aStep, aCurvePoints,
|
||||||
|
aSegmentationThreshold, aGeneratedPoints );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void createNewBezierCurveSegments( const VECTOR2D& aStart, const VECTOR2D& aMiddle,
|
||||||
|
const VECTOR2D& aEnd, float aOffset, float aStep, const float* aCurvePoints,
|
||||||
|
float aSegmentationThreshold, std::vector< VECTOR2D >& aGeneratedPoints )
|
||||||
|
{
|
||||||
|
float newStep = aStep / 2.f;
|
||||||
|
float offsetAfterMiddle = aOffset + aStep;
|
||||||
|
|
||||||
|
segmentBezierCurve( aStart, aMiddle, aOffset, newStep, aCurvePoints, aSegmentationThreshold,
|
||||||
|
aGeneratedPoints );
|
||||||
|
|
||||||
|
aGeneratedPoints.push_back( aMiddle );
|
||||||
|
|
||||||
|
segmentBezierCurve( aMiddle, aEnd, offsetAfterMiddle, newStep, aCurvePoints,
|
||||||
|
aSegmentationThreshold, aGeneratedPoints );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static float distanceFromPointToLine( const VECTOR2D& aPoint, const VECTOR2D& aLineStart,
|
||||||
|
const VECTOR2D& aLineEnd )
|
||||||
|
{
|
||||||
|
auto lineDirection = aLineEnd - aLineStart;
|
||||||
|
auto lineNormal = lineDirection.Perpendicular().Resize( 1.f );
|
||||||
|
auto lineStartToPoint = aPoint - aLineStart;
|
||||||
|
|
||||||
|
auto distance = lineNormal.Dot( lineStartToPoint );
|
||||||
|
|
||||||
|
return fabs( distance );
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 CERN
|
||||||
|
* @author Janito V. Ferreira Filho <janito.vff@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you may find one here:
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||||
|
* or you may write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SVG_IMPORT_PLUGIN_H
|
||||||
|
#define SVG_IMPORT_PLUGIN_H
|
||||||
|
|
||||||
|
#include "nanosvg.h"
|
||||||
|
|
||||||
|
#include "graphics_import_plugin.h"
|
||||||
|
//#include "drw_interface.h"
|
||||||
|
#include "convert_to_biu.h"
|
||||||
|
#include <math/vector2d.h>
|
||||||
|
|
||||||
|
|
||||||
|
class SVG_IMPORT_PLUGIN : public GRAPHICS_IMPORT_PLUGIN
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const wxString GetName() const override
|
||||||
|
{
|
||||||
|
return "Scalable Vector Graphics";
|
||||||
|
}
|
||||||
|
|
||||||
|
const wxArrayString GetFileExtensions() const override
|
||||||
|
{
|
||||||
|
return wxArrayString( 1, { "svg" } );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Import(float aXScale, float aYScale) override;
|
||||||
|
bool Load( const wxString& aFileName ) override;
|
||||||
|
|
||||||
|
virtual unsigned int GetImageHeight() const override
|
||||||
|
{
|
||||||
|
if( !m_parsedImage )
|
||||||
|
{
|
||||||
|
wxASSERT_MSG(false, "Image must have been loaded before checking height");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Millimeter2iu( m_parsedImage->height );
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual unsigned int GetImageWidth() const override
|
||||||
|
{
|
||||||
|
if( !m_parsedImage )
|
||||||
|
{
|
||||||
|
wxASSERT_MSG(false, "Image must have been loaded before checking width");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Millimeter2iu( m_parsedImage->width );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
void DrawPath( const float* aPoints, int aNumPoints, bool aClosedPath );
|
||||||
|
|
||||||
|
void DrawCubicBezierPath( const float* aPoints, int aNumPoints,
|
||||||
|
std::vector< VECTOR2D >& aGeneratedPoints );
|
||||||
|
|
||||||
|
void DrawCubicBezierCurve( const float* aPoints,
|
||||||
|
std::vector< VECTOR2D >& aGeneratedPoints );
|
||||||
|
|
||||||
|
void DrawPolygon( const std::vector< VECTOR2D >& aPoints );
|
||||||
|
void DrawLineSegments( const std::vector< VECTOR2D >& aPoints );
|
||||||
|
|
||||||
|
struct NSVGimage* m_parsedImage;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* SVG_IMPORT_PLUGIN_H */
|
|
@ -33,6 +33,7 @@
|
||||||
#include <pcbnew_id.h>
|
#include <pcbnew_id.h>
|
||||||
#include <confirm.h>
|
#include <confirm.h>
|
||||||
#include <import_dxf/dialog_dxf_import.h>
|
#include <import_dxf/dialog_dxf_import.h>
|
||||||
|
#include <import_gfx/dialog_import_gfx.h>
|
||||||
|
|
||||||
#include <view/view_group.h>
|
#include <view/view_group.h>
|
||||||
#include <view/view_controls.h>
|
#include <view/view_controls.h>
|
||||||
|
@ -738,26 +739,29 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
|
||||||
if( !m_frame->GetModel() )
|
if( !m_frame->GetModel() )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
DIALOG_DXF_IMPORT dlg( m_frame );
|
//DIALOG_DXF_IMPORT dlg( m_frame );
|
||||||
|
DIALOG_IMPORT_GFX dlg( m_frame, m_editModules );
|
||||||
int dlgResult = dlg.ShowModal();
|
int dlgResult = dlg.ShowModal();
|
||||||
|
|
||||||
const std::list<BOARD_ITEM*>& list = dlg.GetImportedItems();
|
/*const std::list<BOARD_ITEM*>*/auto& list = dlg.GetImportedItems();
|
||||||
|
|
||||||
if( dlgResult != wxID_OK || list.empty() )
|
if( dlgResult != wxID_OK || list.empty() )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
VECTOR2I cursorPos = m_controls->GetCursorPosition();
|
|
||||||
VECTOR2I delta = cursorPos - list.front()->GetPosition();
|
|
||||||
|
|
||||||
// Add a VIEW_GROUP that serves as a preview for the new item
|
// Add a VIEW_GROUP that serves as a preview for the new item
|
||||||
SELECTION preview;
|
SELECTION preview;
|
||||||
BOARD_COMMIT commit( m_frame );
|
BOARD_COMMIT commit( m_frame );
|
||||||
|
|
||||||
// Build the undo list & add items to the current view
|
// Build the undo list & add items to the current view
|
||||||
for( auto item : list )
|
//for( auto item : list )
|
||||||
|
for( auto it = list.begin(), itEnd = list.end(); it != itEnd; ++it )
|
||||||
{
|
{
|
||||||
assert( item->Type() == PCB_LINE_T || item->Type() == PCB_TEXT_T );
|
EDA_ITEM* item = it->get();
|
||||||
|
|
||||||
|
wxASSERT( item->Type() == PCB_LINE_T || item->Type() == PCB_TEXT_T );
|
||||||
|
|
||||||
preview.Add( item );
|
preview.Add( item );
|
||||||
|
it->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
BOARD_ITEM* firstItem = static_cast<BOARD_ITEM*>( preview.Front() );
|
BOARD_ITEM* firstItem = static_cast<BOARD_ITEM*>( preview.Front() );
|
||||||
|
@ -771,8 +775,8 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
|
||||||
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DXF );
|
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DXF );
|
||||||
|
|
||||||
// Now move the new items to the current cursor position:
|
// Now move the new items to the current cursor position:
|
||||||
cursorPos = m_controls->GetCursorPosition();
|
VECTOR2I cursorPos = m_controls->GetCursorPosition();
|
||||||
delta = cursorPos - firstItem->GetPosition();
|
VECTOR2I delta = cursorPos - firstItem->GetPosition();
|
||||||
|
|
||||||
for( auto item : preview )
|
for( auto item : preview )
|
||||||
static_cast<BOARD_ITEM*>( item )->Move( wxPoint( delta.x, delta.y ) );
|
static_cast<BOARD_ITEM*>( item )->Move( wxPoint( delta.x, delta.y ) );
|
||||||
|
@ -895,7 +899,8 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert( false );
|
wxASSERT_MSG( false,
|
||||||
|
wxString::Format( "item type %d not allowed", item->Type() ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue