7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-20 23:11:41 +00:00

Implement correct placement of DXF block contained entities

DXF blocks are virtual groups of items.
The insert entity is what actually places all the block contents at a given coordinate.
This should fix importing drawings from professional CAD tools like SolidWorks that will have a good bit of blocks.
This commit is contained in:
Marek Roszko 2020-11-23 09:59:00 -05:00
parent bf59b422bc
commit 32ec8fa928
4 changed files with 182 additions and 46 deletions

View File

@ -263,7 +263,10 @@ DXF_IMPORT_LAYER* DXF_IMPORT_PLUGIN::getImportLayer( const std::string& aLayerNa
if( !layerName.IsEmpty() )
{
auto resultIt = std::find_if( m_layers.begin(), m_layers.end(),
[layerName]( const auto& it ) { return it->m_layerName == layerName; } );
[layerName]( const auto& it )
{
return it->m_layerName == layerName;
} );
if( resultIt != m_layers.end() )
layer = resultIt->get();
@ -273,18 +276,38 @@ DXF_IMPORT_LAYER* DXF_IMPORT_PLUGIN::getImportLayer( const std::string& aLayerNa
}
DXF_IMPORT_BLOCK* DXF_IMPORT_PLUGIN::getImportBlock( const std::string& aBlockName )
{
DXF_IMPORT_BLOCK* block = nullptr;
wxString blockName = wxString::FromUTF8( aBlockName.c_str() );
if( !blockName.IsEmpty() )
{
auto resultIt = std::find_if( m_blocks.begin(), m_blocks.end(),
[blockName]( const auto& it )
{
return it->m_name == blockName;
} );
if( resultIt != m_blocks.end() )
block = resultIt->get();
}
return block;
}
void DXF_IMPORT_PLUGIN::addLine( const DL_LineData& aData )
{
if( m_currentBlock != nullptr )
return;
DXF_IMPORT_LAYER* layer = getImportLayer( attributes.getLayer() );
double lineWidth = lineWeightToWidth( attributes.getWidth(), layer );
VECTOR2D start( mapX( aData.x1 ), mapY( aData.y1 ) );
VECTOR2D end( mapX( aData.x2 ), mapY( aData.y2 ) );
m_internalImporter.AddLine( start, end, lineWidth );
GRAPHICS_IMPORTER_BUFFER* bufferToUse =
( m_currentBlock != nullptr ) ? &m_currentBlock->buffer : &m_internalImporter;
bufferToUse->AddLine( start, end, lineWidth );
updateImageLimits( start );
updateImageLimits( end );
@ -311,9 +334,6 @@ void DXF_IMPORT_PLUGIN::addPolyline(const DL_PolylineData& aData )
void DXF_IMPORT_PLUGIN::addVertex( const DL_VertexData& aData )
{
if( m_currentBlock != nullptr )
return;
if( m_curr_entity.m_EntityParseStatus == 0 )
return; // Error
@ -379,7 +399,8 @@ void DXF_IMPORT_PLUGIN::addBlock( const DL_BlockData& aData )
{
wxString name = wxString::FromUTF8( aData.name.c_str() );
std::unique_ptr<DXF_IMPORT_BLOCK> block = std::make_unique<DXF_IMPORT_BLOCK>( name, aData.bpx, aData.bpy );
std::unique_ptr<DXF_IMPORT_BLOCK> block =
std::make_unique<DXF_IMPORT_BLOCK>( name, aData.bpx, aData.bpy );
m_blocks.push_back( std::move( block ) );
@ -394,21 +415,33 @@ void DXF_IMPORT_PLUGIN::endBlock()
void DXF_IMPORT_PLUGIN::addInsert( const DL_InsertData& aData )
{
wxString blockName = wxString::FromUTF8( aData.name.c_str() );
DXF_IMPORT_BLOCK* block = getImportBlock( aData.name );
if( block == nullptr )
return;
VECTOR2D translation( mapX( aData.ipx ), mapY( aData.ipy ) );
VECTOR2D scale( mapX( aData.sx ), mapY( aData.sy ) );
for( auto& shape : block->buffer.GetShapes() )
{
std::unique_ptr<IMPORTED_SHAPE> newShape = shape->clone();
newShape->Translate( translation );
m_internalImporter.AddShape( newShape );
}
}
void DXF_IMPORT_PLUGIN::addCircle( const DL_CircleData& aData )
{
if( m_currentBlock != nullptr )
return;
VECTOR2D center( mapX( aData.cx ), mapY( aData.cy ) );
DXF_IMPORT_LAYER* layer = getImportLayer( attributes.getLayer() );
double lineWidth = lineWeightToWidth( attributes.getWidth(), layer );
m_internalImporter.AddCircle( center, mapDim( aData.radius ), lineWidth, false );
GRAPHICS_IMPORTER_BUFFER* bufferToUse =
( m_currentBlock != nullptr ) ? &m_currentBlock->buffer : &m_internalImporter;
bufferToUse->AddCircle( center, mapDim( aData.radius ), lineWidth, false );
VECTOR2D radiusDelta( mapDim( aData.radius ), mapDim( aData.radius ) );
@ -442,7 +475,10 @@ void DXF_IMPORT_PLUGIN::addArc( const DL_ArcData& aData )
DXF_IMPORT_LAYER* layer = getImportLayer( attributes.getLayer() );
double lineWidth = lineWeightToWidth( attributes.getWidth(), layer );
m_internalImporter.AddArc( center, arcStart, angle, lineWidth );
GRAPHICS_IMPORTER_BUFFER* bufferToUse =
( m_currentBlock != nullptr ) ? &m_currentBlock->buffer : &m_internalImporter;
bufferToUse->AddArc( center, arcStart, angle, lineWidth );
VECTOR2D radiusDelta( mapDim( aData.radius ), mapDim( aData.radius ) );
@ -453,9 +489,6 @@ void DXF_IMPORT_PLUGIN::addArc( const DL_ArcData& aData )
void DXF_IMPORT_PLUGIN::addText( const DL_TextData& aData )
{
if( m_currentBlock != nullptr )
return;
VECTOR2D refPoint( mapX( aData.ipx ), mapY( aData.ipy ) );
VECTOR2D secPoint( mapX( aData.apx ), mapY( aData.apy ) );
@ -565,8 +598,10 @@ void DXF_IMPORT_PLUGIN::addText( const DL_TextData& aData )
double cosine = cos(angleInRads);
double sine = sin(angleInRads);
m_internalImporter.AddText( refPoint, text, textHeight, charWidth, textThickness,
angle_degree, hJustify, vJustify );
GRAPHICS_IMPORTER_BUFFER* bufferToUse =
( m_currentBlock != nullptr ) ? &m_currentBlock->buffer : &m_internalImporter;
bufferToUse->AddText( refPoint, text, textHeight, charWidth, textThickness, angle_degree,
hJustify, vJustify );
// Calculate the boundary box and update the image limits:
bottomLeft.x = bottomLeft.x * cosine - bottomLeft.y * sine;
@ -596,9 +631,6 @@ void DXF_IMPORT_PLUGIN::addText( const DL_TextData& aData )
void DXF_IMPORT_PLUGIN::addMText( const DL_MTextData& aData )
{
if( m_currentBlock != nullptr )
return;
wxString text = toNativeString( wxString::FromUTF8( aData.text.c_str() ) );
wxString attrib, tmp;
@ -725,8 +757,11 @@ void DXF_IMPORT_PLUGIN::addMText( const DL_MTextData& aData )
double cosine = cos(angleInRads);
double sine = sin(angleInRads);
m_internalImporter.AddText( textpos, text, textHeight, charWidth,
textThickness, angle_degree, hJustify, vJustify );
GRAPHICS_IMPORTER_BUFFER* bufferToUse =
( m_currentBlock != nullptr ) ? &m_currentBlock->buffer : &m_internalImporter;
bufferToUse->AddText( textpos, text, textHeight, charWidth,
textThickness, angle_degree, hJustify, vJustify );
bottomLeft.x = bottomLeft.x * cosine - bottomLeft.y * sine;
bottomLeft.y = bottomLeft.x * sine + bottomLeft.y * cosine;
@ -1057,7 +1092,10 @@ void DXF_IMPORT_PLUGIN::insertLine( const VECTOR2D& aSegStart,
{
VECTOR2D origin( SCALE_FACTOR( aSegStart.x ), SCALE_FACTOR( aSegStart.y ) );
VECTOR2D end( SCALE_FACTOR( aSegEnd.x ), SCALE_FACTOR( aSegEnd.y ) );
m_internalImporter.AddLine( origin, end, aWidth );
GRAPHICS_IMPORTER_BUFFER* bufferToUse =
( m_currentBlock != nullptr ) ? &m_currentBlock->buffer : &m_internalImporter;
bufferToUse->AddLine( origin, end, aWidth );
updateImageLimits( origin );
updateImageLimits( end );
@ -1132,7 +1170,9 @@ void DXF_IMPORT_PLUGIN::insertArc( const VECTOR2D& aSegStart, const VECTOR2D& aS
angle = -angle;
}
m_internalImporter.AddArc( center, arc_start, angle, aWidth );
GRAPHICS_IMPORTER_BUFFER* bufferToUse =
( m_currentBlock != nullptr ) ? &m_currentBlock->buffer : &m_internalImporter;
bufferToUse->AddArc( center, arc_start, angle, aWidth );
VECTOR2D radiusDelta( SCALE_FACTOR( radius ), SCALE_FACTOR( radius ) );
@ -1211,7 +1251,9 @@ void DXF_IMPORT_PLUGIN::insertSpline( int aWidth )
else
end = bezierControl2;
m_internalImporter.AddSpline( start, bezierControl1, bezierControl2, end , aWidth );
GRAPHICS_IMPORTER_BUFFER* bufferToUse =
( m_currentBlock != nullptr ) ? &m_currentBlock->buffer : &m_internalImporter;
bufferToUse->AddSpline( start, bezierControl1, bezierControl2, end, aWidth );
}
#endif
}

View File

@ -140,6 +140,8 @@ public:
wxString m_name;
double m_x, m_y;
GRAPHICS_IMPORTER_BUFFER buffer;
DXF_IMPORT_BLOCK( wxString aName, double aX, double aY )
{
m_name = aName;
@ -323,6 +325,14 @@ private:
*/
DXF_IMPORT_LAYER* getImportLayer( const std::string& aLayerName );
/**
* Returns the import layer block
*
* @param aBlockName is the raw string from dxflib
* @returns The given block by name or nullptf if not found
*/
DXF_IMPORT_BLOCK* getImportBlock( const std::string& aBlockName );
// Functions to aid in the creation of a Polyline
void insertLine( const VECTOR2D& aSegStart, const VECTOR2D& aSegEnd, int aWidth );
void insertArc( const VECTOR2D& aSegStart, const VECTOR2D& aSegEnd,

View File

@ -74,6 +74,12 @@ void GRAPHICS_IMPORTER_BUFFER::AddSpline( const VECTOR2D& aStart, const VECTOR2D
}
void GRAPHICS_IMPORTER_BUFFER::AddShape( std::unique_ptr<IMPORTED_SHAPE>& aShape )
{
m_shapes.push_back( std::move( aShape ) );
}
void GRAPHICS_IMPORTER_BUFFER::ImportTo( GRAPHICS_IMPORTER& aImporter )
{
for( auto& shape : m_shapes )

View File

@ -35,6 +35,10 @@ class IMPORTED_SHAPE
public:
virtual ~IMPORTED_SHAPE() {}
virtual void ImportTo( GRAPHICS_IMPORTER& aImporter ) const = 0;
virtual std::unique_ptr<IMPORTED_SHAPE> clone() const = 0;
virtual void Translate( const VECTOR2D& aVec ) = 0;
};
@ -53,10 +57,21 @@ public:
aImporter.AddLine( m_start, m_end, m_width );
}
virtual std::unique_ptr<IMPORTED_SHAPE> clone() const override
{
return std::make_unique<IMPORTED_LINE>( *this );
}
void Translate( const VECTOR2D& aVec ) override
{
m_start += aVec;
m_end += aVec;
}
private:
const VECTOR2D m_start;
const VECTOR2D m_end;
double m_width;
VECTOR2D m_start;
VECTOR2D m_end;
double m_width;
};
@ -76,11 +91,21 @@ public:
aImporter.AddCircle( m_center, m_radius, m_width, m_filled );
}
virtual std::unique_ptr<IMPORTED_SHAPE> clone() const override
{
return std::make_unique<IMPORTED_CIRCLE>( *this );
}
void Translate( const VECTOR2D& aVec ) override
{
m_center += aVec;
}
private:
const VECTOR2D m_center;
double m_radius;
double m_width;
bool m_filled;
VECTOR2D m_center;
double m_radius;
double m_width;
bool m_filled;
};
@ -100,11 +125,22 @@ public:
aImporter.AddArc( m_center, m_start, m_angle, m_width );
}
virtual std::unique_ptr<IMPORTED_SHAPE> clone() const override
{
return std::make_unique<IMPORTED_ARC>( *this );
}
void Translate( const VECTOR2D& aVec ) override
{
m_center += aVec;
m_start += aVec;
}
private:
const VECTOR2D m_center;
const VECTOR2D m_start;
double m_angle;
double m_width;
VECTOR2D m_center;
VECTOR2D m_start;
double m_angle;
double m_width;
};
@ -122,8 +158,21 @@ public:
aImporter.AddPolygon( m_vertices, m_width );
}
virtual std::unique_ptr<IMPORTED_SHAPE> clone() const override
{
return std::make_unique<IMPORTED_POLYGON>( *this );
}
void Translate( const VECTOR2D& aVec ) override
{
for( auto& vertex : m_vertices )
{
vertex += aVec;
}
}
private:
const std::vector<VECTOR2D> m_vertices;
std::vector<VECTOR2D> m_vertices;
double m_width;
};
@ -151,8 +200,18 @@ public:
m_thickness, m_orientation, m_hJustify, m_vJustify );
}
virtual std::unique_ptr<IMPORTED_SHAPE> clone() const override
{
return std::make_unique<IMPORTED_TEXT>( *this );
}
void Translate( const VECTOR2D& aVec ) override
{
m_origin += aVec;
}
private:
const VECTOR2D m_origin;
VECTOR2D m_origin;
const wxString m_text;
double m_height;
double m_width;
@ -181,12 +240,25 @@ public:
aImporter.AddSpline( m_start, m_bezierControl1, m_bezierControl2, m_end, m_width );
}
virtual std::unique_ptr<IMPORTED_SHAPE> clone() const override
{
return std::make_unique<IMPORTED_SPLINE>( *this );
}
void Translate( const VECTOR2D& aVec ) override
{
m_start += aVec;
m_bezierControl1 += aVec;
m_bezierControl2 += aVec;
m_end += aVec;
}
private:
const VECTOR2D m_start;
const VECTOR2D m_bezierControl1;
const VECTOR2D m_bezierControl2;
const VECTOR2D m_end;
double m_width;
VECTOR2D m_start;
VECTOR2D m_bezierControl1;
VECTOR2D m_bezierControl2;
VECTOR2D m_end;
double m_width;
};
@ -209,6 +281,12 @@ public:
const VECTOR2D& BezierControl2, const VECTOR2D& aEnd , double aWidth ) override;
void ImportTo( GRAPHICS_IMPORTER& aImporter );
void AddShape( std::unique_ptr<IMPORTED_SHAPE>& aShape );
std::list<std::unique_ptr<IMPORTED_SHAPE>>& GetShapes()
{
return m_shapes;
}
protected:
///> List of imported shapes