24 changed files with 18508 additions and 11 deletions
-
17pcbnew/CMakeLists.txt
-
325pcbnew/import_gfx/dialog_import_gfx.cpp
-
68pcbnew/import_gfx/dialog_import_gfx.h
-
216pcbnew/import_gfx/dialog_import_gfx_base.cpp
-
1963pcbnew/import_gfx/dialog_import_gfx_base.fbp
-
87pcbnew/import_gfx/dialog_import_gfx_base.h
-
976pcbnew/import_gfx/dxf_import_plugin.cpp
-
335pcbnew/import_gfx/dxf_import_plugin.h
-
2992pcbnew/import_gfx/examples/basic_ellipses.dxf
-
7264pcbnew/import_gfx/examples/test_outlines.dxf
-
73pcbnew/import_gfx/graphics_import_mgr.cpp
-
61pcbnew/import_gfx/graphics_import_mgr.h
-
120pcbnew/import_gfx/graphics_import_plugin.h
-
60pcbnew/import_gfx/graphics_importer.cpp
-
235pcbnew/import_gfx/graphics_importer.h
-
72pcbnew/import_gfx/graphics_importer_buffer.cpp
-
167pcbnew/import_gfx/graphics_importer_buffer.h
-
154pcbnew/import_gfx/graphics_importer_pcbnew.cpp
-
119pcbnew/import_gfx/graphics_importer_pcbnew.h
-
6pcbnew/import_gfx/nanosvg.cpp
-
2849pcbnew/import_gfx/nanosvg.h
-
245pcbnew/import_gfx/svg_import_plugin.cpp
-
90pcbnew/import_gfx/svg_import_plugin.h
-
25pcbnew/tools/drawing_tool.cpp
@ -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 ); |
|||
|
|||
} |
1963
pcbnew/import_gfx/dialog_import_gfx_base.fbp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -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 |
2992
pcbnew/import_gfx/examples/basic_ellipses.dxf
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
7264
pcbnew/import_gfx/examples/test_outlines.dxf
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -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"
|
2849
pcbnew/import_gfx/nanosvg.h
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -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 */ |
Write
Preview
Loading…
Cancel
Save
Reference in new issue