mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-19 23:31:40 +00:00
Abstract REFERENCE_IMAGE to a separate class
Break the non-PCB-specfic parts of PCB_REFERENCE_IMAGE out to a common REFERENCE_IMAGE class, which is then composed into the PCB_REFERENCE_IMAGE. This will make it easier to bring the transform origin logic to eeschema without repetition.
This commit is contained in:
parent
4a0f111fd6
commit
3f131e2011
common
include
libs/kimath
pcbnew
qa/tests/pcbnew
@ -586,6 +586,7 @@ set( COMMON_SRCS
|
||||
ptree.cpp
|
||||
rc_item.cpp
|
||||
refdes_utils.cpp
|
||||
reference_image.cpp
|
||||
render_settings.cpp
|
||||
scintilla_tricks.cpp
|
||||
status_popup.cpp
|
||||
|
@ -107,20 +107,20 @@ void BITMAP_BASE::updatePPI()
|
||||
}
|
||||
|
||||
|
||||
void BITMAP_BASE::ImportData( BITMAP_BASE* aItem )
|
||||
void BITMAP_BASE::ImportData( BITMAP_BASE& aItem )
|
||||
{
|
||||
*m_image = *aItem->m_image;
|
||||
*m_bitmap = *aItem->m_bitmap;
|
||||
*m_originalImage = *aItem->m_originalImage;
|
||||
m_imageId = aItem->m_imageId;
|
||||
m_scale = aItem->m_scale;
|
||||
m_ppi = aItem->m_ppi;
|
||||
m_pixelSizeIu = aItem->m_pixelSizeIu;
|
||||
m_isMirroredX = aItem->m_isMirroredX;
|
||||
m_isMirroredY = aItem->m_isMirroredY;
|
||||
m_rotation = aItem->m_rotation;
|
||||
m_imageType = aItem->m_imageType;
|
||||
m_imageData = aItem->m_imageData;
|
||||
*m_image = *aItem.m_image;
|
||||
*m_bitmap = *aItem.m_bitmap;
|
||||
*m_originalImage = *aItem.m_originalImage;
|
||||
m_imageId = aItem.m_imageId;
|
||||
m_scale = aItem.m_scale;
|
||||
m_ppi = aItem.m_ppi;
|
||||
m_pixelSizeIu = aItem.m_pixelSizeIu;
|
||||
m_isMirroredX = aItem.m_isMirroredX;
|
||||
m_isMirroredY = aItem.m_isMirroredY;
|
||||
m_rotation = aItem.m_rotation;
|
||||
m_imageType = aItem.m_imageType;
|
||||
m_imageData = aItem.m_imageData;
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,11 +35,10 @@
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
PANEL_IMAGE_EDITOR::PANEL_IMAGE_EDITOR( wxWindow* aParent, BITMAP_BASE* aItem ) :
|
||||
PANEL_IMAGE_EDITOR_BASE( aParent )
|
||||
PANEL_IMAGE_EDITOR::PANEL_IMAGE_EDITOR( wxWindow* aParent, const BITMAP_BASE& aItem ) :
|
||||
PANEL_IMAGE_EDITOR_BASE( aParent ),
|
||||
m_workingImage( std::make_unique<BITMAP_BASE>( aItem ) )
|
||||
{
|
||||
m_workingImage = new BITMAP_BASE( *aItem );
|
||||
|
||||
wxString msg;
|
||||
msg.Printf( wxT( "%f" ), m_workingImage->GetScale() );
|
||||
m_textCtrlScale->SetValue( msg );
|
||||
@ -49,6 +48,11 @@ PANEL_IMAGE_EDITOR::PANEL_IMAGE_EDITOR( wxWindow* aParent, BITMAP_BASE* aItem )
|
||||
}
|
||||
|
||||
|
||||
PANEL_IMAGE_EDITOR::~PANEL_IMAGE_EDITOR()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void PANEL_IMAGE_EDITOR::OnGreyScaleConvert( wxCommandEvent& event )
|
||||
{
|
||||
m_workingImage->ConvertToGreyscale();
|
||||
@ -132,11 +136,11 @@ void PANEL_IMAGE_EDITOR::OnRedrawPanel( wxPaintEvent& event )
|
||||
}
|
||||
|
||||
|
||||
void PANEL_IMAGE_EDITOR::TransferToImage( BITMAP_BASE* aItem )
|
||||
void PANEL_IMAGE_EDITOR::TransferToImage( BITMAP_BASE& aItem )
|
||||
{
|
||||
wxString msg = m_textCtrlScale->GetValue();
|
||||
double scale = 1.0;
|
||||
msg.ToDouble( &scale );
|
||||
m_workingImage->SetScale( scale );
|
||||
aItem->ImportData( m_workingImage );
|
||||
aItem.ImportData( *m_workingImage );
|
||||
}
|
||||
|
280
common/reference_image.cpp
Normal file
280
common/reference_image.cpp
Normal file
@ -0,0 +1,280 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* 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 "reference_image.h"
|
||||
|
||||
#include <wx/debug.h>
|
||||
|
||||
#include <bitmap_base.h>
|
||||
#include <geometry/geometry_utils.h>
|
||||
|
||||
|
||||
REFERENCE_IMAGE::REFERENCE_IMAGE( const EDA_IU_SCALE& aIuScale ) :
|
||||
m_iuScale( aIuScale ), m_pos( 0, 0 ), m_transformOriginOffset( 0, 0 ),
|
||||
m_bitmapBase( std::make_unique<BITMAP_BASE>() )
|
||||
{
|
||||
updatePixelSizeInIU();
|
||||
}
|
||||
|
||||
|
||||
REFERENCE_IMAGE::REFERENCE_IMAGE( const REFERENCE_IMAGE& aOther ) :
|
||||
m_iuScale( aOther.m_iuScale ), m_pos( aOther.m_pos ),
|
||||
m_transformOriginOffset( aOther.m_transformOriginOffset ),
|
||||
m_bitmapBase( std::make_unique<BITMAP_BASE>( *aOther.m_bitmapBase ) )
|
||||
{
|
||||
updatePixelSizeInIU();
|
||||
}
|
||||
|
||||
|
||||
REFERENCE_IMAGE::~REFERENCE_IMAGE()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void REFERENCE_IMAGE::updatePixelSizeInIU()
|
||||
{
|
||||
const double pixelSizeIu = (double) m_iuScale.MilsToIU( 1000 ) / m_bitmapBase->GetPPI();
|
||||
m_bitmapBase->SetPixelSizeIu( pixelSizeIu );
|
||||
}
|
||||
|
||||
|
||||
REFERENCE_IMAGE& REFERENCE_IMAGE::operator=( const REFERENCE_IMAGE& aOther )
|
||||
{
|
||||
wxASSERT( m_iuScale.IU_PER_MILS == aOther.m_iuScale.IU_PER_MILS );
|
||||
|
||||
if( &aOther != this )
|
||||
{
|
||||
if( aOther.m_bitmapBase )
|
||||
{
|
||||
m_bitmapBase = std::make_unique<BITMAP_BASE>( *aOther.m_bitmapBase );
|
||||
}
|
||||
m_pos = aOther.m_pos;
|
||||
m_transformOriginOffset = aOther.m_transformOriginOffset;
|
||||
updatePixelSizeInIU();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool REFERENCE_IMAGE::operator==( const REFERENCE_IMAGE& aOther ) const
|
||||
{
|
||||
if( m_pos != aOther.m_pos )
|
||||
return false;
|
||||
|
||||
if( m_transformOriginOffset != aOther.m_transformOriginOffset )
|
||||
return false;
|
||||
|
||||
if( m_bitmapBase->GetSize() != aOther.m_bitmapBase->GetSize() )
|
||||
return false;
|
||||
|
||||
if( m_bitmapBase->GetPPI() != aOther.m_bitmapBase->GetPPI() )
|
||||
return false;
|
||||
|
||||
if( m_bitmapBase->GetScale() != aOther.m_bitmapBase->GetScale() )
|
||||
return false;
|
||||
|
||||
if( m_bitmapBase->GetImageID() != aOther.m_bitmapBase->GetImageID() )
|
||||
return false;
|
||||
|
||||
if( m_bitmapBase->GetImageData() != aOther.m_bitmapBase->GetImageData() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
double REFERENCE_IMAGE::Similarity( const REFERENCE_IMAGE& aOther ) const
|
||||
{
|
||||
double similarity = 1.0;
|
||||
|
||||
if( m_pos != aOther.m_pos )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_bitmapBase->GetSize() != aOther.m_bitmapBase->GetSize() )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_bitmapBase->GetPPI() != aOther.m_bitmapBase->GetPPI() )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_bitmapBase->GetScale() != aOther.m_bitmapBase->GetScale() )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_bitmapBase->GetImageID() != aOther.m_bitmapBase->GetImageID() )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_bitmapBase->GetImageData() != aOther.m_bitmapBase->GetImageData() )
|
||||
similarity *= 0.9;
|
||||
|
||||
return similarity;
|
||||
}
|
||||
|
||||
|
||||
BOX2I REFERENCE_IMAGE::GetBoundingBox() const
|
||||
{
|
||||
return BOX2I::ByCenter( m_pos, m_bitmapBase->GetSize() );
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I REFERENCE_IMAGE::GetPosition() const
|
||||
{
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
|
||||
void REFERENCE_IMAGE::SetPosition( const VECTOR2I& aPos )
|
||||
{
|
||||
const BOX2D newBox = BOX2D::ByCenter( aPos, m_bitmapBase->GetSize() );
|
||||
|
||||
if( !IsBOX2Safe( newBox ) )
|
||||
return;
|
||||
|
||||
m_pos = aPos;
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I REFERENCE_IMAGE::GetTransformOriginOffset() const
|
||||
{
|
||||
return m_transformOriginOffset;
|
||||
}
|
||||
|
||||
|
||||
void REFERENCE_IMAGE::SetTransformOriginOffset( const VECTOR2I& aCenter )
|
||||
{
|
||||
m_transformOriginOffset = aCenter;
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I REFERENCE_IMAGE::GetSize() const
|
||||
{
|
||||
return m_bitmapBase->GetSize();
|
||||
}
|
||||
|
||||
|
||||
double REFERENCE_IMAGE::GetImageScale() const
|
||||
{
|
||||
return m_bitmapBase->GetScale();
|
||||
}
|
||||
|
||||
|
||||
void REFERENCE_IMAGE::SetImageScale( double aScale )
|
||||
{
|
||||
if( aScale < 0 )
|
||||
return;
|
||||
|
||||
const double ratio = aScale / m_bitmapBase->GetScale();
|
||||
|
||||
const VECTOR2D currentOrigin = m_pos + m_transformOriginOffset;
|
||||
const VECTOR2D newOffset = m_transformOriginOffset * ratio;
|
||||
const VECTOR2D newCenter = currentOrigin - newOffset;
|
||||
const VECTOR2D newSize = m_bitmapBase->GetSize() * ratio;
|
||||
|
||||
// The span of the image is limited to the size of the coordinate system
|
||||
if( !IsVec2SafeXY( newSize ) )
|
||||
return;
|
||||
|
||||
const BOX2D newBox = BOX2D::ByCenter( newCenter, newSize );
|
||||
|
||||
// Any overflow, just reject the call
|
||||
if( !IsBOX2Safe( newBox ) )
|
||||
return;
|
||||
|
||||
m_bitmapBase->SetScale( aScale );
|
||||
SetTransformOriginOffset( KiROUND( newOffset ) );
|
||||
// Don't need to recheck the box, we just did that
|
||||
m_pos = KiROUND( newCenter );
|
||||
}
|
||||
|
||||
|
||||
void REFERENCE_IMAGE::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
|
||||
{
|
||||
VECTOR2I newPos = m_pos;
|
||||
MIRROR( newPos, aCentre, aFlipDirection );
|
||||
|
||||
const BOX2D newBox = BOX2D::ByCenter( newPos, m_bitmapBase->GetSize() );
|
||||
|
||||
if( !IsBOX2Safe( newBox ) )
|
||||
return;
|
||||
|
||||
m_pos = newPos;
|
||||
m_bitmapBase->Mirror( aFlipDirection );
|
||||
}
|
||||
|
||||
|
||||
void REFERENCE_IMAGE::Rotate( const VECTOR2I& aCenter, const EDA_ANGLE& aAngle )
|
||||
{
|
||||
EDA_ANGLE norm( aAngle.AsDegrees(), DEGREES_T );
|
||||
|
||||
RotatePoint( m_pos, aCenter, aAngle );
|
||||
|
||||
norm.Normalize();
|
||||
|
||||
// each call to m_bitmapBase->Rotate() rotates 90 degrees CCW
|
||||
for( double ang = 45.0; ang < norm.AsDegrees(); ang += 90.0 )
|
||||
m_bitmapBase->Rotate( false );
|
||||
}
|
||||
|
||||
|
||||
bool REFERENCE_IMAGE::ReadImageFile( const wxString& aFullFilename )
|
||||
{
|
||||
if( m_bitmapBase->ReadImageFile( aFullFilename ) )
|
||||
{
|
||||
updatePixelSizeInIU();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool REFERENCE_IMAGE::ReadImageFile( wxMemoryBuffer& aBuffer )
|
||||
{
|
||||
if( m_bitmapBase->ReadImageFile( aBuffer ) )
|
||||
{
|
||||
updatePixelSizeInIU();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const BITMAP_BASE& REFERENCE_IMAGE::GetImage() const
|
||||
{
|
||||
// This cannot be null after construction
|
||||
return *m_bitmapBase;
|
||||
}
|
||||
|
||||
|
||||
BITMAP_BASE& REFERENCE_IMAGE::MutableImage() const
|
||||
{
|
||||
return *m_bitmapBase;
|
||||
}
|
||||
|
||||
|
||||
void REFERENCE_IMAGE::SwapData( REFERENCE_IMAGE& aOther )
|
||||
{
|
||||
std::swap( m_pos, aOther.m_pos );
|
||||
std::swap( m_transformOriginOffset, aOther.m_transformOriginOffset );
|
||||
std::swap( m_bitmapBase, aOther.m_bitmapBase );
|
||||
}
|
@ -78,7 +78,7 @@ public:
|
||||
/**
|
||||
* Copy aItem image to this object and update #m_bitmap.
|
||||
*/
|
||||
void ImportData( BITMAP_BASE* aItem );
|
||||
void ImportData( BITMAP_BASE& aItem );
|
||||
|
||||
/**
|
||||
* This scaling factor depends on #m_pixelSizeIu and #m_scale.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2018 jean-pierre.charras
|
||||
* Copyright (C) 2018 Kicad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2018-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
|
||||
@ -22,22 +22,20 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef PANEL_IMAGE_EDITOR_H
|
||||
#define PANEL_IMAGE_EDITOR_H
|
||||
#pragma once
|
||||
|
||||
#include <bitmap_base.h>
|
||||
#include <panel_image_editor_base.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class BITMAP_BASE;
|
||||
|
||||
|
||||
class PANEL_IMAGE_EDITOR : public PANEL_IMAGE_EDITOR_BASE
|
||||
{
|
||||
private:
|
||||
BITMAP_BASE* m_workingImage; // The copy of BITMAP_BASE to be edited
|
||||
|
||||
public:
|
||||
PANEL_IMAGE_EDITOR( wxWindow* aParent, BITMAP_BASE* aItem );
|
||||
~PANEL_IMAGE_EDITOR() { delete m_workingImage; }
|
||||
|
||||
PANEL_IMAGE_EDITOR( wxWindow* aParent, const BITMAP_BASE& aItem );
|
||||
~PANEL_IMAGE_EDITOR();
|
||||
|
||||
public:
|
||||
bool TransferDataFromWindow() override;
|
||||
@ -46,13 +44,14 @@ public:
|
||||
* Function TransferToImage
|
||||
* copy edited image to aItem
|
||||
*/
|
||||
void TransferToImage( BITMAP_BASE* aItem );
|
||||
void TransferToImage( BITMAP_BASE& aItem );
|
||||
|
||||
private:
|
||||
void OnGreyScaleConvert( wxCommandEvent& event ) override;
|
||||
void OnRedrawPanel( wxPaintEvent& event ) override;
|
||||
|
||||
bool CheckValues();
|
||||
};
|
||||
|
||||
#endif
|
||||
// A copy of BITMAP_BASE to be edited
|
||||
std::unique_ptr<BITMAP_BASE> m_workingImage;
|
||||
};
|
137
include/reference_image.h
Normal file
137
include/reference_image.h
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <base_units.h>
|
||||
#include <core/mirror.h>
|
||||
#include <math/box2.h>
|
||||
#include <math/vector2d.h>
|
||||
|
||||
class BITMAP_BASE;
|
||||
|
||||
class wxMemoryBuffer;
|
||||
|
||||
/**
|
||||
* A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is
|
||||
* displayed in an editor as a reference for the user.
|
||||
*/
|
||||
class REFERENCE_IMAGE
|
||||
{
|
||||
public:
|
||||
REFERENCE_IMAGE( const EDA_IU_SCALE& aIuScale );
|
||||
REFERENCE_IMAGE( const REFERENCE_IMAGE& aOther );
|
||||
~REFERENCE_IMAGE();
|
||||
|
||||
REFERENCE_IMAGE& operator=( const REFERENCE_IMAGE& aOther );
|
||||
|
||||
bool operator==( const REFERENCE_IMAGE& aOther ) const;
|
||||
|
||||
double Similarity( const REFERENCE_IMAGE& aOther ) const;
|
||||
|
||||
BOX2I GetBoundingBox() const;
|
||||
|
||||
bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const;
|
||||
|
||||
VECTOR2I GetPosition() const;
|
||||
void SetPosition( const VECTOR2I& aPos );
|
||||
|
||||
VECTOR2I GetSize() const;
|
||||
|
||||
/**
|
||||
* @return the image "zoom" value.
|
||||
* scale = 1.0 = original size of bitmap.
|
||||
* scale < 1.0 = the bitmap is drawn smaller than its original size.
|
||||
* scale > 1.0 = the bitmap is drawn bigger than its original size.
|
||||
*/
|
||||
double GetImageScale() const;
|
||||
|
||||
/**
|
||||
* Set the image "zoom" value.
|
||||
*
|
||||
* The image is scaled such that the position of the image's
|
||||
* transform origin is unchanged.
|
||||
*
|
||||
* If the scale is negative or the image would overflow the
|
||||
* the coordinate system, nothing is updated.
|
||||
*/
|
||||
void SetImageScale( double aScale );
|
||||
|
||||
void Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection );
|
||||
|
||||
void Rotate( const VECTOR2I& aCenter, const EDA_ANGLE& aAngle );
|
||||
|
||||
/**
|
||||
* Read and store an image file.
|
||||
*
|
||||
* Initialize the bitmap used to draw this item format.
|
||||
*
|
||||
* @param aFullFilename is the full filename of the image file to read.
|
||||
* @return true if success reading else false.
|
||||
*/
|
||||
bool ReadImageFile( const wxString& aFullFilename );
|
||||
|
||||
/**
|
||||
* Read and store an image file.
|
||||
*
|
||||
* Initialize the bitmap used to draw this item format.
|
||||
*
|
||||
* @param aBuf is the memory buffer containing the image file to read.
|
||||
* @return true if success reading else false.
|
||||
*/
|
||||
bool ReadImageFile( wxMemoryBuffer& aBuf );
|
||||
|
||||
void SwapData( REFERENCE_IMAGE& aItem );
|
||||
|
||||
/**
|
||||
* Get the underlying image.
|
||||
*
|
||||
* This will always return a valid reference, but it may be to an empty image.
|
||||
*/
|
||||
const BITMAP_BASE& GetImage() const;
|
||||
|
||||
/**
|
||||
* Only use this if you really need to modify the underlying image
|
||||
*/
|
||||
BITMAP_BASE& MutableImage() const;
|
||||
|
||||
|
||||
/**
|
||||
* Get the center of scaling, etc, relative to the image center (GetPosition()).
|
||||
*/
|
||||
VECTOR2I GetTransformOriginOffset() const;
|
||||
void SetTransformOriginOffset( const VECTOR2I& aCenter );
|
||||
|
||||
private:
|
||||
void updatePixelSizeInIU();
|
||||
|
||||
const EDA_IU_SCALE& m_iuScale;
|
||||
|
||||
VECTOR2I m_pos; // XY coordinates of center of the bitmap
|
||||
///< Center of scaling, etc, relative to the image center
|
||||
VECTOR2I m_transformOriginOffset;
|
||||
|
||||
std::unique_ptr<BITMAP_BASE> m_bitmapBase;
|
||||
};
|
@ -27,8 +27,7 @@
|
||||
* @brief a few functions useful in geometry calculations.
|
||||
*/
|
||||
|
||||
#ifndef GEOMETRY_UTILS_H
|
||||
#define GEOMETRY_UTILS_H
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <math.h> // for copysign
|
||||
@ -203,4 +202,26 @@ inline bool IsVec2SafeXY( const VECTOR2<T>& aVec )
|
||||
bool ClipLine( const BOX2I *aClipBox, int &x1, int &y1, int &x2, int &y2 );
|
||||
|
||||
|
||||
#endif // #ifndef GEOMETRY_UTILS_H
|
||||
namespace KIGEOM
|
||||
{
|
||||
/**
|
||||
* Perform a point-to-box hit test.
|
||||
*
|
||||
* @param aHitPoint - The point that is hitting the box
|
||||
* @param aHittee - The box that is tested for hit.
|
||||
* @param aAccuracy - The accuracy of the hit test.
|
||||
*/
|
||||
bool BoxHitTest( const VECTOR2I& aHitPoint, const BOX2I& aHittee, int aAccuracy );
|
||||
|
||||
/**
|
||||
* Perform a box-to-box hit test.
|
||||
*
|
||||
* @param aHitter - The box that is either hitting or containing the hittee.
|
||||
* @param aHittee - The box that is either being hit or contained by the hitter
|
||||
* (this is possibly an object's bounding box).
|
||||
* @param aHitteeContained - True if the hittee is tested for total containment,
|
||||
* false if it is tested for intersection.
|
||||
* @param aAccuracy - The accuracy of the hit test.
|
||||
*/
|
||||
bool BoxHitTest( const BOX2I& aHitter, const BOX2I& aHittee, bool aHitteeContained, int aAccuracy );
|
||||
}; // namespace KIGEOM
|
@ -198,3 +198,21 @@ bool ClipLine( const BOX2I *aClipBox, int &x1, int &y1, int &x2, int &y2 )
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool KIGEOM::BoxHitTest( const VECTOR2I& aHitter, const BOX2I& aHittee, int aAccuracy )
|
||||
{
|
||||
const BOX2I hittee = aHittee.GetInflated( aAccuracy );
|
||||
return hittee.Contains( aHitter );
|
||||
}
|
||||
|
||||
|
||||
bool KIGEOM::BoxHitTest( const BOX2I& aHitter, const BOX2I& aHittee, bool aHitteeContained,
|
||||
int aAccuracy )
|
||||
{
|
||||
const BOX2I hitter = aHitter.GetInflated( aAccuracy );
|
||||
|
||||
if( aHitteeContained )
|
||||
return hitter.Contains( aHittee );
|
||||
|
||||
return hitter.Intersects( aHittee );
|
||||
}
|
@ -33,7 +33,7 @@
|
||||
|
||||
|
||||
DIALOG_REFERENCE_IMAGE_PROPERTIES::DIALOG_REFERENCE_IMAGE_PROPERTIES( PCB_BASE_FRAME* aParent,
|
||||
PCB_REFERENCE_IMAGE* aBitmap ) :
|
||||
PCB_REFERENCE_IMAGE& aBitmap ) :
|
||||
DIALOG_REFERENCE_IMAGE_PROPERTIES_BASE( aParent ),
|
||||
m_frame( aParent ),
|
||||
m_bitmap( aBitmap ),
|
||||
@ -41,14 +41,15 @@ DIALOG_REFERENCE_IMAGE_PROPERTIES::DIALOG_REFERENCE_IMAGE_PROPERTIES( PCB_BASE_F
|
||||
m_posY( aParent, m_YPosLabel, m_ModPositionY, m_YPosUnit )
|
||||
{
|
||||
// Create the image editor page
|
||||
m_imageEditor = new PANEL_IMAGE_EDITOR( m_Notebook, aBitmap->MutableImage() );
|
||||
m_imageEditor =
|
||||
new PANEL_IMAGE_EDITOR( m_Notebook, aBitmap.GetReferenceImage().MutableImage() );
|
||||
m_Notebook->AddPage( m_imageEditor, _( "Image" ), false );
|
||||
|
||||
m_posX.SetCoordType( ORIGIN_TRANSFORMS::ABS_X_COORD );
|
||||
m_posY.SetCoordType( ORIGIN_TRANSFORMS::ABS_Y_COORD );
|
||||
|
||||
// Only show unactivated board layers if the bitmap is on one of them
|
||||
if( !m_frame->GetBoard()->IsLayerEnabled( m_bitmap->GetLayer() ) )
|
||||
if( !m_frame->GetBoard()->IsLayerEnabled( m_bitmap.GetLayer() ) )
|
||||
m_LayerSelectionCtrl->ShowNonActivatedLayers( true );
|
||||
|
||||
m_LayerSelectionCtrl->SetLayersHotkeys( false );
|
||||
@ -63,7 +64,7 @@ DIALOG_REFERENCE_IMAGE_PROPERTIES::DIALOG_REFERENCE_IMAGE_PROPERTIES( PCB_BASE_F
|
||||
|
||||
void PCB_BASE_EDIT_FRAME::ShowReferenceImagePropertiesDialog( BOARD_ITEM* aBitmap )
|
||||
{
|
||||
PCB_REFERENCE_IMAGE* bitmap = static_cast<PCB_REFERENCE_IMAGE*>( aBitmap );
|
||||
PCB_REFERENCE_IMAGE& bitmap = static_cast<PCB_REFERENCE_IMAGE&>( *aBitmap );
|
||||
DIALOG_REFERENCE_IMAGE_PROPERTIES dlg( this, bitmap );
|
||||
|
||||
if( dlg.ShowModal() == wxID_OK )
|
||||
@ -78,12 +79,12 @@ void PCB_BASE_EDIT_FRAME::ShowReferenceImagePropertiesDialog( BOARD_ITEM* aBitma
|
||||
|
||||
bool DIALOG_REFERENCE_IMAGE_PROPERTIES::TransferDataToWindow()
|
||||
{
|
||||
m_posX.SetValue( m_bitmap->GetPosition().x );
|
||||
m_posY.SetValue( m_bitmap->GetPosition().y );
|
||||
m_posX.SetValue( m_bitmap.GetPosition().x );
|
||||
m_posY.SetValue( m_bitmap.GetPosition().y );
|
||||
|
||||
m_LayerSelectionCtrl->SetLayerSelection( m_bitmap->GetLayer() );
|
||||
m_LayerSelectionCtrl->SetLayerSelection( m_bitmap.GetLayer() );
|
||||
|
||||
m_cbLocked->SetValue( m_bitmap->IsLocked() );
|
||||
m_cbLocked->SetValue( m_bitmap.IsLocked() );
|
||||
m_cbLocked->SetToolTip( _( "Locked items cannot be freely moved and oriented on the canvas "
|
||||
"and can only be selected when the 'Locked items' checkbox is "
|
||||
"checked in the selection filter." ) );
|
||||
@ -97,16 +98,16 @@ bool DIALOG_REFERENCE_IMAGE_PROPERTIES::TransferDataFromWindow()
|
||||
if( m_imageEditor->TransferDataFromWindow() )
|
||||
{
|
||||
// Save old image in undo list if not already in edit
|
||||
if( m_bitmap->GetEditFlags() == 0 )
|
||||
m_frame->SaveCopyInUndoList( m_bitmap, UNDO_REDO::CHANGED );
|
||||
if( m_bitmap.GetEditFlags() == 0 )
|
||||
m_frame->SaveCopyInUndoList( &m_bitmap, UNDO_REDO::CHANGED );
|
||||
|
||||
// Update our bitmap from the editor
|
||||
m_imageEditor->TransferToImage( m_bitmap->MutableImage() );
|
||||
m_imageEditor->TransferToImage( m_bitmap.GetReferenceImage().MutableImage() );
|
||||
|
||||
// Set position, etc.
|
||||
m_bitmap->SetPosition( VECTOR2I( m_posX.GetValue(), m_posY.GetValue() ) );
|
||||
m_bitmap->SetLayer( ToLAYER_ID( m_LayerSelectionCtrl->GetLayerSelection() ) );
|
||||
m_bitmap->SetLocked( m_cbLocked->GetValue() );
|
||||
m_bitmap.SetPosition( VECTOR2I( m_posX.GetValue(), m_posY.GetValue() ) );
|
||||
m_bitmap.SetLayer( ToLAYER_ID( m_LayerSelectionCtrl->GetLayerSelection() ) );
|
||||
m_bitmap.SetLocked( m_cbLocked->GetValue() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2018-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2018-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
|
||||
@ -21,8 +21,7 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef DIALOG_REFERENCE_IMAGE_PROPERTIES_H
|
||||
#define DIALOG_REFERENCE_IMAGE_PROPERTIES_H
|
||||
#pragma once
|
||||
|
||||
#include <dialogs/dialog_reference_image_properties_base.h>
|
||||
#include <widgets/unit_binder.h>
|
||||
@ -36,7 +35,7 @@ class PANEL_IMAGE_EDITOR;
|
||||
class DIALOG_REFERENCE_IMAGE_PROPERTIES : public DIALOG_REFERENCE_IMAGE_PROPERTIES_BASE
|
||||
{
|
||||
public:
|
||||
DIALOG_REFERENCE_IMAGE_PROPERTIES( PCB_BASE_FRAME* aParent, PCB_REFERENCE_IMAGE* aBitmap );
|
||||
DIALOG_REFERENCE_IMAGE_PROPERTIES( PCB_BASE_FRAME* aParent, PCB_REFERENCE_IMAGE& aBitmap );
|
||||
~DIALOG_REFERENCE_IMAGE_PROPERTIES() override {}
|
||||
|
||||
private:
|
||||
@ -45,11 +44,10 @@ private:
|
||||
|
||||
private:
|
||||
PCB_BASE_FRAME* m_frame;
|
||||
PCB_REFERENCE_IMAGE* m_bitmap;
|
||||
///< The reference image being edited
|
||||
PCB_REFERENCE_IMAGE& m_bitmap;
|
||||
PANEL_IMAGE_EDITOR* m_imageEditor;
|
||||
|
||||
UNIT_BINDER m_posX;
|
||||
UNIT_BINDER m_posY;
|
||||
};
|
||||
|
||||
#endif // DIALOG_REFERENCE_IMAGE_PROPERTIES_H
|
||||
|
@ -1466,14 +1466,15 @@ void PCB_IO_EASYEDAPRO_PARSER::ParseBoard(
|
||||
|
||||
std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap =
|
||||
std::make_unique<PCB_REFERENCE_IMAGE>( aBoard, kcenter, klayer );
|
||||
REFERENCE_IMAGE& refImage = bitmap->GetReferenceImage();
|
||||
|
||||
wxImage::SetDefaultLoadFlags( wxImage::GetDefaultLoadFlags()
|
||||
& ~wxImage::Load_Verbose );
|
||||
|
||||
if( bitmap->ReadImageFile( buf ) )
|
||||
if( refImage.ReadImageFile( buf ) )
|
||||
{
|
||||
double scaleFactor = ScaleSize( size.x ) / bitmap->GetSize().x;
|
||||
bitmap->SetImageScale( scaleFactor );
|
||||
double scaleFactor = ScaleSize( size.x ) / refImage.GetSize().x;
|
||||
refImage.SetImageScale( scaleFactor );
|
||||
|
||||
// TODO: support non-90-deg angles
|
||||
bitmap->Rotate( kstart, EDA_ANGLE( angle, DEGREES_T ) );
|
||||
@ -1484,7 +1485,7 @@ void PCB_IO_EASYEDAPRO_PARSER::ParseBoard(
|
||||
MIRROR( x, KiROUND( kstart.x ) );
|
||||
bitmap->SetX( x );
|
||||
|
||||
bitmap->MutableImage()->Mirror( FLIP_DIRECTION::LEFT_RIGHT );
|
||||
refImage.MutableImage().Mirror( FLIP_DIRECTION::LEFT_RIGHT );
|
||||
}
|
||||
|
||||
aBoard->Add( bitmap.release(), ADD_MODE::APPEND );
|
||||
|
@ -1072,7 +1072,9 @@ void PCB_IO_KICAD_SEXPR::format( const PCB_REFERENCE_IMAGE* aBitmap, int aNestLe
|
||||
{
|
||||
wxCHECK_RET( aBitmap != nullptr && m_out != nullptr, "" );
|
||||
|
||||
const wxImage* image = aBitmap->GetImage()->GetImageData();
|
||||
const REFERENCE_IMAGE& refImage = aBitmap->GetReferenceImage();
|
||||
|
||||
const wxImage* image = refImage.GetImage().GetImageData();
|
||||
|
||||
wxCHECK_RET( image != nullptr, "wxImage* is NULL" );
|
||||
|
||||
@ -1082,15 +1084,15 @@ void PCB_IO_KICAD_SEXPR::format( const PCB_REFERENCE_IMAGE* aBitmap, int aNestLe
|
||||
|
||||
formatLayer( aBitmap->GetLayer() );
|
||||
|
||||
if( aBitmap->GetImage()->GetScale() != 1.0 )
|
||||
m_out->Print( 0, "(scale %g)", aBitmap->GetImage()->GetScale() );
|
||||
if( refImage.GetImageScale() != 1.0 )
|
||||
m_out->Print( 0, "(scale %g)", refImage.GetImageScale() );
|
||||
|
||||
if( const bool locked = aBitmap->IsLocked() )
|
||||
KICAD_FORMAT::FormatBool( m_out, 0, "locked", locked );
|
||||
|
||||
m_out->Print( aNestLevel + 1, "(data" );
|
||||
|
||||
wxString out = wxBase64Encode( aBitmap->GetImage()->GetImageDataBuffer() );
|
||||
wxString out = wxBase64Encode( refImage.GetImage().GetImageDataBuffer() );
|
||||
|
||||
// Apparently the MIME standard character width for base64 encoding is 76 (unconfirmed)
|
||||
// so use it in a vain attempt to be standard like.
|
||||
|
@ -3195,14 +3195,16 @@ PCB_REFERENCE_IMAGE* PCB_IO_KICAD_SEXPR_PARSER::parsePCB_REFERENCE_IMAGE( BOARD_
|
||||
break;
|
||||
|
||||
case T_scale:
|
||||
bitmap->SetImageScale( parseDouble( "image scale factor" ) );
|
||||
{
|
||||
REFERENCE_IMAGE& refImage = bitmap->GetReferenceImage();
|
||||
refImage.SetImageScale( parseDouble( "image scale factor" ) );
|
||||
|
||||
if( !std::isnormal( bitmap->GetImage()->GetScale() ) )
|
||||
bitmap->SetImageScale( 1.0 );
|
||||
if( !std::isnormal( refImage.GetImageScale() ) )
|
||||
refImage.SetImageScale( 1.0 );
|
||||
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
}
|
||||
case T_data:
|
||||
{
|
||||
token = NextTok();
|
||||
@ -3222,9 +3224,10 @@ PCB_REFERENCE_IMAGE* PCB_IO_KICAD_SEXPR_PARSER::parsePCB_REFERENCE_IMAGE( BOARD_
|
||||
token = NextTok();
|
||||
}
|
||||
|
||||
wxMemoryBuffer buffer = wxBase64Decode( data );
|
||||
wxMemoryBuffer buffer = wxBase64Decode( data );
|
||||
|
||||
if( !bitmap->ReadImageFile( buffer ) )
|
||||
REFERENCE_IMAGE& refImage = bitmap->GetReferenceImage();
|
||||
if( !refImage.ReadImageFile( buffer ) )
|
||||
THROW_IO_ERROR( _( "Failed to read image data." ) );
|
||||
|
||||
break;
|
||||
|
@ -2062,11 +2062,13 @@ void PCB_PAINTER::strokeText( const wxString& aText, const VECTOR2I& aPosition,
|
||||
void PCB_PAINTER::draw( const PCB_REFERENCE_IMAGE* aBitmap, int aLayer )
|
||||
{
|
||||
m_gal->Save();
|
||||
m_gal->Translate( aBitmap->GetPosition() );
|
||||
|
||||
const REFERENCE_IMAGE& refImg = aBitmap->GetReferenceImage();
|
||||
m_gal->Translate( refImg.GetPosition() );
|
||||
|
||||
// When the image scale factor is not 1.0, we need to modify the actual as the image scale
|
||||
// factor is similar to a local zoom
|
||||
double img_scale = aBitmap->GetImageScale();
|
||||
const double img_scale = refImg.GetImageScale();
|
||||
|
||||
if( img_scale != 1.0 )
|
||||
m_gal->Scale( VECTOR2D( img_scale, img_scale ) );
|
||||
@ -2080,7 +2082,7 @@ void PCB_PAINTER::draw( const PCB_REFERENCE_IMAGE* aBitmap, int aLayer )
|
||||
m_gal->SetIsFill( false );
|
||||
|
||||
// Draws a bounding box.
|
||||
VECTOR2D bm_size( aBitmap->GetSize() );
|
||||
VECTOR2D bm_size( refImg.GetSize() );
|
||||
// bm_size is the actual image size in UI.
|
||||
// but m_gal scale was previously set to img_scale
|
||||
// so recalculate size relative to this image size.
|
||||
@ -2094,13 +2096,12 @@ void PCB_PAINTER::draw( const PCB_REFERENCE_IMAGE* aBitmap, int aLayer )
|
||||
// Hard code reference images as opaque when selected. Otherwise cached layers will
|
||||
// not be rendered under the selected image because cached layers are rendered after
|
||||
// non-cached layers (e.g. bitmaps), which will have a closer Z order.
|
||||
m_gal->DrawBitmap( *aBitmap->GetImage(), 1.0 );
|
||||
m_gal->DrawBitmap( refImg.GetImage(), 1.0 );
|
||||
}
|
||||
else
|
||||
m_gal->DrawBitmap( *aBitmap->GetImage(),
|
||||
m_gal->DrawBitmap( refImg.GetImage(),
|
||||
m_pcbSettings.GetColor( aBitmap, aBitmap->GetLayer() ).a );
|
||||
|
||||
|
||||
m_gal->Restore();
|
||||
}
|
||||
|
||||
|
@ -25,19 +25,19 @@
|
||||
|
||||
#include "pcb_reference_image.h"
|
||||
|
||||
#include <pcb_draw_panel_gal.h>
|
||||
#include <plotters/plotter.h>
|
||||
#include <settings/color_settings.h>
|
||||
#include <pcb_painter.h>
|
||||
#include <bitmaps.h>
|
||||
#include <base_units.h>
|
||||
#include <common.h>
|
||||
#include <eda_draw_frame.h>
|
||||
#include <core/mirror.h>
|
||||
#include <bitmaps.h>
|
||||
#include <board.h>
|
||||
#include <trigo.h>
|
||||
#include <common.h>
|
||||
#include <core/mirror.h>
|
||||
#include <eda_draw_frame.h>
|
||||
#include <pcb_draw_panel_gal.h>
|
||||
#include <pcb_painter.h>
|
||||
#include <plotters/plotter.h>
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <geometry/shape_rect.h>
|
||||
#include <settings/color_settings.h>
|
||||
#include <trigo.h>
|
||||
|
||||
#include <wx/mstream.h>
|
||||
|
||||
@ -47,26 +47,20 @@ using KIGFX::PCB_RENDER_SETTINGS;
|
||||
|
||||
PCB_REFERENCE_IMAGE::PCB_REFERENCE_IMAGE( BOARD_ITEM* aParent, const VECTOR2I& aPos,
|
||||
PCB_LAYER_ID aLayer ) :
|
||||
BOARD_ITEM( aParent, PCB_REFERENCE_IMAGE_T, aLayer ), m_pos( aPos ),
|
||||
m_transformOriginOffset( 0, 0 )
|
||||
BOARD_ITEM( aParent, PCB_REFERENCE_IMAGE_T, aLayer ), m_referenceImage( pcbIUScale )
|
||||
{
|
||||
m_bitmapBase = new BITMAP_BASE();
|
||||
m_bitmapBase->SetPixelSizeIu( (float) pcbIUScale.MilsToIU( 1000 ) / m_bitmapBase->GetPPI() );
|
||||
m_referenceImage.SetPosition( aPos );
|
||||
}
|
||||
|
||||
|
||||
PCB_REFERENCE_IMAGE::PCB_REFERENCE_IMAGE( const PCB_REFERENCE_IMAGE& aPCBBitmap ) :
|
||||
BOARD_ITEM( aPCBBitmap ), m_pos( aPCBBitmap.m_pos ),
|
||||
m_transformOriginOffset( aPCBBitmap.m_transformOriginOffset )
|
||||
BOARD_ITEM( aPCBBitmap ), m_referenceImage( aPCBBitmap.m_referenceImage )
|
||||
{
|
||||
m_bitmapBase = new BITMAP_BASE( *aPCBBitmap.m_bitmapBase );
|
||||
m_bitmapBase->SetPixelSizeIu( (float) pcbIUScale.MilsToIU( 1000 ) / m_bitmapBase->GetPPI() );
|
||||
}
|
||||
|
||||
|
||||
PCB_REFERENCE_IMAGE::~PCB_REFERENCE_IMAGE()
|
||||
{
|
||||
delete m_bitmapBase;
|
||||
}
|
||||
|
||||
|
||||
@ -79,43 +73,14 @@ PCB_REFERENCE_IMAGE& PCB_REFERENCE_IMAGE::operator=( const BOARD_ITEM& aItem )
|
||||
if( &aItem != this )
|
||||
{
|
||||
BOARD_ITEM::operator=( aItem );
|
||||
|
||||
PCB_REFERENCE_IMAGE* bitmap = (PCB_REFERENCE_IMAGE*) &aItem;
|
||||
|
||||
delete m_bitmapBase;
|
||||
m_bitmapBase = new BITMAP_BASE( *bitmap->m_bitmapBase );
|
||||
m_pos = bitmap->m_pos;
|
||||
m_bitmapBase->SetPixelSizeIu( (float) pcbIUScale.MilsToIU( 1000 ) / m_bitmapBase->GetPPI() );
|
||||
const PCB_REFERENCE_IMAGE& refImg = static_cast<const PCB_REFERENCE_IMAGE&>( aItem );
|
||||
m_referenceImage = refImg.m_referenceImage;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool PCB_REFERENCE_IMAGE::ReadImageFile( const wxString& aFullFilename )
|
||||
{
|
||||
if( m_bitmapBase->ReadImageFile( aFullFilename ) )
|
||||
{
|
||||
m_bitmapBase->SetPixelSizeIu( (float) pcbIUScale.MilsToIU( 1000 ) / m_bitmapBase->GetPPI() );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool PCB_REFERENCE_IMAGE::ReadImageFile( wxMemoryBuffer& aBuffer )
|
||||
{
|
||||
if( m_bitmapBase->ReadImageFile( aBuffer ) )
|
||||
{
|
||||
m_bitmapBase->SetPixelSizeIu( (float) pcbIUScale.MilsToIU( 1000 ) / m_bitmapBase->GetPPI() );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
EDA_ITEM* PCB_REFERENCE_IMAGE::Clone() const
|
||||
{
|
||||
return new PCB_REFERENCE_IMAGE( *this );
|
||||
@ -135,8 +100,7 @@ void PCB_REFERENCE_IMAGE::swapData( BOARD_ITEM* aItem )
|
||||
std::swap( m_flags, item->m_flags );
|
||||
std::swap( m_parent, item->m_parent );
|
||||
std::swap( m_forceVisible, item->m_forceVisible );
|
||||
std::swap( m_pos, item->m_pos );
|
||||
std::swap( m_bitmapBase, item->m_bitmapBase );
|
||||
m_referenceImage.SwapData( item->m_referenceImage );
|
||||
}
|
||||
|
||||
|
||||
@ -165,11 +129,7 @@ double PCB_REFERENCE_IMAGE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
|
||||
|
||||
const BOX2I PCB_REFERENCE_IMAGE::GetBoundingBox() const
|
||||
{
|
||||
// Bitmaps are center origin, BOX2Is need top-left origin
|
||||
const VECTOR2I size = m_bitmapBase->GetSize();
|
||||
const VECTOR2I topLeft{ m_pos.x - size.x / 2, m_pos.y - size.y / 2 };
|
||||
|
||||
return BOX2I{ topLeft, size };
|
||||
return m_referenceImage.GetBoundingBox();
|
||||
}
|
||||
|
||||
|
||||
@ -181,84 +141,33 @@ std::shared_ptr<SHAPE> PCB_REFERENCE_IMAGE::GetEffectiveShape( PCB_LAYER_ID aLay
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I PCB_REFERENCE_IMAGE::GetPosition() const
|
||||
{
|
||||
return m_referenceImage.GetPosition();
|
||||
}
|
||||
|
||||
|
||||
void PCB_REFERENCE_IMAGE::SetPosition( const VECTOR2I& aPos )
|
||||
{
|
||||
const BOX2D newBox = BOX2D::ByCenter( aPos, m_bitmapBase->GetSize() );
|
||||
|
||||
if( !IsBOX2Safe( newBox ) )
|
||||
return;
|
||||
|
||||
m_pos = aPos;
|
||||
m_referenceImage.SetPosition( aPos );
|
||||
}
|
||||
|
||||
|
||||
void PCB_REFERENCE_IMAGE::Move( const VECTOR2I& aMoveVector )
|
||||
{
|
||||
// Defer to SetPosition to check the new position overflow
|
||||
SetPosition( m_pos + aMoveVector );
|
||||
}
|
||||
|
||||
|
||||
void PCB_REFERENCE_IMAGE::SetImageScale( double aScale )
|
||||
{
|
||||
if( aScale < 0 )
|
||||
return;
|
||||
|
||||
const double ratio = aScale / m_bitmapBase->GetScale();
|
||||
|
||||
const VECTOR2D currentOrigin = m_pos + m_transformOriginOffset;
|
||||
const VECTOR2D newOffset = m_transformOriginOffset * ratio;
|
||||
const VECTOR2D newCenter = currentOrigin - newOffset;
|
||||
const VECTOR2D newSize = m_bitmapBase->GetSize() * ratio;
|
||||
|
||||
// The span of the image is limited to the size of the coordinate system
|
||||
if( !IsVec2SafeXY( newSize ) )
|
||||
return;
|
||||
|
||||
const BOX2D newBox = BOX2D::ByCenter( newCenter, newSize );
|
||||
|
||||
// Any overflow, just reject the call
|
||||
if( !IsBOX2Safe( newBox ) )
|
||||
return;
|
||||
|
||||
m_bitmapBase->SetScale( aScale );
|
||||
SetTransformOriginOffset( KiROUND( newOffset ) );
|
||||
// Don't need to recheck the box, we just did that
|
||||
m_pos = KiROUND( newCenter );
|
||||
}
|
||||
|
||||
|
||||
const VECTOR2I PCB_REFERENCE_IMAGE::GetSize() const
|
||||
{
|
||||
return m_bitmapBase->GetSize();
|
||||
SetPosition( GetPosition() + aMoveVector );
|
||||
}
|
||||
|
||||
|
||||
void PCB_REFERENCE_IMAGE::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
|
||||
{
|
||||
VECTOR2I newPos = m_pos;
|
||||
MIRROR( newPos, aCentre, aFlipDirection );
|
||||
|
||||
const BOX2D newBox = BOX2D::ByCenter( newPos, m_bitmapBase->GetSize() );
|
||||
|
||||
if( !IsBOX2Safe( newBox ) )
|
||||
return;
|
||||
|
||||
m_pos = newPos;
|
||||
m_bitmapBase->Mirror( aFlipDirection );
|
||||
m_referenceImage.Flip( aCentre, aFlipDirection );
|
||||
}
|
||||
|
||||
void PCB_REFERENCE_IMAGE::Rotate( const VECTOR2I& aCenter, const EDA_ANGLE& aAngle )
|
||||
{
|
||||
EDA_ANGLE norm( aAngle.AsDegrees(), DEGREES_T );
|
||||
|
||||
RotatePoint( m_pos, aCenter, aAngle );
|
||||
|
||||
norm.Normalize();
|
||||
|
||||
// each call to m_bitmapBase->Rotate() rotates 90 degrees CCW
|
||||
for( double ang = 45.0; ang < norm.AsDegrees(); ang += 90.0 )
|
||||
m_bitmapBase->Rotate( false );
|
||||
m_referenceImage.Rotate( aCenter, aAngle );
|
||||
}
|
||||
|
||||
|
||||
@ -268,31 +177,21 @@ void PCB_REFERENCE_IMAGE::Show( int nestLevel, std::ostream& os ) const
|
||||
// XML output:
|
||||
wxString s = GetClass();
|
||||
|
||||
NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str() << m_pos << "/>\n";
|
||||
NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str() << m_referenceImage.GetPosition()
|
||||
<< "/>\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool PCB_REFERENCE_IMAGE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
|
||||
{
|
||||
BOX2I rect = GetBoundingBox();
|
||||
|
||||
rect.Inflate( aAccuracy );
|
||||
|
||||
return rect.Contains( aPosition );
|
||||
return KIGEOM::BoxHitTest( aPosition, GetBoundingBox(), aAccuracy );
|
||||
}
|
||||
|
||||
|
||||
bool PCB_REFERENCE_IMAGE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
|
||||
{
|
||||
BOX2I rect = aRect;
|
||||
|
||||
rect.Inflate( aAccuracy );
|
||||
|
||||
if( aContained )
|
||||
return rect.Contains( GetBoundingBox() );
|
||||
|
||||
return rect.Intersects( GetBoundingBox() );
|
||||
return KIGEOM::BoxHitTest( aRect, GetBoundingBox(), aContained, aAccuracy );
|
||||
}
|
||||
|
||||
|
||||
@ -302,16 +201,20 @@ BITMAPS PCB_REFERENCE_IMAGE::GetMenuImage() const
|
||||
}
|
||||
|
||||
|
||||
void PCB_REFERENCE_IMAGE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
|
||||
void PCB_REFERENCE_IMAGE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
|
||||
std::vector<MSG_PANEL_ITEM>& aList )
|
||||
{
|
||||
aList.emplace_back( _( "Reference Image" ), wxEmptyString );
|
||||
|
||||
aList.emplace_back( _( "PPI" ), wxString::Format( wxT( "%d "), GetImage()->GetPPI() ) );
|
||||
aList.emplace_back( _( "Scale" ), wxString::Format( wxT( "%f "), GetImageScale() ) );
|
||||
aList.emplace_back( _( "PPI" ),
|
||||
wxString::Format( wxT( "%d " ), m_referenceImage.GetImage().GetPPI() ) );
|
||||
aList.emplace_back( _( "Scale" ),
|
||||
wxString::Format( wxT( "%f " ), m_referenceImage.GetImageScale() ) );
|
||||
|
||||
aList.emplace_back( _( "Width" ), aFrame->MessageTextFromValue( GetSize().x ) );
|
||||
aList.emplace_back( _( "Height" ), aFrame->MessageTextFromValue( GetSize().y ) );
|
||||
aList.emplace_back( _( "Width" ),
|
||||
aFrame->MessageTextFromValue( m_referenceImage.GetSize().x ) );
|
||||
aList.emplace_back( _( "Height" ),
|
||||
aFrame->MessageTextFromValue( m_referenceImage.GetSize().y ) );
|
||||
aList.emplace_back( _( "Layer" ), LayerName( m_layer ) );
|
||||
}
|
||||
|
||||
@ -339,22 +242,7 @@ bool PCB_REFERENCE_IMAGE::operator==( const PCB_REFERENCE_IMAGE& aOther ) const
|
||||
if( m_layer != aOther.m_layer )
|
||||
return false;
|
||||
|
||||
if( m_pos != aOther.m_pos )
|
||||
return false;
|
||||
|
||||
if( m_bitmapBase->GetSize() != aOther.m_bitmapBase->GetSize() )
|
||||
return false;
|
||||
|
||||
if( m_bitmapBase->GetPPI() != aOther.m_bitmapBase->GetPPI() )
|
||||
return false;
|
||||
|
||||
if( m_bitmapBase->GetScale() != aOther.m_bitmapBase->GetScale() )
|
||||
return false;
|
||||
|
||||
if( m_bitmapBase->GetImageID() != aOther.m_bitmapBase->GetImageID() )
|
||||
return false;
|
||||
|
||||
if( m_bitmapBase->GetImageData() != aOther.m_bitmapBase->GetImageData() )
|
||||
if( m_referenceImage != aOther.m_referenceImage )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -373,28 +261,52 @@ double PCB_REFERENCE_IMAGE::Similarity( const BOARD_ITEM& aOther ) const
|
||||
if( m_layer != other.m_layer )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_pos != other.m_pos )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_bitmapBase->GetSize() != other.m_bitmapBase->GetSize() )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_bitmapBase->GetPPI() != other.m_bitmapBase->GetPPI() )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_bitmapBase->GetScale() != other.m_bitmapBase->GetScale() )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_bitmapBase->GetImageID() != other.m_bitmapBase->GetImageID() )
|
||||
similarity *= 0.9;
|
||||
|
||||
if( m_bitmapBase->GetImageData() != other.m_bitmapBase->GetImageData() )
|
||||
similarity *= 0.9;
|
||||
similarity *= m_referenceImage.Similarity( other.m_referenceImage );
|
||||
|
||||
return similarity;
|
||||
}
|
||||
|
||||
|
||||
int PCB_REFERENCE_IMAGE::GetTransformOriginOffsetX() const
|
||||
{
|
||||
return m_referenceImage.GetTransformOriginOffset().x;
|
||||
}
|
||||
|
||||
|
||||
void PCB_REFERENCE_IMAGE::SetTransformOriginOffsetX( int aX )
|
||||
{
|
||||
VECTOR2I offset = m_referenceImage.GetTransformOriginOffset();
|
||||
offset.x = aX;
|
||||
m_referenceImage.SetTransformOriginOffset( offset );
|
||||
}
|
||||
|
||||
|
||||
int PCB_REFERENCE_IMAGE::GetTransformOriginOffsetY() const
|
||||
{
|
||||
return m_referenceImage.GetTransformOriginOffset().y;
|
||||
}
|
||||
|
||||
|
||||
void PCB_REFERENCE_IMAGE::SetTransformOriginOffsetY( int aY )
|
||||
{
|
||||
VECTOR2I offset = m_referenceImage.GetTransformOriginOffset();
|
||||
offset.y = aY;
|
||||
m_referenceImage.SetTransformOriginOffset( offset );
|
||||
}
|
||||
|
||||
|
||||
double PCB_REFERENCE_IMAGE::GetImageScale() const
|
||||
{
|
||||
return m_referenceImage.GetImageScale();
|
||||
}
|
||||
|
||||
|
||||
void PCB_REFERENCE_IMAGE::SetImageScale( double aScale )
|
||||
{
|
||||
m_referenceImage.SetImageScale( aScale );
|
||||
}
|
||||
|
||||
|
||||
static struct PCB_REFERENCE_IMAGE_DESC
|
||||
{
|
||||
PCB_REFERENCE_IMAGE_DESC()
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include <board_item.h>
|
||||
#include <bitmap_base.h>
|
||||
#include <reference_image.h>
|
||||
|
||||
|
||||
/**
|
||||
@ -44,39 +45,11 @@ public:
|
||||
|
||||
PCB_REFERENCE_IMAGE& operator=( const BOARD_ITEM& aItem );
|
||||
|
||||
const BITMAP_BASE* GetImage() const
|
||||
{
|
||||
wxCHECK_MSG( m_bitmapBase != nullptr, nullptr,
|
||||
wxS( "Invalid PCB_REFERENCE_IMAGE init, m_bitmapBase is NULL." ) );
|
||||
return m_bitmapBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only use this if you really need to modify the underlying image
|
||||
* @return the underlying reference image object.
|
||||
*/
|
||||
BITMAP_BASE* MutableImage() const
|
||||
{
|
||||
return m_bitmapBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the image "zoom" value.
|
||||
* scale = 1.0 = original size of bitmap.
|
||||
* scale < 1.0 = the bitmap is drawn smaller than its original size.
|
||||
* scale > 1.0 = the bitmap is drawn bigger than its original size.
|
||||
*/
|
||||
double GetImageScale() const { return m_bitmapBase->GetScale(); }
|
||||
|
||||
/**
|
||||
* Set the image "zoom" value.
|
||||
*
|
||||
* The image is scaled such that the position of the image's
|
||||
* transform origin is unchanged.
|
||||
*
|
||||
* If the scale is negaive or the image would overflow the
|
||||
* the coordinate system, nothing is updated.
|
||||
*/
|
||||
void SetImageScale( double aScale );
|
||||
REFERENCE_IMAGE& GetReferenceImage() { return m_referenceImage; }
|
||||
const REFERENCE_IMAGE& GetReferenceImage() const { return m_referenceImage; }
|
||||
|
||||
static inline bool ClassOf( const EDA_ITEM* aItem )
|
||||
{
|
||||
@ -85,11 +58,6 @@ public:
|
||||
|
||||
wxString GetClass() const override { return wxT( "PCB_REFERENCE_IMAGE" ); }
|
||||
|
||||
/**
|
||||
* @return the actual size (in user units, not in pixels) of the image.
|
||||
*/
|
||||
const VECTOR2I GetSize() const;
|
||||
|
||||
double ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const override;
|
||||
|
||||
const BOX2I GetBoundingBox() const override;
|
||||
@ -102,26 +70,6 @@ public:
|
||||
/// @copydoc VIEW_ITEM::ViewGetLayers()
|
||||
virtual void ViewGetLayers( int aLayers[], int& aCount ) const override;
|
||||
|
||||
/**
|
||||
* Read and store an image file.
|
||||
*
|
||||
* Initialize the bitmap used to draw this item format.
|
||||
*
|
||||
* @param aFullFilename is the full filename of the image file to read.
|
||||
* @return true if success reading else false.
|
||||
*/
|
||||
bool ReadImageFile( const wxString& aFullFilename );
|
||||
|
||||
/**
|
||||
* Read and store an image file.
|
||||
*
|
||||
* Initialize the bitmap used to draw this item format.
|
||||
*
|
||||
* @param aBuf is the memory buffer containing the image file to read.
|
||||
* @return true if success reading else false.
|
||||
*/
|
||||
bool ReadImageFile( wxMemoryBuffer& aBuf );
|
||||
|
||||
void Move( const VECTOR2I& aMoveVector ) override;
|
||||
|
||||
void Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection ) override;
|
||||
@ -139,7 +87,7 @@ public:
|
||||
/**
|
||||
* Get the position of the image (this is the center of the image).
|
||||
*/
|
||||
VECTOR2I GetPosition() const override { return m_pos; }
|
||||
VECTOR2I GetPosition() const override;
|
||||
|
||||
/**
|
||||
* Set the position of the image.
|
||||
@ -148,12 +96,6 @@ public:
|
||||
*/
|
||||
void SetPosition( const VECTOR2I& aPosition ) override;
|
||||
|
||||
/**
|
||||
* Get the center of scaling, etc, relative to the image center (GetPosition()).
|
||||
*/
|
||||
VECTOR2I GetTransformOriginOffset() const { return m_transformOriginOffset; }
|
||||
void SetTransformOriginOffset( const VECTOR2I& aCenter ) { m_transformOriginOffset = aCenter; }
|
||||
|
||||
bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
|
||||
bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override;
|
||||
|
||||
@ -168,18 +110,20 @@ public:
|
||||
void Show( int nestLevel, std::ostream& os ) const override;
|
||||
#endif
|
||||
|
||||
// Property manager interfaces
|
||||
int GetTransformOriginOffsetX() const { return m_transformOriginOffset.x; }
|
||||
void SetTransformOriginOffsetX( int aX ) { m_transformOriginOffset.x = aX; }
|
||||
int GetTransformOriginOffsetY() const { return m_transformOriginOffset.y; }
|
||||
void SetTransformOriginOffsetY( int aY ) { m_transformOriginOffset.y = aY; }
|
||||
|
||||
protected:
|
||||
void swapData( BOARD_ITEM* aItem ) override;
|
||||
|
||||
private:
|
||||
VECTOR2I m_pos; // XY coordinates of center of the bitmap
|
||||
///< Center of scaling, etc, relative to the image center
|
||||
VECTOR2I m_transformOriginOffset;
|
||||
BITMAP_BASE* m_bitmapBase; // the BITMAP_BASE item
|
||||
friend struct PCB_REFERENCE_IMAGE_DESC;
|
||||
|
||||
// Property manager interfaces
|
||||
int GetTransformOriginOffsetX() const;
|
||||
void SetTransformOriginOffsetX( int aX );
|
||||
int GetTransformOriginOffsetY() const;
|
||||
void SetTransformOriginOffsetY( int aY );
|
||||
|
||||
double GetImageScale() const;
|
||||
void SetImageScale( double aScale );
|
||||
|
||||
REFERENCE_IMAGE m_referenceImage;
|
||||
};
|
||||
|
@ -746,7 +746,7 @@ int DRAWING_TOOL::PlaceReferenceImage( const TOOL_EVENT& aEvent )
|
||||
if( wxFileExists( fullFilename ) )
|
||||
image = new PCB_REFERENCE_IMAGE( m_frame->GetModel(), cursorPos );
|
||||
|
||||
if( !image || !image->ReadImageFile( fullFilename ) )
|
||||
if( !image || !image->GetReferenceImage().ReadImageFile( fullFilename ) )
|
||||
{
|
||||
wxMessageBox( wxString::Format(_( "Could not load image from '%s'." ), fullFilename ) );
|
||||
delete image;
|
||||
|
@ -214,16 +214,18 @@ std::shared_ptr<EDIT_POINTS> PCB_POINT_EDITOR::makePoints( EDA_ITEM* aItem )
|
||||
{
|
||||
case PCB_REFERENCE_IMAGE_T:
|
||||
{
|
||||
const PCB_REFERENCE_IMAGE* refImage = static_cast<const PCB_REFERENCE_IMAGE*>( aItem );
|
||||
const VECTOR2I topLeft = refImage->GetPosition() - refImage->GetSize() / 2;
|
||||
const VECTOR2I botRight = refImage->GetPosition() + refImage->GetSize() / 2;
|
||||
const REFERENCE_IMAGE& refImage =
|
||||
static_cast<const PCB_REFERENCE_IMAGE&>( *aItem ).GetReferenceImage();
|
||||
|
||||
const VECTOR2I topLeft = refImage.GetPosition() - refImage.GetSize() / 2;
|
||||
const VECTOR2I botRight = refImage.GetPosition() + refImage.GetSize() / 2;
|
||||
|
||||
points->AddPoint( topLeft );
|
||||
points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
|
||||
points->AddPoint( botRight );
|
||||
points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
|
||||
|
||||
points->AddPoint( refImage->GetPosition() + refImage->GetTransformOriginOffset() );
|
||||
points->AddPoint( refImage.GetPosition() + refImage.GetTransformOriginOffset() );
|
||||
|
||||
break;
|
||||
}
|
||||
@ -1361,7 +1363,8 @@ void PCB_POINT_EDITOR::updateItem( BOARD_COMMIT* aCommit )
|
||||
{
|
||||
case PCB_REFERENCE_IMAGE_T:
|
||||
{
|
||||
PCB_REFERENCE_IMAGE* bitmap = static_cast<PCB_REFERENCE_IMAGE*>( item );
|
||||
PCB_REFERENCE_IMAGE& bitmap = static_cast<PCB_REFERENCE_IMAGE&>( *item );
|
||||
REFERENCE_IMAGE& refImg = bitmap.GetReferenceImage();
|
||||
const VECTOR2I topLeft = m_editPoints->Point( RECT_TOP_LEFT ).GetPosition();
|
||||
const VECTOR2I topRight = m_editPoints->Point( RECT_TOP_RIGHT ).GetPosition();
|
||||
const VECTOR2I botLeft = m_editPoints->Point( RECT_BOT_LEFT ).GetPosition();
|
||||
@ -1373,52 +1376,53 @@ void PCB_POINT_EDITOR::updateItem( BOARD_COMMIT* aCommit )
|
||||
// Moving the transform origin
|
||||
// As the other points didn't move, we can get the image extent from them
|
||||
const VECTOR2I newOffset = xfrmOrigin - ( topLeft + botRight ) / 2;
|
||||
bitmap->SetTransformOriginOffset( newOffset );
|
||||
refImg.SetTransformOriginOffset( newOffset );
|
||||
}
|
||||
else
|
||||
{
|
||||
const VECTOR2I oldOrigin = bitmap->GetPosition() + bitmap->GetTransformOriginOffset();
|
||||
const VECTOR2I oldSize = bitmap->GetSize();
|
||||
const VECTOR2I oldOrigin = refImg.GetPosition() + refImg.GetTransformOriginOffset();
|
||||
const VECTOR2I oldSize = refImg.GetSize();
|
||||
const VECTOR2I pos = refImg.GetPosition();
|
||||
|
||||
OPT_VECTOR2I newCorner;
|
||||
OPT_VECTOR2I oldCorner;
|
||||
VECTOR2I oldCorner = pos;
|
||||
|
||||
if( isModified( m_editPoints->Point( RECT_TOP_LEFT ) ) )
|
||||
{
|
||||
newCorner = topLeft;
|
||||
oldCorner = ( bitmap->GetPosition() - oldSize / 2 );
|
||||
oldCorner -= oldSize / 2;
|
||||
}
|
||||
else if( isModified( m_editPoints->Point( RECT_TOP_RIGHT ) ) )
|
||||
{
|
||||
newCorner = topRight;
|
||||
oldCorner = ( bitmap->GetPosition() - VECTOR2I( -oldSize.x, oldSize.y ) / 2 );
|
||||
oldCorner -= VECTOR2I( -oldSize.x, oldSize.y ) / 2;
|
||||
}
|
||||
else if( isModified( m_editPoints->Point( RECT_BOT_LEFT ) ) )
|
||||
{
|
||||
newCorner = botLeft;
|
||||
oldCorner = ( bitmap->GetPosition() - VECTOR2I( oldSize.x, -oldSize.y ) / 2 );
|
||||
oldCorner -= VECTOR2I( oldSize.x, -oldSize.y ) / 2;
|
||||
}
|
||||
else if( isModified( m_editPoints->Point( RECT_BOT_RIGHT ) ) )
|
||||
{
|
||||
newCorner = botRight;
|
||||
oldCorner = ( bitmap->GetPosition() + oldSize / 2 );
|
||||
oldCorner += oldSize / 2;
|
||||
}
|
||||
|
||||
if( newCorner && oldCorner )
|
||||
if( newCorner )
|
||||
{
|
||||
// Turn in the respective vectors from the origin
|
||||
*newCorner -= xfrmOrigin;
|
||||
*oldCorner -= oldOrigin;
|
||||
oldCorner -= oldOrigin;
|
||||
|
||||
// If we tried to cross the origin, clamp it to stop it
|
||||
if( sign( newCorner->x ) != sign( oldCorner->x )
|
||||
|| sign( newCorner->y ) != sign( oldCorner->y ) )
|
||||
if( sign( newCorner->x ) != sign( oldCorner.x )
|
||||
|| sign( newCorner->y ) != sign( oldCorner.y ) )
|
||||
{
|
||||
*newCorner = VECTOR2I( 0, 0 );
|
||||
}
|
||||
|
||||
const double newLength = newCorner->EuclideanNorm();
|
||||
const double oldLength = oldCorner->EuclideanNorm();
|
||||
const double oldLength = oldCorner.EuclideanNorm();
|
||||
|
||||
double ratio = oldLength > 0 ? ( newLength / oldLength ) : 1.0;
|
||||
|
||||
@ -1429,7 +1433,7 @@ void PCB_POINT_EDITOR::updateItem( BOARD_COMMIT* aCommit )
|
||||
ratio = std::min( newWidth / oldSize.x, newHeight / oldSize.y );
|
||||
|
||||
// Also handles the origin offset
|
||||
bitmap->SetImageScale( bitmap->GetImageScale() * ratio );
|
||||
refImg.SetImageScale( refImg.GetImageScale() * ratio );
|
||||
}
|
||||
}
|
||||
|
||||
@ -2064,9 +2068,10 @@ void PCB_POINT_EDITOR::updatePoints()
|
||||
{
|
||||
case PCB_REFERENCE_IMAGE_T:
|
||||
{
|
||||
const PCB_REFERENCE_IMAGE* bitmap = static_cast<const PCB_REFERENCE_IMAGE*>( item );
|
||||
const VECTOR2I topLeft = bitmap->GetPosition() - bitmap->GetSize() / 2;
|
||||
const VECTOR2I botRight = bitmap->GetPosition() + bitmap->GetSize() / 2;
|
||||
const REFERENCE_IMAGE& refImg =
|
||||
static_cast<const PCB_REFERENCE_IMAGE&>( *item ).GetReferenceImage();
|
||||
const VECTOR2I topLeft = refImg.GetPosition() - refImg.GetSize() / 2;
|
||||
const VECTOR2I botRight = refImg.GetPosition() + refImg.GetSize() / 2;
|
||||
|
||||
m_editPoints->Point( RECT_TOP_LEFT ).SetPosition( topLeft );
|
||||
m_editPoints->Point( RECT_TOP_RIGHT ).SetPosition( botRight.x, topLeft.y );
|
||||
@ -2074,7 +2079,7 @@ void PCB_POINT_EDITOR::updatePoints()
|
||||
m_editPoints->Point( RECT_BOT_RIGHT ).SetPosition( botRight );
|
||||
|
||||
m_editPoints->Point( REFIMG_ORIGIN )
|
||||
.SetPosition( bitmap->GetPosition() + bitmap->GetTransformOriginOffset() );
|
||||
.SetPosition( refImg.GetPosition() + refImg.GetTransformOriginOffset() );
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -3580,8 +3580,8 @@ void PCB_SELECTION_TOOL::GuessSelectionCandidates( GENERAL_COLLECTOR& aCollector
|
||||
}
|
||||
else if( item->Type() == PCB_REFERENCE_IMAGE_T )
|
||||
{
|
||||
VECTOR2D size = static_cast<const PCB_REFERENCE_IMAGE*>( item )->GetSize();
|
||||
area = size.x * size.y;
|
||||
BOX2I box = item->GetBoundingBox();
|
||||
area = (double) box.GetWidth() * box.GetHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -105,18 +105,15 @@ BOOST_FIXTURE_TEST_CASE( ReferenceImageLoading, REFERENCE_IMAGE_LOAD_TEST_FIXTUR
|
||||
const auto& image =
|
||||
static_cast<PCB_REFERENCE_IMAGE&>( KI_TEST::RequireBoardItemWithTypeAndId(
|
||||
aBoard, PCB_REFERENCE_IMAGE_T, imageTestCase.m_imageUuid ) );
|
||||
const REFERENCE_IMAGE& refImage = image.GetReferenceImage();
|
||||
|
||||
BOOST_CHECK_EQUAL( image.IsLocked(), imageTestCase.m_expectedLocked );
|
||||
BOOST_CHECK_EQUAL( image.GetPosition(), imageTestCase.m_expectedPos * 1000000 );
|
||||
BOOST_CHECK_CLOSE( image.GetImageScale(), imageTestCase.m_expectedScale, 1e-6 );
|
||||
BOOST_CHECK_CLOSE( refImage.GetImageScale(), imageTestCase.m_expectedScale, 1e-6 );
|
||||
|
||||
const BITMAP_BASE* bitmap = image.GetImage();
|
||||
const BITMAP_BASE& bitmap = refImage.GetImage();
|
||||
|
||||
BOOST_REQUIRE( bitmap );
|
||||
|
||||
BOOST_TEST_MESSAGE( "Got underlying image" );
|
||||
|
||||
BOOST_CHECK_EQUAL( bitmap->GetSizePixels(), imageTestCase.m_expectedPixelSize );
|
||||
BOOST_CHECK_EQUAL( bitmap.GetSizePixels(), imageTestCase.m_expectedPixelSize );
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user