Merge branch 'add-orcad-importer' into 'master'
Draft: Add OrCAD Library (OLB) Importer See merge request kicad/code/kicad!1963
This commit is contained in:
commit
a9d40aa34c
|
@ -46,6 +46,10 @@ endif()
|
|||
|
||||
project( kicad )
|
||||
|
||||
if( NOT DEFINED OPENORCADPARSER_PATH )
|
||||
set(OPENORCADPARSER_PATH "/YOUR/PATH/TO/OpenOrcadParser")
|
||||
endif()
|
||||
|
||||
# Create a default build type for our QA that doesn't include `NDEBUG`
|
||||
set(CMAKE_CXX_FLAGS_QABUILD "-Os -g1 -ggdb1")
|
||||
|
||||
|
|
|
@ -468,6 +468,8 @@ set( COMMON_IO_SRCS
|
|||
io/cadstar/cadstar_archive_parser.cpp
|
||||
io/cadstar/cadstar_parts_lib_parser.cpp
|
||||
|
||||
# OrCAD
|
||||
|
||||
# Eagle
|
||||
io/eagle/eagle_parser.cpp
|
||||
|
||||
|
|
|
@ -140,6 +140,10 @@ const std::string FILEEXT::ProjectLocalSettingsFileExtension( "kicad_prl" );
|
|||
const std::string FILEEXT::LegacySchematicFileExtension( "sch" );
|
||||
const std::string FILEEXT::CadstarSchematicFileExtension( "csa" );
|
||||
const std::string FILEEXT::CadstarPartsLibraryFileExtension( "lib" );
|
||||
const std::string FILEEXT::OrCadDesignFileExtension( "DSN" );
|
||||
const std::string FILEEXT::OrCadDesignBackupFileExtension( "DBK" );
|
||||
const std::string FILEEXT::OrCadLibraryFileExtension( "OLB" );
|
||||
const std::string FILEEXT::OrCadLibraryBackupFileExtension( "OBK" );
|
||||
const std::string FILEEXT::KiCadSchematicFileExtension( "kicad_sch" );
|
||||
const std::string FILEEXT::SpiceFileExtension( "cir" );
|
||||
const std::string FILEEXT::CadstarNetlistFileExtension( "frp" );
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
include(FetchContent)
|
||||
|
||||
# Add all the warnings to the files
|
||||
if( COMPILER_SUPPORTS_WARNINGS )
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARN_FLAGS_CXX}")
|
||||
|
@ -26,6 +28,24 @@ set_property( SOURCE sim/ngspice.cpp
|
|||
NGSPICE_DLL_FILE="${NGSPICE_DLL_FILE}"
|
||||
)
|
||||
|
||||
set(SPDLOG_FMT_EXTERNAL OFF CACHE BOOL "Use external fmt library" FORCE)
|
||||
set(SPDLOG_FMT_EXTERNAL_HO OFF CACHE BOOL "Use external fmt library" FORCE)
|
||||
|
||||
FetchContent_Declare(
|
||||
spdlog
|
||||
GIT_REPOSITORY https://github.com/gabime/spdlog
|
||||
GIT_TAG v1.14.1
|
||||
)
|
||||
FetchContent_MakeAvailable(spdlog)
|
||||
|
||||
FetchContent_Declare(
|
||||
nameof
|
||||
GIT_REPOSITORY https://github.com/Neargye/nameof
|
||||
GIT_TAG v0.10.4
|
||||
)
|
||||
FetchContent_MakeAvailable(nameof)
|
||||
|
||||
|
||||
include_directories( BEFORE ${INC_BEFORE} )
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}/common
|
||||
|
@ -37,6 +57,9 @@ include_directories(
|
|||
./symbol_editor
|
||||
./tools
|
||||
./widgets
|
||||
${CMAKE_BINARY_DIR}/_deps/spdlog-src/include
|
||||
${CMAKE_BINARY_DIR}/_deps/nameof-src/include
|
||||
${OPENORCADPARSER_PATH}/src
|
||||
)
|
||||
|
||||
set( EESCHEMA_SCH_IO
|
||||
|
@ -74,6 +97,10 @@ set( EESCHEMA_SCH_IO
|
|||
sch_io/cadstar/cadstar_sch_archive_parser.cpp
|
||||
sch_io/cadstar/sch_io_cadstar_archive.cpp
|
||||
|
||||
# OrCAD IO plugin
|
||||
sch_io/orcad/orcad2kicad.cpp
|
||||
sch_io/orcad/sch_io_orcad.cpp
|
||||
|
||||
# LTSpice IO plugin
|
||||
sch_io/ltspice/ltspice_schematic.cpp
|
||||
sch_io/ltspice/sch_io_ltspice.cpp
|
||||
|
@ -550,6 +577,8 @@ set_source_files_properties( ${CMAKE_SOURCE_DIR}/common/single_top.cpp PROPERTIE
|
|||
target_link_libraries( eeschema
|
||||
kicommon
|
||||
${wxWidgets_LIBRARIES}
|
||||
spdlog::spdlog
|
||||
${OPENORCADPARSER_PATH}/build/lib/libOpenOrCadParser.so
|
||||
)
|
||||
|
||||
# the main Eeschema program, in DSO form.
|
||||
|
@ -567,7 +596,9 @@ target_include_directories( eeschema_kiface_objects
|
|||
|
||||
target_link_libraries( eeschema_kiface_objects
|
||||
PUBLIC
|
||||
common )
|
||||
common
|
||||
${OPENORCADPARSER_PATH}/build/lib/libOpenOrCadParser.so
|
||||
)
|
||||
|
||||
# Since we're not using target_link_libraries, we need to explicitly
|
||||
# declare the dependency
|
||||
|
|
|
@ -0,0 +1,544 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 Dominik Wernberger <dominik.wernberger@gmx.de>
|
||||
* Copyright (C) 2024 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 <cmath>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
|
||||
#include "orcad2kicad.h"
|
||||
|
||||
#include <core/typeinfo.h>
|
||||
#include <sch_shape.h>
|
||||
#include <sch_text.h>
|
||||
|
||||
|
||||
// OpenOrcadParser Headers
|
||||
#include "Container.hpp"
|
||||
#include "GetStreamHelper.hpp"
|
||||
#include "PinShape.hpp"
|
||||
#include "Primitives/PrimArc.hpp"
|
||||
#include "Primitives/PrimBezier.hpp"
|
||||
#include "Primitives/PrimLine.hpp"
|
||||
#include "Primitives/PrimPolygon.hpp"
|
||||
#include "Primitives/PrimPolyline.hpp"
|
||||
#include "Primitives/PrimRect.hpp"
|
||||
#include "Streams/StreamPackage.hpp"
|
||||
|
||||
|
||||
SCH_SHAPE* convPrimArc2ARC(const PrimArc* aOrcadObj)
|
||||
{
|
||||
// Kicad does not support elliptical arcs, we approximate
|
||||
// it by straight lines, however arcs are actually not yet
|
||||
// supported!
|
||||
|
||||
const auto p1 = VECTOR2I( convDimIU( aOrcadObj->x1 ), convDimIU( aOrcadObj->y1 ) );
|
||||
const auto p2 = VECTOR2I( convDimIU( aOrcadObj->x2 ), convDimIU( aOrcadObj->y2 ) );
|
||||
const auto start = VECTOR2I( convDimIU( aOrcadObj->startX ), convDimIU( aOrcadObj->startY ) );
|
||||
const auto end = VECTOR2I( convDimIU( aOrcadObj->endX ), convDimIU( aOrcadObj->endY ) );
|
||||
|
||||
// if( isCircle( p1, p2 ) )
|
||||
// {
|
||||
// std::unique_ptr<SCH_SHAPE> kicadObj = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC, LAYER_DEVICE );
|
||||
|
||||
// // Circle radius
|
||||
// double r = std::abs( p1.x - p2.x ) / 2.0;
|
||||
|
||||
// // Point between end and start point
|
||||
// VECTOR2D m1 = start + (end - start) / 2.0;
|
||||
|
||||
// // Center Point
|
||||
// VECTOR2D c = VECTOR2D( p1.x + r, p1.y + r );
|
||||
|
||||
// // Vector from center to m1
|
||||
// VECTOR2D m2 = m1 - c;
|
||||
|
||||
// double len_m2 = m2.EuclideanNorm();
|
||||
// VECTOR2D mid_d = m2 / len_m2 * r;
|
||||
|
||||
// VECTOR2I mid = VECTOR2I( static_cast<int32_t>( std::round( mid_d.x ) ), static_cast<int32_t>( std::round( mid_d.y ) ));
|
||||
|
||||
// kicadObj->SetArcGeometry( end, mid, start );
|
||||
|
||||
// ksymbol->AddDrawItem( kicadObj.release() );
|
||||
// }
|
||||
|
||||
auto segment = createEllipsoide( p1, p2, start, end );
|
||||
|
||||
auto stroke = STROKE_PARAMS{};
|
||||
stroke.SetLineStyle( LineStyle2LINE_STYLE.at( aOrcadObj->getLineStyle() ) );
|
||||
stroke.SetWidth( LineWidth2Width.at( aOrcadObj->getLineWidth() ) );
|
||||
// stroke.SetColor( KIGFX::COLOR4D{0.0, 0.0, 0.0, 1.0} );
|
||||
|
||||
// for( auto& segment : segments )
|
||||
{
|
||||
segment->SetStroke( stroke );
|
||||
}
|
||||
|
||||
return segment;
|
||||
}
|
||||
|
||||
|
||||
std::vector<SCH_SHAPE*> convPrimBezier2BEZIER(const PrimBezier* aOrcadObj)
|
||||
{
|
||||
const int segments = static_cast<int>( ( aOrcadObj->points.size() - 1 ) / 3 );
|
||||
|
||||
auto stroke = STROKE_PARAMS{};
|
||||
stroke.SetLineStyle( LineStyle2LINE_STYLE.at( aOrcadObj->getLineStyle() ) );
|
||||
stroke.SetWidth( LineWidth2Width.at( aOrcadObj->getLineWidth() ) );
|
||||
// stroke.SetColor( KIGFX::COLOR4D{0.0, 0.0, 0.0, 1.0} );
|
||||
|
||||
std::vector<SCH_SHAPE*> segmentsVec;
|
||||
|
||||
for( int i = 0; i < segments; ++i )
|
||||
{
|
||||
const auto start = VECTOR2I( convDimIU( aOrcadObj->points.at(i + 0).x ), convDimIU( aOrcadObj->points.at(i + 0).y ) );
|
||||
const auto c1 = VECTOR2I( convDimIU( aOrcadObj->points.at(i + 1).x ), convDimIU( aOrcadObj->points.at(i + 1).y ) );
|
||||
const auto c2 = VECTOR2I( convDimIU( aOrcadObj->points.at(i + 2).x ), convDimIU( aOrcadObj->points.at(i + 2).y ) );
|
||||
const auto end = VECTOR2I( convDimIU( aOrcadObj->points.at(i + 3).x ), convDimIU( aOrcadObj->points.at(i + 3).y ) );
|
||||
|
||||
SCH_SHAPE* kicadObj = new SCH_SHAPE( SHAPE_T::BEZIER, LAYER_DEVICE );
|
||||
|
||||
kicadObj->SetStroke( stroke );
|
||||
|
||||
kicadObj->SetStart( start );
|
||||
kicadObj->SetBezierC1( c1 );
|
||||
kicadObj->SetBezierC2( c2 );
|
||||
kicadObj->SetEnd( end );
|
||||
|
||||
segmentsVec.push_back( kicadObj );
|
||||
}
|
||||
|
||||
return segmentsVec;
|
||||
}
|
||||
|
||||
|
||||
SCH_TEXT* convPrimCommentText2SCH_TEXT(const PrimCommentText* aOrcadObj)
|
||||
{
|
||||
int32_t width = aOrcadObj->x2 - aOrcadObj->x1;
|
||||
int32_t height = aOrcadObj->y2 - aOrcadObj->y1;
|
||||
|
||||
VECTOR2I pos = VECTOR2I( convDimIU( aOrcadObj->locX + width / 2 ), convDimIU( aOrcadObj->locY + height / 2 ) );
|
||||
|
||||
wxString text = {aOrcadObj->name.c_str(), wxConvUTF8};
|
||||
|
||||
SCH_TEXT* kicadObj = new SCH_TEXT( pos, text, LAYER_NOTES, SCH_TEXT_T );
|
||||
|
||||
return kicadObj;
|
||||
}
|
||||
|
||||
|
||||
SCH_SHAPE* convPrimEllipse2POLY(const PrimEllipse* aOrcadObj)
|
||||
{
|
||||
FILL_T fill;
|
||||
|
||||
switch( aOrcadObj->getFillStyle() )
|
||||
{
|
||||
case FillStyle::Solid:
|
||||
fill = FILL_T::FILLED_SHAPE;
|
||||
break;
|
||||
case FillStyle::None:
|
||||
fill = FILL_T::NO_FILL;
|
||||
break;
|
||||
default: // Hatching is not supported in Kicad
|
||||
fill = FILL_T::NO_FILL;
|
||||
break;
|
||||
}
|
||||
|
||||
const auto p1 = VECTOR2I( convDimIU( aOrcadObj->x1 ), convDimIU( aOrcadObj->y1 ) );
|
||||
const auto p2 = VECTOR2I( convDimIU( aOrcadObj->x2 ), convDimIU( aOrcadObj->y2 ) );
|
||||
|
||||
auto kicadObj = createEllipsoide( p1, p2, fill );
|
||||
|
||||
auto stroke = STROKE_PARAMS{};
|
||||
stroke.SetLineStyle( LineStyle2LINE_STYLE.at( aOrcadObj->getLineStyle() ) );
|
||||
stroke.SetWidth( LineWidth2Width.at( aOrcadObj->getLineWidth() ) );
|
||||
// stroke.SetColor( KIGFX::COLOR4D{0.0, 0.0, 0.0, 1.0} );
|
||||
kicadObj->SetStroke( stroke );
|
||||
|
||||
return kicadObj;
|
||||
}
|
||||
|
||||
|
||||
SCH_SHAPE* convPrimLine2POLY(const PrimLine* aOrcadObj)
|
||||
{
|
||||
SCH_SHAPE* kicadObj = new SCH_SHAPE( SHAPE_T::POLY, LAYER_DEVICE );
|
||||
|
||||
auto stroke = STROKE_PARAMS{};
|
||||
stroke.SetLineStyle( LineStyle2LINE_STYLE.at( aOrcadObj->getLineStyle() ) );
|
||||
stroke.SetWidth( LineWidth2Width.at( aOrcadObj->getLineWidth() ) );
|
||||
// stroke.SetColor( KIGFX::COLOR4D{0.0, 0.0, 0.0, 1.0} );
|
||||
kicadObj->SetStroke( stroke );
|
||||
|
||||
kicadObj->AddPoint( VECTOR2I( convDimIU( aOrcadObj->x1 ), convDimIU( aOrcadObj->y1 ) ) );
|
||||
kicadObj->AddPoint( VECTOR2I( convDimIU( aOrcadObj->x2 ), convDimIU( aOrcadObj->y2 ) ) );
|
||||
|
||||
return kicadObj;
|
||||
}
|
||||
|
||||
|
||||
SCH_SHAPE* convPrimPolygon2POLY(const PrimPolygon* aOrcadObj)
|
||||
{
|
||||
FILL_T fill;
|
||||
|
||||
switch( aOrcadObj->fillStyle )
|
||||
{
|
||||
case FillStyle::Solid:
|
||||
fill = FILL_T::FILLED_SHAPE;
|
||||
break;
|
||||
case FillStyle::None:
|
||||
fill = FILL_T::NO_FILL;
|
||||
break;
|
||||
default: // Hatching is not supported in Kicad
|
||||
fill = FILL_T::NO_FILL;
|
||||
break;
|
||||
}
|
||||
|
||||
SCH_SHAPE* kicadObj = new SCH_SHAPE( SHAPE_T::POLY, LAYER_DEVICE, 0, fill );
|
||||
|
||||
auto stroke = STROKE_PARAMS{};
|
||||
stroke.SetLineStyle( LineStyle2LINE_STYLE.at( aOrcadObj->getLineStyle() ) );
|
||||
stroke.SetWidth( LineWidth2Width.at( aOrcadObj->getLineWidth() ) );
|
||||
// stroke.SetColor( KIGFX::COLOR4D{0.0, 0.0, 0.0, 1.0} );
|
||||
kicadObj->SetStroke( stroke );
|
||||
|
||||
for( const auto& point : aOrcadObj->points )
|
||||
{
|
||||
kicadObj->AddPoint( VECTOR2I( convDimIU( point.x ), convDimIU( point.y ) ) );
|
||||
}
|
||||
|
||||
return kicadObj;
|
||||
}
|
||||
|
||||
|
||||
SCH_SHAPE* convPrimPolyline2POLY(const PrimPolyline* aOrcadObj)
|
||||
{
|
||||
SCH_SHAPE* kicadObj = new SCH_SHAPE( SHAPE_T::POLY, LAYER_DEVICE );
|
||||
|
||||
auto stroke = STROKE_PARAMS{};
|
||||
stroke.SetLineStyle( LineStyle2LINE_STYLE.at( aOrcadObj->getLineStyle() ) );
|
||||
stroke.SetWidth( LineWidth2Width.at( aOrcadObj->getLineWidth() ) );
|
||||
// stroke.SetColor( KIGFX::COLOR4D{0.0, 0.0, 0.0, 1.0} );
|
||||
kicadObj->SetStroke( stroke );
|
||||
|
||||
for( const auto& point : aOrcadObj->points )
|
||||
{
|
||||
kicadObj->AddPoint( VECTOR2I( convDimIU( point.x ), convDimIU( point.y ) ) );
|
||||
}
|
||||
|
||||
return kicadObj;
|
||||
}
|
||||
|
||||
|
||||
SCH_SHAPE* convPrimRect2RECTANGLE(const PrimRect* aOrcadObj)
|
||||
{
|
||||
SCH_SHAPE* kicadObj = new SCH_SHAPE( SHAPE_T::RECTANGLE, LAYER_DEVICE );
|
||||
|
||||
auto stroke = STROKE_PARAMS{};
|
||||
stroke.SetLineStyle( LineStyle2LINE_STYLE.at( aOrcadObj->getLineStyle() ) );
|
||||
stroke.SetWidth( LineWidth2Width.at( aOrcadObj->getLineWidth() ) );
|
||||
// stroke.SetColor( KIGFX::COLOR4D{0.0, 0.0, 0.0, 1.0} );
|
||||
kicadObj->SetStroke( stroke );
|
||||
|
||||
kicadObj->SetPosition( VECTOR2I( 0, 0 ) );
|
||||
kicadObj->SetStart( VECTOR2I( convDimIU( aOrcadObj->x1 ), convDimIU( aOrcadObj->y1 ) ) );
|
||||
kicadObj->SetEnd( VECTOR2I( convDimIU( aOrcadObj->x2 ), convDimIU( aOrcadObj->y2 ) ) );
|
||||
|
||||
return kicadObj;
|
||||
}
|
||||
|
||||
|
||||
int32_t convDimIU(int32_t aOrcadIU)
|
||||
{
|
||||
return aOrcadIU * 2540;
|
||||
}
|
||||
|
||||
|
||||
PIN_ORIENTATION getPinOrientation(const StructSymbolPin* aPin)
|
||||
{
|
||||
if( aPin->startX == aPin->hotptX )
|
||||
{
|
||||
if( aPin->startY > aPin->hotptY)
|
||||
{
|
||||
return PIN_ORIENTATION::PIN_DOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
return PIN_ORIENTATION::PIN_UP;
|
||||
}
|
||||
}
|
||||
|
||||
if( aPin->startY == aPin->hotptY )
|
||||
{
|
||||
if( aPin->startX > aPin->hotptX)
|
||||
{
|
||||
return PIN_ORIENTATION::PIN_RIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return PIN_ORIENTATION::PIN_LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
// Pin orientation is kind of diagonal,
|
||||
// return some dummy value.
|
||||
return PIN_ORIENTATION::PIN_LEFT;
|
||||
}
|
||||
|
||||
|
||||
// aP1, aP2 are the points spanning the bounding rectangle of the ellipsoid
|
||||
// A circle is a special ellipsoid where the bounding rectangle is square
|
||||
bool isCircle(const VECTOR2I& aP1, const VECTOR2I& aP2)
|
||||
{
|
||||
int32_t width = std::abs( aP1.x - aP2.x );
|
||||
int32_t height = std::abs( aP1.y - aP2.y );
|
||||
|
||||
if( width == height )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
SCH_SHAPE* createEllipsoide(const VECTOR2I& aP1, const VECTOR2I& aP2, FILL_T aFill )
|
||||
{
|
||||
auto rect = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE, LAYER_DEVICE );
|
||||
rect->SetPosition( aP1 );
|
||||
rect->SetStart( aP1 );
|
||||
rect->SetEnd( aP2 );
|
||||
|
||||
// Draw bounding rectangle
|
||||
// return rect.release();
|
||||
|
||||
const double r1 = rect->GetRectangleWidth() / 2.0; //!< Radius 1
|
||||
const double r2 = rect->GetRectangleHeight() / 2.0; //!< Radius 2
|
||||
|
||||
// Ellipsoid midpoint
|
||||
const VECTOR2D mid = VECTOR2D( aP1.x + r1, aP1.y + r2 );
|
||||
|
||||
// Number of linear segments we approximate the ellipsoid with
|
||||
const int numberSegments = 100;
|
||||
|
||||
SCH_SHAPE* s = new SCH_SHAPE( SHAPE_T::POLY, LAYER_DEVICE, 0, aFill );
|
||||
|
||||
for(int i = 0; i < numberSegments; ++i)
|
||||
{
|
||||
const double da = 2.0 * std::numbers::pi / (numberSegments - 1);
|
||||
const double x = mid.x + r1 * std::cos(i * da);
|
||||
const double y = mid.y + r2 * std::sin(i * da);
|
||||
const auto p = VECTOR2I( static_cast<int32_t>(std::round(x)), static_cast<int32_t>(std::round(y)) );
|
||||
|
||||
s->AddPoint( p );
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
SCH_SHAPE* createEllipsoide(const VECTOR2I& aP1, const VECTOR2I& aP2, const VECTOR2I& aStart, const VECTOR2I& aEnd )
|
||||
{
|
||||
auto rect = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE, LAYER_DEVICE );
|
||||
rect->SetPosition( aP1 );
|
||||
rect->SetStart( aP1 );
|
||||
rect->SetEnd( aP2 );
|
||||
|
||||
const double r1 = rect->GetRectangleWidth() / 2.0; //!< Radius 1
|
||||
const double r2 = rect->GetRectangleHeight() / 2.0; //!< Radius 2
|
||||
|
||||
// Ellipsoid midpoint
|
||||
const VECTOR2D mid = VECTOR2D( aP1.x + r1, aP1.y + r2 );
|
||||
|
||||
const VECTOR2D startVec = aStart - mid;
|
||||
const VECTOR2D endVec = aEnd - mid;
|
||||
|
||||
const VECTOR2D normX = VECTOR2D( 1.0, 0.0 );
|
||||
|
||||
const double phi_start = std::acos( (startVec.x * normX.x + startVec.y * normX.y ) / ( startVec.EuclideanNorm() * normX.EuclideanNorm() ) );
|
||||
const double phi_end = std::acos( (endVec.x * normX.x + endVec.y * normX.y ) / ( endVec.EuclideanNorm() * normX.EuclideanNorm() ) );
|
||||
|
||||
double delta_phi = ( endVec.x * startVec.x + endVec.y * startVec.y ) / ( endVec.EuclideanNorm() * startVec.EuclideanNorm() );
|
||||
delta_phi = std::acos( delta_phi );
|
||||
|
||||
// Number of linear segments we approximate the ellipsoid with
|
||||
const int numberSegments = 100;
|
||||
|
||||
SCH_SHAPE* s = new SCH_SHAPE( SHAPE_T::POLY, LAYER_DEVICE );
|
||||
|
||||
double phi = phi_end;
|
||||
// double delta_phi = (phi_end - phi_start) - 360;
|
||||
|
||||
for(int i = 0; i < numberSegments; ++i)
|
||||
{
|
||||
const double da = delta_phi / (numberSegments - 1);
|
||||
const double x = mid.x + r1 * std::cos(i * da + phi);
|
||||
const double y = mid.y + r2 * std::sin(i * da + phi);
|
||||
const auto p = VECTOR2I( static_cast<int32_t>(std::round(x)), static_cast<int32_t>(std::round(y)) );
|
||||
|
||||
s->AddPoint( p );
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
// OrCAD uses trailing backslashes after each character to
|
||||
// indicate a overbar over that character.
|
||||
// E.g. OrCAD `R\E\S\E\T\` becomes KiCAD `~{RESET}`
|
||||
wxString convPinName( const std::string& aOrCadPinName )
|
||||
{
|
||||
struct CharProp
|
||||
{
|
||||
CharProp() : str{}, hasOverbar{false} { }
|
||||
CharProp(const std::string& aStr, bool aHasOverbar) : str{aStr}, hasOverbar{aHasOverbar} { }
|
||||
|
||||
std::string str;
|
||||
bool hasOverbar;
|
||||
};
|
||||
|
||||
std::deque<CharProp> charProps;
|
||||
|
||||
for( const auto& c : aOrCadPinName )
|
||||
{
|
||||
if( c == '\\' )
|
||||
{
|
||||
if( !charProps.empty() )
|
||||
{
|
||||
charProps.back().hasOverbar = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
charProps.push_back( {std::string{c}, false} );
|
||||
}
|
||||
}
|
||||
|
||||
std::deque<CharProp> strProps;
|
||||
|
||||
// Combine multiple successive short overbars to one large
|
||||
for( const auto& charProp : charProps )
|
||||
{
|
||||
if( strProps.empty() )
|
||||
{
|
||||
strProps.push_back( charProp );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( (charProp.hasOverbar && strProps.back().hasOverbar) ||
|
||||
(!charProp.hasOverbar && !strProps.back().hasOverbar ) )
|
||||
{
|
||||
strProps.back().str += charProp.str;
|
||||
}
|
||||
else
|
||||
{
|
||||
strProps.push_back( charProp );
|
||||
}
|
||||
}
|
||||
|
||||
std::string kicadPinName{};
|
||||
|
||||
for( const auto& strProp : strProps )
|
||||
{
|
||||
if( strProp.hasOverbar )
|
||||
{
|
||||
kicadPinName += std::string{"~{"} + strProp.str + std::string{"}"};
|
||||
}
|
||||
else
|
||||
{
|
||||
kicadPinName += strProp.str;
|
||||
}
|
||||
}
|
||||
|
||||
return wxString{kicadPinName.c_str(), wxConvUTF8};
|
||||
}
|
||||
|
||||
|
||||
SCH_PIN* StreamPackage2SCH_PIN( const StreamPackage* aOrcadStream, LIB_SYMBOL* aSymbol, uint32_t aIdx )
|
||||
{
|
||||
if( !aOrcadStream )
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if( aOrcadStream->libraryParts.empty() )
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
StructSymbolPin* pkgPin = nullptr;
|
||||
|
||||
if( aIdx < aOrcadStream->libraryParts.at( 0 )->symbolPins.size() )
|
||||
{
|
||||
pkgPin = aOrcadStream->libraryParts.at( 0 )->symbolPins.at( aIdx ).get();
|
||||
}
|
||||
|
||||
if( !pkgPin )
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SCH_PIN* pin = new SCH_PIN( aSymbol );
|
||||
|
||||
pin->SetName( convPinName( pkgPin->name ) );
|
||||
|
||||
const GRAPHIC_PINSHAPE shape = OrCad2Kicad_PinShape.at( ToShapeType( pkgPin->pinShape ) );
|
||||
pin->SetShape( shape );
|
||||
|
||||
wxString pinNumber = wxString{"", wxConvUTF8};
|
||||
|
||||
do
|
||||
{
|
||||
if( !aOrcadStream->package )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if( aOrcadStream->package->devices.empty() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if( !aOrcadStream->package->devices.at( 0 ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if( aIdx < aOrcadStream->package->devices.at( 0 )->pinMap.size() )
|
||||
{
|
||||
pinNumber = wxString{aOrcadStream->package->devices.at( 0 )->pinMap.at( aIdx ).c_str(), wxConvUTF8};
|
||||
}
|
||||
}
|
||||
while( false );
|
||||
|
||||
pin->SetNumber( pinNumber );
|
||||
|
||||
const auto pinOrientation = getPinOrientation( pkgPin );
|
||||
pin->SetOrientation( pinOrientation );
|
||||
pin->SetType( OrCad2Kicad_PinType.at( pkgPin->portType ) );
|
||||
pin->SetLength( convDimIU( pkgPin->getPinLength() ) );
|
||||
pin->SetPosition( VECTOR2I( convDimIU ( pkgPin->hotptX ), convDimIU( pkgPin->hotptY ) ) );
|
||||
|
||||
return pin;
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 Dominik Wernberger <dominik.wernberger@gmx.de>
|
||||
* Copyright (C) 2024 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 <map>
|
||||
|
||||
#include <pin_type.h>
|
||||
#include <sch_pin.h>
|
||||
#include <sch_shape.h>
|
||||
#include <sch_text.h>
|
||||
|
||||
// OpenOrcadParser Headers
|
||||
#include "Enums/LineStyle.hpp"
|
||||
#include "Enums/LineWidth.hpp"
|
||||
#include "PinShape.hpp"
|
||||
#include "Primitives/PrimArc.hpp"
|
||||
#include "Primitives/PrimBezier.hpp"
|
||||
#include "Primitives/PrimCommentText.hpp"
|
||||
#include "Primitives/PrimEllipse.hpp"
|
||||
#include "Primitives/PrimLine.hpp"
|
||||
#include "Primitives/PrimPolygon.hpp"
|
||||
#include "Primitives/PrimPolyline.hpp"
|
||||
#include "Primitives/PrimRect.hpp"
|
||||
#include "Streams/StreamPackage.hpp"
|
||||
#include "Structures/StructSymbolPin.hpp"
|
||||
|
||||
|
||||
SCH_SHAPE* convPrimArc2ARC(const PrimArc* aObj);
|
||||
std::vector<SCH_SHAPE*> convPrimBezier2BEZIER(const PrimBezier* aOrcadObj);
|
||||
SCH_TEXT* convPrimCommentText2SCH_TEXT(const PrimCommentText* aOrcadObj);
|
||||
SCH_SHAPE* convPrimEllipse2POLY(const PrimEllipse* aOrcadObj);
|
||||
SCH_SHAPE* convPrimLine2POLY(const PrimLine* aOrcadObj);
|
||||
SCH_SHAPE* convPrimPolyline2POLY(const PrimPolyline* aOrcadObj);
|
||||
SCH_SHAPE* convPrimPolygon2POLY(const PrimPolygon* aOrcadObj);
|
||||
SCH_SHAPE* convPrimRect2RECTANGLE(const PrimRect* aOrcadObj);
|
||||
int32_t convDimIU(int32_t aOrcadIU);
|
||||
PIN_ORIENTATION getPinOrientation(int32_t aStartX, int32_t aStartY, int32_t aHotptX, int32_t aHotptY);
|
||||
bool isCircle(const VECTOR2I& aP1, const VECTOR2I& aP2);
|
||||
SCH_SHAPE* createEllipsoide(const VECTOR2I& aP1, const VECTOR2I& aP2, FILL_T aFill = FILL_T::NO_FILL);
|
||||
SCH_SHAPE* createEllipsoide(const VECTOR2I& aP1, const VECTOR2I& aP2, const VECTOR2I& aStart, const VECTOR2I& aEnd );
|
||||
SCH_PIN* StreamPackage2SCH_PIN( const StreamPackage* aOrcadStream, LIB_SYMBOL* aSymbol, uint32_t aIdx );
|
||||
|
||||
|
||||
const std::map<ShapeType, GRAPHIC_PINSHAPE> OrCad2Kicad_PinShape = {
|
||||
{ShapeType::Clock, GRAPHIC_PINSHAPE::CLOCK},
|
||||
{ShapeType::Dot, GRAPHIC_PINSHAPE::INVERTED},
|
||||
{ShapeType::DotClock, GRAPHIC_PINSHAPE::INVERTED_CLOCK},
|
||||
{ShapeType::Line, GRAPHIC_PINSHAPE::LINE},
|
||||
{ShapeType::Short, GRAPHIC_PINSHAPE::LINE},
|
||||
{ShapeType::ShortClock, GRAPHIC_PINSHAPE::CLOCK},
|
||||
{ShapeType::ShortDot, GRAPHIC_PINSHAPE::INVERTED},
|
||||
{ShapeType::ShortDotClock, GRAPHIC_PINSHAPE::INVERTED_CLOCK},
|
||||
{ShapeType::ZeroLength, GRAPHIC_PINSHAPE::LINE}
|
||||
};
|
||||
|
||||
|
||||
const std::map<PortType, ELECTRICAL_PINTYPE> OrCad2Kicad_PinType = {
|
||||
{PortType::Input, ELECTRICAL_PINTYPE::PT_INPUT},
|
||||
{PortType::Bidirectional, ELECTRICAL_PINTYPE::PT_BIDI},
|
||||
{PortType::Output, ELECTRICAL_PINTYPE::PT_OUTPUT},
|
||||
{PortType::OpenCollector, ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR},
|
||||
{PortType::Passive, ELECTRICAL_PINTYPE::PT_PASSIVE},
|
||||
{PortType::ThreeState, ELECTRICAL_PINTYPE::PT_TRISTATE},
|
||||
{PortType::OpenEmitter, ELECTRICAL_PINTYPE::PT_OPENEMITTER},
|
||||
{PortType::Power, ELECTRICAL_PINTYPE::PT_UNSPECIFIED} // We can't know whether to use PT_POWER_IN or PT_POWER_OUT
|
||||
};
|
||||
|
||||
|
||||
const std::map<LineWidth, int> LineWidth2Width = {
|
||||
{LineWidth::Thin, 3 * 254},
|
||||
{LineWidth::Medium, 9 * 254},
|
||||
{LineWidth::Wide, 12 * 254},
|
||||
{LineWidth::Default, 0} // Defaults to 6 * 254
|
||||
};
|
||||
|
||||
|
||||
const std::map<LineStyle, LINE_STYLE> LineStyle2LINE_STYLE = {
|
||||
{LineStyle::Solid, LINE_STYLE::SOLID},
|
||||
{LineStyle::Dash, LINE_STYLE::DASH},
|
||||
{LineStyle::Dot, LINE_STYLE::DOT},
|
||||
{LineStyle::DashDot, LINE_STYLE::DASHDOT},
|
||||
{LineStyle::DashDotDot, LINE_STYLE::DASHDOTDOT},
|
||||
{LineStyle::Default, LINE_STYLE::DEFAULT}
|
||||
};
|
|
@ -0,0 +1,397 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 Dominik Wernberger <dominik.wernberger@gmx.de>
|
||||
* Copyright (C) 2024 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 <cmath>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
|
||||
#include "sch_io_orcad.h"
|
||||
#include "orcad2kicad.h"
|
||||
|
||||
#include <kiplatform/environment.h>
|
||||
#include <project_sch.h>
|
||||
#include <sch_screen.h>
|
||||
#include <sch_shape.h>
|
||||
#include <sch_sheet.h>
|
||||
#include <sch_text.h>
|
||||
#include <schematic.h>
|
||||
#include <string_utils.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
|
||||
#include <wx/log.h>
|
||||
#include <wx/stdstream.h>
|
||||
#include <wx/zipstrm.h>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <core/map_helpers.h>
|
||||
#include <wx/wfstream.h>
|
||||
|
||||
// OpenOrcadParser Headers
|
||||
#include "Container.hpp"
|
||||
#include "Enums/DirectoryType.hpp"
|
||||
#include "GetStreamHelper.hpp"
|
||||
#include "PinShape.hpp"
|
||||
#include "Primitives/PrimArc.hpp"
|
||||
#include "Primitives/PrimBezier.hpp"
|
||||
#include "Primitives/PrimCommentText.hpp"
|
||||
#include "Primitives/PrimLine.hpp"
|
||||
#include "Primitives/PrimPolygon.hpp"
|
||||
#include "Primitives/PrimPolyline.hpp"
|
||||
#include "Primitives/PrimRect.hpp"
|
||||
#include "Streams/StreamPackage.hpp"
|
||||
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
|
||||
Database parseDatabase(const wxString& aLibraryPath)
|
||||
{
|
||||
|
||||
const fs::path dbPath{std::string{aLibraryPath.mb_str()}};
|
||||
Container parser{dbPath, ParserConfig{}};
|
||||
|
||||
// ContainerContext& ctx = parser.getContext();
|
||||
|
||||
parser.parseDatabaseFile();
|
||||
|
||||
Database db = parser.getDb();
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
|
||||
void dummy_create_in_schematic(SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet)
|
||||
{
|
||||
std::unique_ptr<LIB_SYMBOL> ksymbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
|
||||
|
||||
LIB_ID libId;
|
||||
libId.Parse( "foo", true );
|
||||
|
||||
ksymbol->SetPower();
|
||||
ksymbol->SetLibId( libId );
|
||||
ksymbol->SetName( "Name" );
|
||||
ksymbol->GetReferenceField().SetText( wxS( "#PWR" ) );
|
||||
ksymbol->GetReferenceField().SetVisible( false );
|
||||
ksymbol->GetValueField().SetText( "Name" );
|
||||
ksymbol->GetValueField().SetVisible( true );
|
||||
ksymbol->SetDescription( wxString::Format( _( "Power symbol creates a global "
|
||||
"label with name '%s'" ),
|
||||
"Name" ) );
|
||||
ksymbol->SetKeyWords( wxS( "power-flag" ) );
|
||||
ksymbol->SetShowPinNames( false );
|
||||
ksymbol->SetShowPinNumbers( false );
|
||||
|
||||
std::unique_ptr<SCH_PIN> pin = std::make_unique<SCH_PIN>( ksymbol.get() );
|
||||
|
||||
pin->SetName( "Name" );
|
||||
pin->SetNumber( wxS( "1" ) );
|
||||
pin->SetOrientation( PIN_ORIENTATION::PIN_DOWN );
|
||||
pin->SetType( ELECTRICAL_PINTYPE::PT_POWER_IN );
|
||||
pin->SetLength( 0 );
|
||||
|
||||
ksymbol->AddDrawItem( pin.release() );
|
||||
|
||||
|
||||
|
||||
LIB_SYMBOL* pwrLibSym = ksymbol.release();
|
||||
|
||||
|
||||
|
||||
std::unique_ptr<SCH_SYMBOL> schSym = std::make_unique<SCH_SYMBOL>(
|
||||
*pwrLibSym, libId, &aSchematic->CurrentSheet(), 0 );
|
||||
|
||||
VECTOR2D pos( 0, 0 );
|
||||
schSym->SetPosition( pos );
|
||||
schSym->SetRef( &aSchematic->CurrentSheet(), "asdf" );
|
||||
|
||||
SCH_SCREEN* screen = aRootSheet->GetScreen();
|
||||
screen->Append( schSym.release() );
|
||||
}
|
||||
|
||||
|
||||
bool SCH_IO_ORCAD::CanReadSchematicFile( const wxString& aFileName ) const
|
||||
{
|
||||
// Not yet supported
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SCH_IO_ORCAD::CanReadLibrary( const wxString& aFileName ) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int SCH_IO_ORCAD::GetModifyHash() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void SCH_IO_ORCAD::EnumerateSymbolLib( wxArrayString& aSymbolNameList,
|
||||
const wxString& aLibraryPath,
|
||||
const STRING_UTF8_MAP* aProperties )
|
||||
{
|
||||
if( !m_db.has_value() )
|
||||
{
|
||||
m_db = parseDatabase( aLibraryPath );
|
||||
}
|
||||
|
||||
const auto dir = getDirectoryStreamFromDb<StreamPackagesDirectory>(
|
||||
m_db.value(), DirectoryType::PackagesDirectory );
|
||||
|
||||
if( dir )
|
||||
{
|
||||
for( const auto& item : dir->items )
|
||||
{
|
||||
std::cout << "Enumerate package " << item.name << std::endl;
|
||||
aSymbolNameList.Add( wxString{item.name.c_str(), wxConvUTF8} );
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Enumerated " << aSymbolNameList.size() << " packages" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void SCH_IO_ORCAD::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
|
||||
const wxString& aLibraryPath,
|
||||
const STRING_UTF8_MAP* aProperties )
|
||||
{
|
||||
wxArrayString aSymbolNameList{};
|
||||
EnumerateSymbolLib( aSymbolNameList, aLibraryPath, aProperties );
|
||||
|
||||
for(const auto& name : aSymbolNameList )
|
||||
{
|
||||
std::cout << "Loading package " << name << std::endl;
|
||||
const auto symbol = LoadSymbol( aLibraryPath, name, aProperties );
|
||||
aSymbolList.push_back( symbol );
|
||||
}
|
||||
|
||||
std::cout << "Loaded " << aSymbolNameList.size() << " packages" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
LIB_SYMBOL* SCH_IO_ORCAD::LoadSymbol( const wxString& aLibraryPath,
|
||||
const wxString& aAliasName,
|
||||
const STRING_UTF8_MAP* aProperties )
|
||||
{
|
||||
std::cout << "Loading " << aAliasName << std::endl;
|
||||
|
||||
if( !m_db.has_value() )
|
||||
{
|
||||
m_db = parseDatabase( aLibraryPath );
|
||||
}
|
||||
|
||||
std::shared_ptr<StreamPackage> package{};
|
||||
|
||||
for( auto& stream : m_db.value().mStreams )
|
||||
{
|
||||
if( stream->mCtx.mCfbfStreamLocation.matches_pattern({{"Packages"}, {std::string{aAliasName.mb_str()}}}) )
|
||||
{
|
||||
package = std::dynamic_pointer_cast<StreamPackage>( stream );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LIB_SYMBOL* ksymbol = new LIB_SYMBOL( wxEmptyString );
|
||||
|
||||
if(package)
|
||||
{
|
||||
wxString name{"Dummy", wxConvUTF8};
|
||||
wxString refDes{"X", wxConvUTF8};
|
||||
wxString pcbFootprint{"", wxConvUTF8};
|
||||
|
||||
if( package->package )
|
||||
{
|
||||
name = wxString{package->package->name.c_str(), wxConvUTF8};
|
||||
refDes = wxString{package->package->refDes.c_str(), wxConvUTF8};
|
||||
pcbFootprint = wxString{package->package->pcbFootprint.c_str(), wxConvUTF8};
|
||||
}
|
||||
|
||||
for( const auto& libraryPart : package->libraryParts )
|
||||
{
|
||||
if( !libraryPart )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for( const auto& primitive : libraryPart->primitives )
|
||||
{
|
||||
switch( primitive->getObjectType() )
|
||||
{
|
||||
case Primitive::Arc:
|
||||
{
|
||||
const auto orcadObj = dynamic_cast<const PrimArc*>( primitive.get() );
|
||||
auto kicadObj = convPrimArc2ARC( orcadObj );
|
||||
ksymbol->AddDrawItem( kicadObj );
|
||||
break;
|
||||
}
|
||||
case Primitive::Bezier:
|
||||
{
|
||||
const auto orcadObj = dynamic_cast<const PrimBezier*>( primitive.get() );
|
||||
auto segments = convPrimBezier2BEZIER( orcadObj );
|
||||
|
||||
for( auto& segment : segments )
|
||||
{
|
||||
ksymbol->AddDrawItem( segment );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case Primitive::CommentText:
|
||||
{
|
||||
const auto orcadObj = dynamic_cast<const PrimCommentText*>( primitive.get() );
|
||||
auto kicadObj = convPrimCommentText2SCH_TEXT( orcadObj );
|
||||
ksymbol->AddDrawItem( kicadObj );
|
||||
break;
|
||||
}
|
||||
case Primitive::Ellipse:
|
||||
{
|
||||
const auto orcadObj = dynamic_cast<const PrimEllipse*>( primitive.get() );
|
||||
auto kicadObj = convPrimEllipse2POLY( orcadObj );
|
||||
ksymbol->AddDrawItem( kicadObj );
|
||||
break;
|
||||
}
|
||||
case Primitive::Line:
|
||||
{
|
||||
const auto orcadObj = dynamic_cast<const PrimLine*>( primitive.get() );
|
||||
auto kicadObj = convPrimLine2POLY( orcadObj );
|
||||
ksymbol->AddDrawItem( kicadObj );
|
||||
break;
|
||||
}
|
||||
case Primitive::Polygon:
|
||||
{
|
||||
const auto orcadObj = dynamic_cast<const PrimPolygon*>( primitive.get() );
|
||||
auto kicadObj = convPrimPolygon2POLY( orcadObj );
|
||||
ksymbol->AddDrawItem( kicadObj );
|
||||
break;
|
||||
}
|
||||
case Primitive::Polyline:
|
||||
{
|
||||
const auto orcadObj = dynamic_cast<const PrimPolyline*>( primitive.get() );
|
||||
auto kicadObj = convPrimPolyline2POLY( orcadObj );
|
||||
ksymbol->AddDrawItem( kicadObj );
|
||||
break;
|
||||
}
|
||||
case Primitive::Rect:
|
||||
{
|
||||
const auto orcadObj = dynamic_cast<const PrimRect*>( primitive.get() );
|
||||
auto kicadObj = convPrimRect2RECTANGLE( orcadObj );
|
||||
ksymbol->AddDrawItem( kicadObj );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
std::cout << "Unimplemented Primitive detected" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for( size_t i = 0U; i < libraryPart->symbolPins.size(); ++i )
|
||||
{
|
||||
auto pin = StreamPackage2SCH_PIN( package.get(), ksymbol, i );
|
||||
|
||||
if( pin )
|
||||
{
|
||||
ksymbol->AddDrawItem( pin );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LIB_ID libId{ wxS( "Library" ), name };
|
||||
|
||||
ksymbol->SetLibId( libId );
|
||||
ksymbol->SetName( name );
|
||||
|
||||
ksymbol->GetReferenceField().SetText( refDes );
|
||||
ksymbol->GetReferenceField().SetVisible( true );
|
||||
|
||||
ksymbol->GetFootprintField().SetText( pcbFootprint );
|
||||
ksymbol->GetFootprintField().SetVisible( false );
|
||||
|
||||
ksymbol->GetValueField().SetText( wxS( "" ) );
|
||||
ksymbol->GetValueField().SetVisible( true );
|
||||
|
||||
bool pinNameVisible = true;
|
||||
bool pinNumberVisible = true;
|
||||
|
||||
if( package && !package->libraryParts.empty() )
|
||||
{
|
||||
const auto& generalProperties = package->libraryParts.at(0)->generalProperties;
|
||||
|
||||
pinNameVisible = generalProperties.pinNameVisible;
|
||||
pinNumberVisible = generalProperties.pinNumberVisible;
|
||||
}
|
||||
|
||||
ksymbol->SetShowPinNames( pinNameVisible );
|
||||
ksymbol->SetShowPinNumbers( pinNumberVisible );
|
||||
}
|
||||
|
||||
return ksymbol;
|
||||
}
|
||||
|
||||
|
||||
SCH_SHEET* SCH_IO_ORCAD::LoadSchematicFile( const wxString& aFileName, SCHEMATIC* aSchematic,
|
||||
SCH_SHEET* aAppendToMe,
|
||||
const STRING_UTF8_MAP* aProperties )
|
||||
{
|
||||
std::cout << "Loading schematic " << std::endl;
|
||||
|
||||
wxCHECK( !aFileName.IsEmpty() && aSchematic, nullptr );
|
||||
|
||||
SCH_SHEET* rootSheet = nullptr;
|
||||
|
||||
if( aAppendToMe )
|
||||
{
|
||||
wxCHECK_MSG( aSchematic->IsValid(), nullptr,
|
||||
wxS( "Can't append to a schematic with no root!" ) );
|
||||
|
||||
rootSheet = &aSchematic->Root();
|
||||
}
|
||||
else
|
||||
{
|
||||
rootSheet = new SCH_SHEET( aSchematic );
|
||||
rootSheet->SetFileName( aFileName );
|
||||
aSchematic->SetRoot( rootSheet );
|
||||
}
|
||||
|
||||
if( !rootSheet->GetScreen() )
|
||||
{
|
||||
SCH_SCREEN* screen = new SCH_SCREEN( aSchematic );
|
||||
|
||||
screen->SetFileName( aFileName );
|
||||
rootSheet->SetScreen( screen );
|
||||
}
|
||||
|
||||
SYMBOL_LIB_TABLE* libTable = PROJECT_SCH::SchSymbolLibTable( &aSchematic->Prj() );
|
||||
|
||||
wxCHECK_MSG( libTable, nullptr, wxS( "Could not load symbol lib table." ) );
|
||||
|
||||
// @todo
|
||||
// LoadSchematic( aSchematic, rootSheet, aFileName );
|
||||
dummy_create_in_schematic(aSchematic, rootSheet);
|
||||
|
||||
aSchematic->CurrentSheet().UpdateAllScreenReferences();
|
||||
|
||||
return rootSheet;
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 Dominik Wernberger <dominik.wernberger@gmx.de>
|
||||
* Copyright (C) 2024 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 SCH_IO_ORCAD_H_
|
||||
#define SCH_IO_ORCAD_H_
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <sch_io/sch_io.h>
|
||||
#include <sch_io/sch_io_mgr.h>
|
||||
#include <reporter.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <wx/arrstr.h>
|
||||
|
||||
// OpenOrcadParser headers
|
||||
#include "Database.hpp"
|
||||
|
||||
|
||||
class SCH_SHEET;
|
||||
class SCH_SCREEN;
|
||||
|
||||
|
||||
class SCH_IO_ORCAD : public SCH_IO
|
||||
{
|
||||
public:
|
||||
SCH_IO_ORCAD() : SCH_IO( wxS( "OrCAD Database" ) ), m_db{}
|
||||
{
|
||||
m_reporter = &WXLOG_REPORTER::GetInstance();
|
||||
}
|
||||
|
||||
~SCH_IO_ORCAD() {}
|
||||
|
||||
const IO_BASE::IO_FILE_DESC GetSchematicFileDesc() const override
|
||||
{
|
||||
return IO_BASE::IO_FILE_DESC( _HKI( "OrCAD Design files" ),
|
||||
{ FILEEXT::OrCadDesignFileExtension, FILEEXT::OrCadDesignBackupFileExtension } );
|
||||
}
|
||||
|
||||
const IO_BASE::IO_FILE_DESC GetLibraryDesc() const override
|
||||
{
|
||||
return IO_BASE::IO_FILE_DESC( _HKI( "OrCAD Library files" ),
|
||||
{ FILEEXT::OrCadLibraryFileExtension, FILEEXT::OrCadLibraryBackupFileExtension } );
|
||||
}
|
||||
|
||||
bool CanReadSchematicFile( const wxString& aFileName ) const override;
|
||||
|
||||
bool CanReadLibrary( const wxString& aFileName ) const override;
|
||||
|
||||
int GetModifyHash() const override;
|
||||
|
||||
SCH_SHEET* LoadSchematicFile( const wxString& aFileName, SCHEMATIC* aSchematic,
|
||||
SCH_SHEET* aAppendToMe = nullptr,
|
||||
const STRING_UTF8_MAP* aProperties = nullptr ) override;
|
||||
|
||||
void EnumerateSymbolLib( wxArrayString& aSymbolNameList, const wxString& aLibraryPath,
|
||||
const STRING_UTF8_MAP* aProperties = nullptr ) override;
|
||||
|
||||
void EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList, const wxString& aLibraryPath,
|
||||
const STRING_UTF8_MAP* aProperties = nullptr ) override;
|
||||
|
||||
LIB_SYMBOL* LoadSymbol( const wxString& aLibraryPath, const wxString& aAliasName,
|
||||
const STRING_UTF8_MAP* aProperties = nullptr ) override;
|
||||
|
||||
bool IsLibraryWritable( const wxString& aLibraryPath ) override { return false; }
|
||||
|
||||
private:
|
||||
std::optional<Database> m_db;
|
||||
};
|
||||
|
||||
|
||||
#endif // SCH_IO_ORCAD_H_
|
|
@ -34,6 +34,7 @@
|
|||
#include <sch_io/easyedapro/sch_io_easyedapro.h>
|
||||
#include <sch_io/database/sch_io_database.h>
|
||||
#include <sch_io/ltspice/sch_io_ltspice.h>
|
||||
#include <sch_io/orcad/sch_io_orcad.h>
|
||||
#include <sch_io/http_lib/sch_io_http_lib.h>
|
||||
#include <common.h> // for ExpandEnvVarSubstitutions
|
||||
|
||||
|
@ -74,6 +75,7 @@ SCH_IO* SCH_IO_MGR::FindPlugin( SCH_FILE_T aFileType )
|
|||
case SCH_EASYEDA: return new SCH_IO_EASYEDA();
|
||||
case SCH_EASYEDAPRO: return new SCH_IO_EASYEDAPRO();
|
||||
case SCH_LTSPICE: return new SCH_IO_LTSPICE();
|
||||
case SCH_ORCAD: return new SCH_IO_ORCAD();
|
||||
case SCH_HTTP: return new SCH_IO_HTTP_LIB();
|
||||
default: return nullptr;
|
||||
}
|
||||
|
@ -97,6 +99,7 @@ const wxString SCH_IO_MGR::ShowType( SCH_FILE_T aType )
|
|||
case SCH_EASYEDA: return wxString( wxT( "EasyEDA (JLCEDA) Std" ) );
|
||||
case SCH_EASYEDAPRO: return wxString( wxT( "EasyEDA (JLCEDA) Pro" ) );
|
||||
case SCH_LTSPICE: return wxString( wxT( "LTspice" ) );
|
||||
case SCH_ORCAD: return wxString( wxT( "OrCAD" ) );
|
||||
case SCH_HTTP: return wxString( wxT( "HTTP" ) );
|
||||
default: return wxString::Format( _( "Unknown SCH_FILE_T value: %d" ),
|
||||
aType );
|
||||
|
@ -128,6 +131,8 @@ SCH_IO_MGR::SCH_FILE_T SCH_IO_MGR::EnumFromStr( const wxString& aType )
|
|||
return SCH_EASYEDAPRO;
|
||||
else if( aType == wxT( "LTspice" ) )
|
||||
return SCH_LTSPICE;
|
||||
else if( aType == wxT( "OrCAD" ) )
|
||||
return SCH_ORCAD;
|
||||
else if( aType == wxT( "HTTP" ) )
|
||||
return SCH_HTTP;
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ public:
|
|||
SCH_EASYEDA, ///< EasyEDA Std schematic file
|
||||
SCH_EASYEDAPRO, ///< EasyEDA Pro archive
|
||||
SCH_LTSPICE, ///< LtSpice Schematic format
|
||||
SCH_ORCAD, ///< OrCAD file format
|
||||
SCH_HTTP, ///< KiCad HTTP library
|
||||
|
||||
// Add your schematic type here.
|
||||
|
|
|
@ -133,6 +133,10 @@ public:
|
|||
static const std::string KiCadSchematicFileExtension;
|
||||
static const std::string SpiceFileExtension;
|
||||
static const std::string CadstarNetlistFileExtension;
|
||||
static const std::string OrCadDesignFileExtension;
|
||||
static const std::string OrCadDesignBackupFileExtension;
|
||||
static const std::string OrCadLibraryFileExtension;
|
||||
static const std::string OrCadLibraryBackupFileExtension;
|
||||
static const std::string OrCadPcb2NetlistFileExtension;
|
||||
static const std::string NetlistFileExtension;
|
||||
static const std::string AllegroNetlistFileExtension;
|
||||
|
|
|
@ -109,6 +109,7 @@ PRIVATE
|
|||
${GDI_PLUS_LIBRARIES}
|
||||
Boost::headers
|
||||
Boost::unit_test_framework
|
||||
${OPENORCADPARSER_PATH}/build/lib/libOpenOrCadParser.so
|
||||
)
|
||||
|
||||
# Eeschema tests, so pretend to be eeschema (for units, etc)
|
||||
|
|
|
@ -93,6 +93,7 @@ PRIVATE
|
|||
${GDI_PLUS_LIBRARIES}
|
||||
Boost::headers
|
||||
Boost::unit_test_framework
|
||||
${OPENORCADPARSER_PATH}/build/lib/libOpenOrCadParser.so
|
||||
)
|
||||
|
||||
if( KICAD_SPICE_QA AND MSVC )
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
#
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
# Disable shared library building for all thirdparty libraries
|
||||
set( BUILD_SHARED_LIBS OFF )
|
||||
|
||||
|
@ -32,6 +34,13 @@ set( BUILD_SHARED_LIBS OFF )
|
|||
# instead of with cmake_policy will apply the change to the third-party CMakeLists files.
|
||||
set( CMAKE_POLICY_DEFAULT_CMP0077 NEW )
|
||||
|
||||
FetchContent_Declare(
|
||||
fmt
|
||||
GIT_REPOSITORY https://github.com/fmtlib/fmt
|
||||
GIT_TAG 10.2.1
|
||||
)
|
||||
FetchContent_MakeAvailable(fmt)
|
||||
|
||||
set( ARGPARSE_INSTALL OFF )
|
||||
add_subdirectory( argparse )
|
||||
add_subdirectory( clipper )
|
||||
|
@ -40,8 +49,8 @@ add_subdirectory( compoundfilereader )
|
|||
add_subdirectory( delaunator )
|
||||
add_subdirectory( dxflib_qcad )
|
||||
add_subdirectory( expected )
|
||||
set( FMT_INSTALL OFF )
|
||||
add_subdirectory( fmt )
|
||||
# set( FMT_INSTALL OFF )
|
||||
# add_subdirectory( fmt )
|
||||
add_subdirectory( gzip-hpp )
|
||||
add_subdirectory( lemon )
|
||||
add_subdirectory( libcontext )
|
||||
|
|
|
@ -30,6 +30,7 @@ message(STATUS "nanodbc compile: C++${CMAKE_CXX_STANDARD}")
|
|||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_COMPILER_IS_GNUCXX)
|
||||
include(CheckCXXCompilerFlag)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive")
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel")
|
||||
string(REGEX REPLACE "[/-]W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
if (NOT (CMAKE_VERSION VERSION_LESS 3.6.0)) # Compiler features for Intel in CMake 3.6+
|
||||
|
|
Loading…
Reference in New Issue