1265 lines
37 KiB
C++
1265 lines
37 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: zones.cpp
|
|
// Purpose:
|
|
// Author: jean-pierre Charras
|
|
// Modified by:
|
|
// Created: 25/01/2006 11:35:19
|
|
// RCS-ID:
|
|
// Copyright: GNU License
|
|
// Licence: GNU License
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Generated by DialogBlocks (unregistered), 25/01/2006 11:35:19
|
|
|
|
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
|
|
#pragma implementation "zones.h"
|
|
#endif
|
|
|
|
// For compilers that support precompilation, includes "wx/wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/wx.h"
|
|
#endif
|
|
|
|
////@begin includes
|
|
////@end includes
|
|
|
|
#include "zones.h"
|
|
|
|
////@begin XPM images
|
|
////@end XPM images
|
|
|
|
/* Routines Locales */
|
|
static void Display_Zone_Netname(WinEDA_PcbFrame *frame);
|
|
static void Exit_Zones(WinEDA_DrawPanel * Panel, wxDC *DC);
|
|
static void Show_Zone_Edge_While_MoveMouse(WinEDA_DrawPanel * panel, wxDC * DC, bool erase);
|
|
static void Genere_Segments_Zone(WinEDA_PcbFrame *frame, wxDC * DC, int net_code);
|
|
static bool Genere_Pad_Connexion(WinEDA_PcbFrame *frame, wxDC * DC, int layer);
|
|
|
|
/* Variables locales */
|
|
static bool Zone_Debug = FALSE;
|
|
static bool Zone_45_Only = FALSE;
|
|
static bool Zone_Exclude_Pads = TRUE;
|
|
static bool Zone_Genere_Freins_Thermiques = TRUE;
|
|
|
|
static unsigned long s_TimeStamp; /* signature temporelle pour la zone generee */
|
|
|
|
/*!
|
|
* WinEDA_ZoneFrame type definition
|
|
*/
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS( WinEDA_ZoneFrame, wxDialog )
|
|
|
|
/*!
|
|
* WinEDA_ZoneFrame event table definition
|
|
*/
|
|
|
|
BEGIN_EVENT_TABLE( WinEDA_ZoneFrame, wxDialog )
|
|
|
|
////@begin WinEDA_ZoneFrame event table entries
|
|
EVT_BUTTON( ID_FILL_ZONE, WinEDA_ZoneFrame::ExecFillZone )
|
|
|
|
EVT_BUTTON( wxID_CANCEL, WinEDA_ZoneFrame::OnCancelClick )
|
|
|
|
EVT_BUTTON( ID_SET_OPTIONS_ZONE, WinEDA_ZoneFrame::ExecFillZone )
|
|
|
|
////@end WinEDA_ZoneFrame event table entries
|
|
|
|
END_EVENT_TABLE()
|
|
|
|
/*!
|
|
* WinEDA_ZoneFrame constructors
|
|
*/
|
|
|
|
WinEDA_ZoneFrame::WinEDA_ZoneFrame( )
|
|
{
|
|
}
|
|
|
|
WinEDA_ZoneFrame::WinEDA_ZoneFrame( WinEDA_PcbFrame* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
|
|
{
|
|
m_Parent = parent;
|
|
Create(parent, id, caption, pos, size, style);
|
|
}
|
|
|
|
/*!
|
|
* WinEDA_ZoneFrame creator
|
|
*/
|
|
|
|
bool WinEDA_ZoneFrame::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
|
|
{
|
|
////@begin WinEDA_ZoneFrame member initialisation
|
|
m_GridCtrl = NULL;
|
|
m_ClearanceValueTitle = NULL;
|
|
m_ZoneClearanceCtrl = NULL;
|
|
m_FillOpt = NULL;
|
|
m_OrientEdgesOpt = NULL;
|
|
////@end WinEDA_ZoneFrame member initialisation
|
|
|
|
////@begin WinEDA_ZoneFrame creation
|
|
SetExtraStyle(GetExtraStyle()|wxWS_EX_BLOCK_EVENTS);
|
|
wxDialog::Create( parent, id, caption, pos, size, style );
|
|
|
|
CreateControls();
|
|
GetSizer()->Fit(this);
|
|
GetSizer()->SetSizeHints(this);
|
|
Centre();
|
|
////@end WinEDA_ZoneFrame creation
|
|
|
|
return true;
|
|
}
|
|
|
|
/*!
|
|
* Control creation for WinEDA_ZoneFrame
|
|
*/
|
|
|
|
void WinEDA_ZoneFrame::CreateControls()
|
|
{
|
|
SetFont(*g_DialogFont);
|
|
|
|
////@begin WinEDA_ZoneFrame content construction
|
|
// Generated by DialogBlocks, 03/03/2006 13:36:21 (unregistered)
|
|
|
|
WinEDA_ZoneFrame* itemDialog1 = this;
|
|
|
|
wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxHORIZONTAL);
|
|
itemDialog1->SetSizer(itemBoxSizer2);
|
|
|
|
wxBoxSizer* itemBoxSizer3 = new wxBoxSizer(wxVERTICAL);
|
|
itemBoxSizer2->Add(itemBoxSizer3, 0, wxGROW|wxALL, 5);
|
|
|
|
wxString m_GridCtrlStrings[] = {
|
|
_("0.00000"),
|
|
_("0.00000"),
|
|
_("0.00000"),
|
|
_("0.00000")
|
|
};
|
|
m_GridCtrl = new wxRadioBox( itemDialog1, ID_RADIOBOX, _("Grid size:"), wxDefaultPosition, wxDefaultSize, 4, m_GridCtrlStrings, 1, wxRA_SPECIFY_COLS );
|
|
itemBoxSizer3->Add(m_GridCtrl, 0, wxALIGN_LEFT|wxALL, 5);
|
|
|
|
m_ClearanceValueTitle = new wxStaticText( itemDialog1, wxID_STATIC, _("Zone clearance value (mm):"), wxDefaultPosition, wxDefaultSize, 0 );
|
|
itemBoxSizer3->Add(m_ClearanceValueTitle, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
|
|
|
|
m_ZoneClearanceCtrl = new wxTextCtrl( itemDialog1, ID_TEXTCTRL, _T(""), wxDefaultPosition, wxDefaultSize, 0 );
|
|
itemBoxSizer3->Add(m_ZoneClearanceCtrl, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxBOTTOM, 5);
|
|
|
|
itemBoxSizer2->Add(5, 5, 0, wxGROW|wxALL, 5);
|
|
|
|
wxBoxSizer* itemBoxSizer8 = new wxBoxSizer(wxVERTICAL);
|
|
itemBoxSizer2->Add(itemBoxSizer8, 0, wxGROW|wxALL, 5);
|
|
|
|
wxString m_FillOptStrings[] = {
|
|
_("Include Pads"),
|
|
_("Thermal"),
|
|
_("Exclude Pads")
|
|
};
|
|
m_FillOpt = new wxRadioBox( itemDialog1, ID_RADIOBOX1, _("Pad options:"), wxDefaultPosition, wxDefaultSize, 3, m_FillOptStrings, 1, wxRA_SPECIFY_COLS );
|
|
itemBoxSizer8->Add(m_FillOpt, 0, wxALIGN_LEFT|wxALL, 5);
|
|
|
|
wxString m_OrientEdgesOptStrings[] = {
|
|
_("Any"),
|
|
_("H , V and 45 deg")
|
|
};
|
|
m_OrientEdgesOpt = new wxRadioBox( itemDialog1, ID_RADIOBOX2, _("Zone edges orient:"), wxDefaultPosition, wxDefaultSize, 2, m_OrientEdgesOptStrings, 1, wxRA_SPECIFY_COLS );
|
|
itemBoxSizer8->Add(m_OrientEdgesOpt, 0, wxALIGN_RIGHT|wxALL, 5);
|
|
|
|
itemBoxSizer2->Add(5, 5, 0, wxGROW|wxALL, 5);
|
|
|
|
wxBoxSizer* itemBoxSizer12 = new wxBoxSizer(wxVERTICAL);
|
|
itemBoxSizer2->Add(itemBoxSizer12, 0, wxALIGN_TOP|wxALL, 5);
|
|
|
|
wxButton* itemButton13 = new wxButton( itemDialog1, ID_FILL_ZONE, _("Fill"), wxDefaultPosition, wxDefaultSize, 0 );
|
|
itemButton13->SetDefault();
|
|
itemButton13->SetForegroundColour(wxColour(204, 0, 0));
|
|
itemBoxSizer12->Add(itemButton13, 0, wxGROW|wxALL, 5);
|
|
|
|
wxButton* itemButton14 = new wxButton( itemDialog1, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
|
|
itemButton14->SetForegroundColour(wxColour(0, 0, 255));
|
|
itemBoxSizer12->Add(itemButton14, 0, wxGROW|wxALL, 5);
|
|
|
|
wxButton* itemButton15 = new wxButton( itemDialog1, ID_SET_OPTIONS_ZONE, _("Update Options"), wxDefaultPosition, wxDefaultSize, 0 );
|
|
itemButton15->SetForegroundColour(wxColour(0, 100, 0));
|
|
itemBoxSizer12->Add(itemButton15, 0, wxGROW|wxALL, 5);
|
|
|
|
itemBoxSizer2->Add(5, 5, 0, wxGROW|wxALL, 5);
|
|
|
|
////@end WinEDA_ZoneFrame content construction
|
|
wxString title = _("Zone clearance value:") + ReturnUnitSymbol(g_UnitMetric);
|
|
m_ClearanceValueTitle->SetLabel( title );
|
|
|
|
title = _("Grid :") + ReturnUnitSymbol(g_UnitMetric);;
|
|
m_GridCtrl->SetLabel(title);
|
|
|
|
if ( g_DesignSettings.m_ZoneClearence == 0 )
|
|
g_DesignSettings.m_ZoneClearence = g_DesignSettings.m_TrackClearence;
|
|
title = ReturnStringFromValue( g_UnitMetric, g_DesignSettings.m_ZoneClearence, m_Parent->m_InternalUnits);
|
|
m_ZoneClearanceCtrl->SetValue( title );
|
|
|
|
if ( Zone_45_Only ) m_OrientEdgesOpt->SetSelection(1);
|
|
|
|
int GridList[4] = { 50,100,250,500}, selection = 0;
|
|
for ( unsigned ii = 0; ii < m_GridCtrl->GetCount(); ii++ )
|
|
{
|
|
wxString msg = ReturnStringFromValue(g_UnitMetric, GridList[ii], m_Parent->m_InternalUnits);
|
|
m_GridCtrl->SetString(ii,msg);
|
|
if ( g_GridRoutingSize == GridList[ii] ) selection = ii;
|
|
}
|
|
m_GridCtrl->SetSelection(selection);
|
|
|
|
if ( Zone_Exclude_Pads)
|
|
{
|
|
if ( Zone_Genere_Freins_Thermiques ) m_FillOpt->SetSelection(1);
|
|
else m_FillOpt->SetSelection(2);
|
|
}
|
|
|
|
}
|
|
|
|
/*!
|
|
* Should we show tooltips?
|
|
*/
|
|
|
|
bool WinEDA_ZoneFrame::ShowToolTips()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/*!
|
|
* Get bitmap resources
|
|
*/
|
|
|
|
wxBitmap WinEDA_ZoneFrame::GetBitmapResource( const wxString& name )
|
|
{
|
|
// Bitmap retrieval
|
|
////@begin WinEDA_ZoneFrame bitmap retrieval
|
|
wxUnusedVar(name);
|
|
return wxNullBitmap;
|
|
////@end WinEDA_ZoneFrame bitmap retrieval
|
|
}
|
|
|
|
/*!
|
|
* Get icon resources
|
|
*/
|
|
|
|
wxIcon WinEDA_ZoneFrame::GetIconResource( const wxString& name )
|
|
{
|
|
// Icon retrieval
|
|
////@begin WinEDA_ZoneFrame icon retrieval
|
|
wxUnusedVar(name);
|
|
return wxNullIcon;
|
|
////@end WinEDA_ZoneFrame icon retrieval
|
|
}
|
|
|
|
/*!
|
|
* wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL
|
|
*/
|
|
|
|
void WinEDA_ZoneFrame::OnCancelClick( wxCommandEvent& event )
|
|
{
|
|
////@begin wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL in WinEDA_ZoneFrame.
|
|
// Before editing this code, remove the block markers.
|
|
event.Skip();
|
|
////@end wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL in WinEDA_ZoneFrame.
|
|
}
|
|
|
|
|
|
/*!
|
|
* wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON2
|
|
*/
|
|
/***********************************************************/
|
|
void WinEDA_ZoneFrame::ExecFillZone( wxCommandEvent & event)
|
|
/***********************************************************/
|
|
{
|
|
switch ( m_FillOpt->GetSelection() )
|
|
{
|
|
case 0:
|
|
Zone_Exclude_Pads = FALSE;
|
|
Zone_Genere_Freins_Thermiques = FALSE;
|
|
break;
|
|
|
|
case 1:
|
|
Zone_Exclude_Pads = TRUE;
|
|
Zone_Genere_Freins_Thermiques = TRUE;
|
|
break;
|
|
|
|
case 2:
|
|
Zone_Exclude_Pads = TRUE;
|
|
Zone_Genere_Freins_Thermiques = FALSE;
|
|
break;
|
|
}
|
|
|
|
switch ( m_GridCtrl->GetSelection() )
|
|
{
|
|
case 0:
|
|
g_GridRoutingSize = 50;
|
|
break;
|
|
|
|
case 1:
|
|
g_GridRoutingSize = 100;
|
|
break;
|
|
|
|
case 2:
|
|
g_GridRoutingSize = 250;
|
|
break;
|
|
|
|
case 3:
|
|
g_GridRoutingSize = 500;
|
|
break;
|
|
}
|
|
|
|
wxString txtvalue = m_ZoneClearanceCtrl->GetValue();
|
|
g_DesignSettings.m_ZoneClearence =
|
|
ReturnValueFromString( g_UnitMetric, txtvalue, m_Parent->m_InternalUnits);
|
|
if ( m_OrientEdgesOpt->GetSelection() == 0) Zone_45_Only = FALSE;
|
|
else Zone_45_Only = TRUE;
|
|
|
|
if ( event.GetId() == ID_SET_OPTIONS_ZONE ) EndModal(1);
|
|
else EndModal(0);
|
|
}
|
|
|
|
/**************************************************************/
|
|
void WinEDA_PcbFrame::Edit_Zone_Width(wxDC * DC, SEGZONE * Zone)
|
|
/**************************************************************/
|
|
/* Edite (change la largeur des segments) la zone Zone.
|
|
La zone est constituee des segments zones de meme TimeStamp
|
|
*/
|
|
{
|
|
SEGZONE * pt_segm, * NextS ;
|
|
unsigned long TimeStamp;
|
|
bool modify = FALSE;
|
|
double f_new_width;
|
|
int w_tmp;
|
|
wxString Line;
|
|
wxString Msg( _("New zone segment width: ") );
|
|
|
|
if ( Zone == NULL ) return;
|
|
|
|
f_new_width = To_User_Unit(g_UnitMetric, Zone->m_Width, GetScreen()->GetInternalUnits());
|
|
Line.Printf(wxT("%.4f"), f_new_width);
|
|
Msg += g_UnitMetric ? wxT("(mm)") : wxT("(\")");
|
|
if ( Get_Message(Msg, Line, this) != 0 ) return;
|
|
|
|
w_tmp = g_DesignSettings.m_CurrentTrackWidth;
|
|
Line.ToDouble( &f_new_width);
|
|
g_DesignSettings.m_CurrentTrackWidth = From_User_Unit(g_UnitMetric, f_new_width, GetScreen()->GetInternalUnits());
|
|
|
|
TimeStamp = Zone->m_TimeStamp;
|
|
|
|
for( pt_segm = (SEGZONE*)m_Pcb->m_Zone; pt_segm != NULL; pt_segm = NextS)
|
|
{
|
|
NextS = (SEGZONE*) pt_segm->Pnext;
|
|
if(pt_segm->m_TimeStamp == TimeStamp)
|
|
{
|
|
modify = TRUE;
|
|
Edit_TrackSegm_Width(DC, pt_segm);
|
|
}
|
|
}
|
|
|
|
g_DesignSettings.m_CurrentTrackWidth = w_tmp;
|
|
if ( modify )
|
|
{
|
|
GetScreen()->SetModify();
|
|
DrawPanel->Refresh();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**********************************************************/
|
|
void WinEDA_PcbFrame::Delete_Zone(wxDC * DC, SEGZONE * Zone)
|
|
/**********************************************************/
|
|
/* Efface la zone Zone.
|
|
La zone est constituee des segments zones de meme TimeStamp
|
|
*/
|
|
{
|
|
SEGZONE * pt_segm, * NextS ;
|
|
unsigned long TimeStamp;
|
|
int nb_segm = 0;
|
|
bool modify = FALSE;
|
|
|
|
TimeStamp = Zone->m_TimeStamp;
|
|
|
|
for( pt_segm = (SEGZONE*)m_Pcb->m_Zone; pt_segm != NULL; pt_segm = NextS)
|
|
{
|
|
NextS = (SEGZONE*) pt_segm->Pnext;
|
|
if(pt_segm->m_TimeStamp == TimeStamp)
|
|
{
|
|
modify = TRUE;
|
|
/* effacement des segments a l'ecran */
|
|
Trace_Une_Piste(DrawPanel, DC, pt_segm, nb_segm, GR_XOR);
|
|
DeleteStructure(pt_segm);
|
|
}
|
|
}
|
|
|
|
if ( modify )
|
|
{
|
|
GetScreen()->SetModify();
|
|
GetScreen()->SetRefreshReq();
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
EDGE_ZONE * WinEDA_PcbFrame::Del_SegmEdgeZone(wxDC * DC, EDGE_ZONE * edge_zone)
|
|
/*****************************************************************************/
|
|
/* Routine d'effacement du segment de limite zone en cours de trace */
|
|
{
|
|
EDGE_ZONE * Segm, * previous_segm;
|
|
|
|
if (m_Pcb->m_CurrentLimitZone) Segm = m_Pcb->m_CurrentLimitZone;
|
|
else Segm = edge_zone;
|
|
|
|
if( Segm == NULL) return NULL;
|
|
|
|
Trace_DrawSegmentPcb(DrawPanel, DC, Segm, GR_XOR);
|
|
|
|
previous_segm = (EDGE_ZONE *)Segm->Pback;
|
|
delete Segm;
|
|
|
|
Segm = previous_segm;
|
|
m_Pcb->m_CurrentLimitZone = Segm;
|
|
GetScreen()->m_CurrentItem = Segm;
|
|
|
|
if( Segm )
|
|
{
|
|
Segm->Pnext = NULL;
|
|
if( DrawPanel->ManageCurseur)
|
|
DrawPanel->ManageCurseur(DrawPanel, DC, TRUE);
|
|
}
|
|
else
|
|
{
|
|
DrawPanel->ManageCurseur = NULL;
|
|
DrawPanel->ForceCloseManageCurseur = NULL;
|
|
GetScreen()->m_CurrentItem = NULL;
|
|
}
|
|
return Segm;
|
|
}
|
|
|
|
|
|
/*********************************************/
|
|
void WinEDA_PcbFrame::CaptureNetName(wxDC * DC)
|
|
/*********************************************/
|
|
/* routine permettant de capturer le nom net net (netcode) d'un pad
|
|
ou d'une piste pour l'utiliser comme netcode de zone
|
|
*/
|
|
{
|
|
D_PAD* pt_pad = 0;
|
|
TRACK * adrpiste ;
|
|
MODULE * Module;
|
|
int masquelayer = g_TabOneLayerMask[GetScreen()->m_Active_Layer];
|
|
int netcode;
|
|
|
|
netcode = -1;
|
|
MsgPanel->EraseMsgBox();
|
|
adrpiste = Locate_Pistes(m_Pcb->m_Track, masquelayer,CURSEUR_OFF_GRILLE);
|
|
if ( adrpiste == NULL )
|
|
{
|
|
pt_pad = Locate_Any_Pad(m_Pcb, CURSEUR_OFF_GRILLE);
|
|
|
|
if(pt_pad) /* Verif qu'il est bien sur la couche active */
|
|
{
|
|
Module = (MODULE*) pt_pad->m_Parent;
|
|
pt_pad = Locate_Pads(Module,g_TabOneLayerMask[GetScreen()->m_Active_Layer],
|
|
CURSEUR_OFF_GRILLE);
|
|
}
|
|
if( pt_pad )
|
|
{
|
|
pt_pad->Display_Infos(this);
|
|
netcode = pt_pad->m_NetCode;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Affiche_Infos_Piste(this, adrpiste) ;
|
|
netcode = adrpiste->m_NetCode;
|
|
}
|
|
|
|
// Mise en surbrillance du net
|
|
if(g_HightLigt_Status) Hight_Light(DC);
|
|
g_HightLigth_NetCode = netcode;
|
|
|
|
if ( g_HightLigth_NetCode >= 0 )
|
|
{
|
|
Hight_Light(DC);
|
|
}
|
|
|
|
/* Affichage du net selectionne pour la zone a tracer */
|
|
Display_Zone_Netname(this);
|
|
}
|
|
|
|
/*******************************************************/
|
|
static void Display_Zone_Netname(WinEDA_PcbFrame *frame)
|
|
/*******************************************************/
|
|
/*
|
|
Affiche le net_code et le nom de net couramment selectionne
|
|
*/
|
|
{
|
|
EQUIPOT * pt_equipot;
|
|
wxString line;
|
|
|
|
pt_equipot = frame->m_Pcb->m_Equipots;
|
|
|
|
if( g_HightLigth_NetCode > 0 )
|
|
{
|
|
for( ; pt_equipot != NULL; pt_equipot = (EQUIPOT*)pt_equipot->Pnext)
|
|
{
|
|
if( pt_equipot->m_NetCode == g_HightLigth_NetCode) break;
|
|
}
|
|
if( pt_equipot )
|
|
{
|
|
line.Printf( wxT("Zone: Net[%d] <%s>"),g_HightLigth_NetCode,
|
|
pt_equipot->m_Netname.GetData());
|
|
}
|
|
else line.Printf( wxT("Zone: NetCode[%d], Equipot not found"),
|
|
g_HightLigth_NetCode);
|
|
}
|
|
|
|
line = _("Zone: No net selected");
|
|
|
|
frame->Affiche_Message(line);
|
|
}
|
|
|
|
/********************************************************/
|
|
static void Exit_Zones(WinEDA_DrawPanel * Panel, wxDC *DC)
|
|
/********************************************************/
|
|
/* routine d'annulation de la Commande Begin_Zone si une piste est en cours
|
|
de tracage, ou de sortie de l'application SEGZONES.
|
|
Appel par la touche ESC
|
|
*/
|
|
{
|
|
WinEDA_PcbFrame* pcbframe = (WinEDA_PcbFrame*)Panel->m_Parent;
|
|
|
|
if( pcbframe->m_Pcb->m_CurrentLimitZone )
|
|
{
|
|
if( Panel->ManageCurseur ) /* trace en cours */
|
|
{
|
|
Panel->ManageCurseur(Panel, DC, 0);
|
|
}
|
|
pcbframe->DelLimitesZone(DC, FALSE);
|
|
}
|
|
|
|
Panel->ManageCurseur = NULL;
|
|
Panel->ForceCloseManageCurseur = NULL;
|
|
pcbframe->GetScreen()->m_CurrentItem = NULL;
|
|
|
|
}
|
|
|
|
|
|
/**************************************************************/
|
|
void WinEDA_BasePcbFrame::DelLimitesZone(wxDC *DC, bool Redraw)
|
|
/**************************************************************/
|
|
/* Supprime la liste des segments constituant la frontiere courante
|
|
Libere la memoire correspondante
|
|
*/
|
|
{
|
|
EDGE_ZONE * segment, * Next;
|
|
|
|
if( m_Pcb->m_CurrentLimitZone == NULL ) return;
|
|
|
|
if ( ! IsOK(this, _("Delete Current Zone Edges")) ) return;
|
|
/* efface ancienne limite de zone */
|
|
segment = m_Pcb->m_CurrentLimitZone;
|
|
for( ; segment != NULL; segment = Next)
|
|
{
|
|
Next = (EDGE_ZONE*) segment->Pback;
|
|
if ( Redraw ) Trace_DrawSegmentPcb(DrawPanel, DC, segment,GR_XOR);
|
|
segment->Pnext = NULL; delete segment;
|
|
}
|
|
|
|
GetScreen()->m_CurrentItem = NULL;
|
|
m_Pcb->m_CurrentLimitZone = NULL;
|
|
}
|
|
|
|
/********************************************/
|
|
EDGE_ZONE * WinEDA_PcbFrame::Begin_Zone(void)
|
|
/********************************************/
|
|
/*
|
|
Routine d'initialisation d'un trace de Limite de Zone ou
|
|
de placement d'un point intermediaire
|
|
*/
|
|
{
|
|
EDGE_ZONE * oldedge, * newedge = NULL;
|
|
|
|
oldedge = m_Pcb->m_CurrentLimitZone;
|
|
|
|
if( (m_Pcb->m_CurrentLimitZone == NULL ) || /* debut reel du trace */
|
|
(DrawPanel->ManageCurseur == NULL) ) /* reprise d'un trace complementaire */
|
|
{
|
|
m_Pcb->m_CurrentLimitZone = newedge = new EDGE_ZONE( m_Pcb );
|
|
|
|
newedge->m_Flags = IS_NEW | STARTPOINT | IS_MOVED;
|
|
newedge->Pback = oldedge;
|
|
if(oldedge) oldedge->Pnext = newedge;
|
|
newedge->m_Layer = GetScreen()->m_Active_Layer;
|
|
newedge->m_Width = 2 ; /* Largeur minimum tracable */
|
|
newedge->m_Start = newedge->m_End = GetScreen()->m_Curseur;
|
|
|
|
m_Pcb->m_CurrentLimitZone = newedge;
|
|
DrawPanel->ManageCurseur = Show_Zone_Edge_While_MoveMouse;
|
|
DrawPanel->ForceCloseManageCurseur = Exit_Zones;
|
|
}
|
|
|
|
else /* piste en cours : les coord du point d'arrivee ont ete mises
|
|
a jour par la routine Show_Zone_Edge_While_MoveMouse*/
|
|
{
|
|
if( (oldedge->m_Start.x != oldedge->m_End.x) ||
|
|
(oldedge->m_Start.y != oldedge->m_End.y) )
|
|
{
|
|
newedge = new EDGE_ZONE( oldedge);
|
|
newedge->Pback = oldedge;
|
|
oldedge->Pnext = newedge;
|
|
newedge->m_Flags = IS_NEW | IS_MOVED;
|
|
newedge->m_Start = newedge->m_End = oldedge->m_End;
|
|
newedge->m_Layer = GetScreen()->m_Active_Layer;
|
|
m_Pcb->m_CurrentLimitZone = newedge;
|
|
}
|
|
}
|
|
|
|
return newedge;
|
|
}
|
|
|
|
/*********************************************/
|
|
void WinEDA_PcbFrame::End_Zone(wxDC * DC)
|
|
/*********************************************/
|
|
/*
|
|
Routine de fin de trace d'une zone (succession de segments)
|
|
*/
|
|
{
|
|
EDGE_ZONE * PtLim;
|
|
|
|
if( m_Pcb->m_CurrentLimitZone )
|
|
{
|
|
Begin_Zone();
|
|
|
|
/* le dernier point genere est de longueur tj nulle donc inutile. */
|
|
/* il sera raccorde au point de depart */
|
|
PtLim = m_Pcb->m_CurrentLimitZone;
|
|
PtLim->m_Flags &= ~(IS_NEW|IS_MOVED);
|
|
while( PtLim && PtLim->Pback)
|
|
{
|
|
PtLim = (EDGE_ZONE*) PtLim->Pback;
|
|
if ( PtLim->m_Flags & STARTPOINT) break;
|
|
PtLim->m_Flags &= ~(IS_NEW|IS_MOVED);
|
|
}
|
|
|
|
if( PtLim )
|
|
{
|
|
PtLim->m_Flags &= ~(IS_NEW|IS_MOVED);
|
|
m_Pcb->m_CurrentLimitZone->m_End = PtLim->m_Start;
|
|
}
|
|
Trace_DrawSegmentPcb(DrawPanel, DC, m_Pcb->m_CurrentLimitZone,GR_XOR);
|
|
}
|
|
|
|
DrawPanel->ManageCurseur = NULL;
|
|
DrawPanel->ForceCloseManageCurseur = NULL;
|
|
}
|
|
|
|
|
|
/******************************************************************************************/
|
|
static void Show_Zone_Edge_While_MoveMouse(WinEDA_DrawPanel * panel, wxDC * DC, bool erase)
|
|
/******************************************************************************************/
|
|
/* redessin du contour de la piste lors des deplacements de la souris
|
|
*/
|
|
{
|
|
EDGE_ZONE * PtLim, * edgezone;
|
|
WinEDA_PcbFrame * pcbframe = (WinEDA_PcbFrame *) panel->m_Parent;
|
|
|
|
if( pcbframe->m_Pcb->m_CurrentLimitZone == NULL ) return ;
|
|
|
|
/* efface ancienne position si elle a ete deja dessinee */
|
|
if( erase )
|
|
{
|
|
PtLim = pcbframe->m_Pcb->m_CurrentLimitZone;
|
|
for( ; PtLim != NULL; PtLim = (EDGE_ZONE*) PtLim->Pback)
|
|
{
|
|
Trace_DrawSegmentPcb(panel, DC, PtLim,GR_XOR);
|
|
}
|
|
}
|
|
|
|
/* mise a jour de la couche */
|
|
edgezone = PtLim = pcbframe->m_Pcb->m_CurrentLimitZone;
|
|
for( ; PtLim != NULL; PtLim = (EDGE_ZONE*) PtLim->Pback)
|
|
{
|
|
PtLim->m_Layer = pcbframe->GetScreen()->m_Active_Layer;
|
|
}
|
|
|
|
/* dessin de la nouvelle piste : mise a jour du point d'arrivee */
|
|
if (Zone_45_Only)
|
|
{/* Calcul de l'extremite de la piste pour orientations permises:
|
|
horiz,vertical ou 45 degre */
|
|
edgezone->m_End = pcbframe->GetScreen()->m_Curseur;
|
|
Calcule_Coord_Extremite_45(edgezone->m_Start.x, edgezone->m_Start.y,
|
|
&edgezone->m_End.x, &edgezone->m_End.y);
|
|
}
|
|
else /* ici l'angle d'inclinaison est quelconque */
|
|
{
|
|
edgezone->m_End = pcbframe->GetScreen()->m_Curseur;
|
|
}
|
|
|
|
PtLim = edgezone;
|
|
for( ; PtLim != NULL; PtLim = (EDGE_ZONE*) PtLim->Pback)
|
|
{
|
|
Trace_DrawSegmentPcb(panel, DC, PtLim,GR_XOR);
|
|
}
|
|
}
|
|
|
|
|
|
/**********************************************/
|
|
void WinEDA_PcbFrame::Fill_Zone(wxDC * DC)
|
|
/**********************************************/
|
|
/*
|
|
Fonction generale de creation de zone
|
|
Un contour de zone doit exister, sinon l'ensemble du PCB est utilise
|
|
|
|
ce qui permet de creer des obstacles et donc des parties non remplies.
|
|
|
|
Le remplissage s'effectue a partir du point d'ancrage, jusque ves les limites
|
|
|
|
|
|
On place la zone sur la couche (layer) active.
|
|
|
|
|
|
"Hight Light" la zone fera partie de ce net
|
|
*/
|
|
{
|
|
int ii, jj;
|
|
EDGE_ZONE* PtLim;
|
|
int lp_tmp, lay_tmp_TOP, lay_tmp_BOTTOM;
|
|
EQUIPOT* pt_equipot;
|
|
int save_isol = g_DesignSettings.m_TrackClearence;
|
|
wxPoint ZoneStartFill;
|
|
wxString msg;
|
|
|
|
MsgPanel->EraseMsgBox();
|
|
if ( m_Pcb->ComputeBoundaryBox() == FALSE )
|
|
{
|
|
DisplayError(this, wxT("Board is empty!"), 10);
|
|
return;
|
|
}
|
|
DrawPanel->m_IgnoreMouseEvents = TRUE;
|
|
WinEDA_ZoneFrame * frame = new WinEDA_ZoneFrame(this);
|
|
ii = frame->ShowModal(); frame->Destroy();
|
|
DrawPanel->MouseToCursorSchema();
|
|
DrawPanel->m_IgnoreMouseEvents = FALSE;
|
|
if ( ii ) return;
|
|
|
|
g_DesignSettings.m_TrackClearence = g_DesignSettings.m_ZoneClearence;
|
|
|
|
/* mise a jour de la couche */
|
|
PtLim = m_Pcb->m_CurrentLimitZone;
|
|
for( ; PtLim != NULL; PtLim = (EDGE_ZONE*) PtLim->Pback)
|
|
{
|
|
Trace_DrawSegmentPcb(DrawPanel, DC, PtLim, GR_XOR);
|
|
PtLim->m_Layer = GetScreen()->m_Active_Layer;
|
|
Trace_DrawSegmentPcb(DrawPanel, DC, PtLim, GR_XOR);
|
|
}
|
|
|
|
s_TimeStamp = time( NULL );
|
|
|
|
/* Calcul du pas de routage fixe a 5 mils et plus */
|
|
E_scale = g_GridRoutingSize / 50 ; if (g_GridRoutingSize < 1 ) g_GridRoutingSize = 1 ;
|
|
|
|
/* calcule de Ncols et Nrow, taille de la matrice de routage */
|
|
ComputeMatriceSize(this, g_GridRoutingSize);
|
|
|
|
/* Determination de la cellule pointee par la souris */
|
|
ZoneStartFill.x = (GetScreen()->m_Curseur.x - m_Pcb->m_BoundaryBox.m_Pos.x + (g_GridRoutingSize/2) ) / g_GridRoutingSize;
|
|
ZoneStartFill.y = (GetScreen()->m_Curseur.y - m_Pcb->m_BoundaryBox.m_Pos.y + (g_GridRoutingSize/2) ) / g_GridRoutingSize;
|
|
if(ZoneStartFill.x < 0) ZoneStartFill.x = 0;
|
|
if(ZoneStartFill.x >= Ncols) ZoneStartFill.x = Ncols-1;
|
|
if(ZoneStartFill.y < 0) ZoneStartFill.y = 0;
|
|
if(ZoneStartFill.y >= Nrows) ZoneStartFill.y = Nrows-1;
|
|
|
|
/* Creation du mapping de la matrice de routage */
|
|
Nb_Sides = ONE_SIDE;
|
|
if( Board.InitBoard() < 0)
|
|
{
|
|
DisplayError(this, wxT("Mo memory for creating zones"));
|
|
return;
|
|
}
|
|
|
|
msg.Printf( wxT("%d"),Ncols);
|
|
Affiche_1_Parametre(this, 1, wxT("Cols"),msg,GREEN);
|
|
msg.Printf( wxT("%d"),Nrows);
|
|
Affiche_1_Parametre(this, 7, wxT("Lines"),msg,GREEN);
|
|
msg.Printf( wxT("%d"), Board.m_MemSize / 1024 );
|
|
Affiche_1_Parametre(this, 14, wxT("Mem(Ko)"),msg,CYAN);
|
|
|
|
lay_tmp_BOTTOM = Route_Layer_BOTTOM;
|
|
lay_tmp_TOP = Route_Layer_TOP;
|
|
|
|
Route_Layer_BOTTOM = Route_Layer_TOP = GetScreen()->m_Active_Layer;
|
|
lp_tmp = g_DesignSettings.m_CurrentTrackWidth; g_DesignSettings.m_CurrentTrackWidth = g_GridRoutingSize;
|
|
|
|
/* Affichage du NetName */
|
|
if(g_HightLigth_NetCode > 0)
|
|
{
|
|
pt_equipot = GetEquipot(m_Pcb, g_HightLigth_NetCode);
|
|
if( pt_equipot == NULL)
|
|
{
|
|
if(g_HightLigth_NetCode > 0 ) DisplayError(this, wxT("Equipot Error"));
|
|
}
|
|
else msg = pt_equipot->m_Netname;
|
|
}
|
|
else msg = _("No Net");
|
|
|
|
Affiche_1_Parametre(this, 22,_("NetName"),msg,RED) ;
|
|
|
|
/* Init des points d'accrochage possibles de la zone:
|
|
les pistes du net sont des points d'accrochage convenables*/
|
|
TRACK * pt_segm = m_Pcb->m_Track;
|
|
for( ; pt_segm != NULL; pt_segm = (TRACK*) pt_segm->Pnext)
|
|
{
|
|
if(g_HightLigth_NetCode != pt_segm->m_NetCode) continue;
|
|
if ( pt_segm->m_Layer != GetScreen()->m_Active_Layer ) continue;
|
|
if (pt_segm->m_StructType != TYPETRACK ) continue;
|
|
TraceSegmentPcb(m_Pcb, pt_segm, CELL_is_FRIEND, 0, WRITE_CELL );
|
|
}
|
|
|
|
/* Trace des contours du PCB sur la matrice de routage: */
|
|
Route_Layer_BOTTOM = Route_Layer_TOP = EDGE_N;
|
|
PlaceCells(m_Pcb, -1, 0);
|
|
Route_Layer_BOTTOM = Route_Layer_TOP = GetScreen()->m_Active_Layer;
|
|
|
|
/* Trace des limites de la zone sur la matrice de routage: */
|
|
PtLim = m_Pcb->m_CurrentLimitZone;
|
|
for( ; PtLim != NULL; PtLim = (EDGE_ZONE*)PtLim->Pback)
|
|
{
|
|
int ux0, uy0, ux1, uy1;
|
|
ux0 = PtLim->m_Start.x - m_Pcb->m_BoundaryBox.m_Pos.x;
|
|
uy0 = PtLim->m_Start.y - m_Pcb->m_BoundaryBox.m_Pos.y;
|
|
ux1 = PtLim->m_End.x - m_Pcb->m_BoundaryBox.m_Pos.x;
|
|
uy1 = PtLim->m_End.y - m_Pcb->m_BoundaryBox.m_Pos.y;
|
|
TraceLignePcb(ux0,uy0,ux1,uy1,-1,HOLE|CELL_is_EDGE,WRITE_CELL);
|
|
}
|
|
|
|
|
|
OrCell(ZoneStartFill.y,ZoneStartFill.x, BOTTOM, CELL_is_ZONE);
|
|
|
|
/* Marquage des cellules faisant partie de la zone*/
|
|
ii = 1; jj = 1;
|
|
while( ii )
|
|
{
|
|
msg.Printf( wxT("%d"), jj++ );
|
|
Affiche_1_Parametre(this, 50, wxT("Iter."),msg,CYAN);
|
|
ii = Propagation(this);
|
|
}
|
|
|
|
/* Selection des cellules convenables pour les points d'ancrage de la zone */
|
|
for( ii = 0; ii < Nrows ; ii++)
|
|
{
|
|
for( jj = 0; jj < Ncols ; jj++)
|
|
{
|
|
long cell = GetCell(ii,jj,BOTTOM);
|
|
if( (cell & CELL_is_ZONE) )
|
|
{
|
|
if ( (cell & CELL_is_FRIEND) == 0)
|
|
AndCell(ii,jj,BOTTOM, (BoardCell) ~(CELL_is_FRIEND|CELL_is_ZONE) );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Maintenant, toutes les cellules candidates sont marquees */
|
|
/* Placement des cellules (pads, tracks, vias, edges pcb ou segments)
|
|
faisant des obsctacles sur la matrice de routage */
|
|
ii = 0;
|
|
if( Zone_Exclude_Pads ) ii = FORCE_PADS;
|
|
Affiche_1_Parametre(this, 42, wxT("GenZone"),wxEmptyString,RED);
|
|
PlaceCells(m_Pcb, g_HightLigth_NetCode, ii);
|
|
Affiche_1_Parametre(this, -1, wxEmptyString, _("Ok"),RED);
|
|
|
|
/* Trace des limites de la zone sur la matrice de routage
|
|
(a pu etre detruit par PlaceCells()) : */
|
|
PtLim = m_Pcb->m_CurrentLimitZone;
|
|
for( ; PtLim != NULL; PtLim = (EDGE_ZONE*)PtLim->Pback)
|
|
{
|
|
int ux0, uy0, ux1, uy1;
|
|
ux0 = PtLim->m_Start.x - m_Pcb->m_BoundaryBox.m_Pos.x;
|
|
uy0 = PtLim->m_Start.y - m_Pcb->m_BoundaryBox.m_Pos.y;
|
|
ux1 = PtLim->m_End.x - m_Pcb->m_BoundaryBox.m_Pos.x;
|
|
uy1 = PtLim->m_End.y - m_Pcb->m_BoundaryBox.m_Pos.y;
|
|
TraceLignePcb(ux0,uy0,ux1,uy1,-1,HOLE|CELL_is_EDGE,WRITE_CELL);
|
|
}
|
|
|
|
|
|
/* Init du point d'accrochage de la zone donné par la position souris
|
|
(a pu etre detruit par PlaceCells()) : */
|
|
OrCell(ZoneStartFill.y,ZoneStartFill.x, BOTTOM, CELL_is_ZONE);
|
|
|
|
if(Zone_Debug) DisplayBoard(DrawPanel, DC);
|
|
|
|
/* Remplissage des cellules (creation effective de la zone)*/
|
|
ii = 1; jj = 1;
|
|
while( ii )
|
|
{
|
|
msg.Printf( wxT("%d"), jj++ );
|
|
Affiche_1_Parametre(this, 50, wxT("Iter."),msg,CYAN);
|
|
ii = Propagation(this);
|
|
}
|
|
|
|
if(Zone_Debug) DisplayBoard(DrawPanel, DC);
|
|
|
|
/* Generation des segments de piste type Zone correspondants*/
|
|
if(g_HightLigth_NetCode < 0 )
|
|
Genere_Segments_Zone(this, DC, 0);
|
|
else Genere_Segments_Zone(this, DC, g_HightLigth_NetCode);
|
|
|
|
/* Trace des connexions type frein thermique */
|
|
g_DesignSettings.m_CurrentTrackWidth = lp_tmp;
|
|
if ( Zone_Exclude_Pads && Zone_Genere_Freins_Thermiques)
|
|
Genere_Pad_Connexion(this, DC, GetScreen()->m_Active_Layer);
|
|
|
|
g_DesignSettings.m_TrackClearence = save_isol;
|
|
|
|
GetScreen()->SetModify();
|
|
|
|
/* Liberation de la memoire */
|
|
Board.UnInitBoard();
|
|
|
|
/* Reprise des conditions initiales */
|
|
Route_Layer_TOP = lay_tmp_TOP;
|
|
Route_Layer_BOTTOM = lay_tmp_BOTTOM;
|
|
}
|
|
|
|
|
|
/*******************************************************************************/
|
|
static void Genere_Segments_Zone(WinEDA_PcbFrame *frame, wxDC * DC, int net_code)
|
|
/*******************************************************************************/
|
|
/* Genere les segments de piste dans les limites de la zone a remplir
|
|
Algorithme:
|
|
procede en 2 balayages
|
|
- Gauche->droite
|
|
- Haut->Bas
|
|
Parametres:
|
|
net_code = net_code a attribuer au segment de zone
|
|
TimeStamp(global): signature temporelle d'identification
|
|
(mis en .start)
|
|
*/
|
|
{
|
|
int row, col;
|
|
long current_cell, old_cell;
|
|
int ux0 = 0, uy0 = 0, ux1 = 0, uy1 = 0;
|
|
int Xmin = frame->m_Pcb->m_BoundaryBox.m_Pos.x;
|
|
int Ymin = frame->m_Pcb->m_BoundaryBox.m_Pos.y;
|
|
SEGZONE * pt_track;
|
|
int layer = frame->GetScreen()->m_Active_Layer;
|
|
int nbsegm = 0;
|
|
wxString msg;
|
|
|
|
/* balayage Gauche-> droite */
|
|
Affiche_1_Parametre(frame, 64, wxT("Segm H"), wxT("0"),BROWN);
|
|
for( row = 0; row < Nrows ; row++)
|
|
{
|
|
old_cell = 0;
|
|
uy0 = uy1 = (row * g_GridRoutingSize) + Ymin;
|
|
for( col = 0; col < Ncols ; col++)
|
|
{
|
|
current_cell = GetCell(row,col,BOTTOM) & CELL_is_ZONE;
|
|
if(current_cell) /* ce point doit faire partie d'un segment */
|
|
{
|
|
ux1 = (col * g_GridRoutingSize) + Xmin;
|
|
if( old_cell == 0 ) ux0 = ux1;
|
|
}
|
|
|
|
if( ! current_cell || (col == Ncols-1) ) /* peut etre fin d'un segment */
|
|
{
|
|
if( (old_cell) && (ux0 != ux1) )
|
|
{ /* un segment avait debute de longueur > 0 */
|
|
pt_track = new SEGZONE(frame->m_Pcb);
|
|
pt_track->m_Layer = layer;
|
|
pt_track->m_NetCode = net_code;
|
|
pt_track->m_Width = g_GridRoutingSize;
|
|
pt_track->m_Start.x = ux0; pt_track->m_Start.y = uy0;
|
|
pt_track->m_End.x = ux1; pt_track->m_End.y = uy1;
|
|
pt_track->m_TimeStamp = s_TimeStamp;
|
|
pt_track->Insert(frame->m_Pcb, NULL);
|
|
pt_track->Draw(frame->DrawPanel, DC, GR_OR);
|
|
nbsegm++;
|
|
}
|
|
}
|
|
old_cell = current_cell;
|
|
}
|
|
msg.Printf( wxT("%d"),nbsegm);
|
|
Affiche_1_Parametre(frame, -1, wxEmptyString,msg,BROWN);
|
|
}
|
|
|
|
Affiche_1_Parametre(frame, 72, wxT("Segm V"), wxT("0"),BROWN);
|
|
for( col = 0; col < Ncols ; col++)
|
|
{
|
|
old_cell = 0;
|
|
ux0 = ux1 = (col * g_GridRoutingSize) + Xmin;
|
|
for( row = 0; row < Nrows ; row++)
|
|
{
|
|
current_cell = GetCell(row,col,BOTTOM) & CELL_is_ZONE;
|
|
if(current_cell) /* ce point doit faire partie d'un segment */
|
|
{
|
|
uy1 = (row * g_GridRoutingSize) + Ymin;
|
|
if( old_cell == 0 ) uy0 = uy1;
|
|
}
|
|
if( ! current_cell || (row == Nrows-1) ) /* peut etre fin d'un segment */
|
|
{
|
|
if( (old_cell) && (uy0 != uy1) )
|
|
{ /* un segment avait debute de longueur > 0 */
|
|
pt_track = new SEGZONE(frame->m_Pcb);
|
|
pt_track->m_Layer = layer;
|
|
pt_track->m_Width = g_GridRoutingSize;
|
|
pt_track->m_NetCode = net_code;
|
|
pt_track->m_Start.x = ux0; pt_track->m_Start.y = uy0;
|
|
pt_track->m_End.x = ux1; pt_track->m_End.y = uy1;
|
|
pt_track->m_TimeStamp = s_TimeStamp;
|
|
pt_track->Insert(frame->m_Pcb, NULL);
|
|
pt_track->Draw(frame->DrawPanel, DC, GR_OR);
|
|
nbsegm++;
|
|
}
|
|
}
|
|
old_cell = current_cell;
|
|
}
|
|
msg.Printf( wxT("%d"),nbsegm);
|
|
Affiche_1_Parametre(frame, -1, wxEmptyString,msg,BROWN);
|
|
}
|
|
}
|
|
|
|
|
|
/********************************************/
|
|
int Propagation(WinEDA_PcbFrame * frame)
|
|
/********************************************/
|
|
/* Determine les cellules inscrites dans les limites de la zone a remplir
|
|
Algorithme:
|
|
Si une cellule disponible a un voisin faisant partie de la zone, elle
|
|
devient elle meme partie de la zone
|
|
On procede en 4 balayages de la matrice des cellules
|
|
- Gauche->droite de Haut->bas
|
|
- Droite->gauche de Haut->bas
|
|
- Bas->Haut de Droite->gauche
|
|
- Bas->Haut de Gauche->Droite
|
|
et pour chaque balayage, on considere des 2 cellules voisines de
|
|
la cellule courants: cellule precedente sur la ligne et cellule precedente
|
|
sur la colonne.
|
|
|
|
La routine peut demander plusieurs iterations
|
|
les iterations doivent continuer juqu'a ce que la routine ne trouve plus
|
|
de cellules a modifier.
|
|
Retourne:
|
|
Nombre de cellules modifiees (c.a.d mises a la valeur CELL_is_ZONE.
|
|
*/
|
|
{
|
|
int row, col, nn;
|
|
long current_cell, old_cell_H;
|
|
int long * pt_cell_V;
|
|
int nbpoints = 0;
|
|
#define NO_CELL_ZONE (HOLE | CELL_is_EDGE | CELL_is_ZONE)
|
|
wxString msg;
|
|
|
|
Affiche_1_Parametre(frame, 57, wxT("Detect"),msg,CYAN);
|
|
/* balayage Gauche-> droite de Haut->bas */
|
|
Affiche_1_Parametre(frame, -1, wxEmptyString, wxT("1"),CYAN);
|
|
|
|
// Reservation memoire pour stockahe de 1 ligne ou une colonne de cellules
|
|
nn = MAX(Nrows, Ncols) * sizeof(*pt_cell_V);
|
|
pt_cell_V = (long *) MyMalloc(nn);
|
|
memset(pt_cell_V, 0, nn);
|
|
for( row = 0; row < Nrows ; row++)
|
|
{
|
|
old_cell_H = 0;
|
|
for( col = 0; col < Ncols ; col++)
|
|
{
|
|
current_cell = GetCell(row,col,BOTTOM) & NO_CELL_ZONE;
|
|
if(current_cell == 0 ) /* une cellule libre a ete trouvee */
|
|
{
|
|
if( (old_cell_H & CELL_is_ZONE)
|
|
|| (pt_cell_V[col] & CELL_is_ZONE) )
|
|
{
|
|
OrCell(row,col,BOTTOM,CELL_is_ZONE);
|
|
current_cell = CELL_is_ZONE;
|
|
nbpoints++;
|
|
}
|
|
}
|
|
pt_cell_V[col] = old_cell_H = current_cell;
|
|
}
|
|
}
|
|
|
|
/* balayage Droite-> gauche de Haut->bas */
|
|
Affiche_1_Parametre(frame, -1, wxEmptyString, wxT("2"),CYAN);
|
|
memset(pt_cell_V, 0, nn);
|
|
for( row = 0; row < Nrows ; row++)
|
|
{
|
|
old_cell_H = 0;
|
|
for( col = Ncols -1 ; col >= 0 ; col--)
|
|
{
|
|
current_cell = GetCell(row,col,BOTTOM) & NO_CELL_ZONE ;
|
|
if(current_cell == 0 ) /* une cellule libre a ete trouvee */
|
|
{
|
|
if( (old_cell_H & CELL_is_ZONE)
|
|
|| (pt_cell_V[col] & CELL_is_ZONE) )
|
|
{
|
|
OrCell(row,col,BOTTOM,CELL_is_ZONE);
|
|
current_cell = CELL_is_ZONE;
|
|
nbpoints++;
|
|
}
|
|
}
|
|
pt_cell_V[col] = old_cell_H = current_cell;
|
|
}
|
|
}
|
|
|
|
/* balayage Bas->Haut de Droite->gauche */
|
|
Affiche_1_Parametre(frame, -1, wxEmptyString, wxT("3"),CYAN);
|
|
memset(pt_cell_V, 0, nn);
|
|
for( col = Ncols -1 ; col >= 0 ; col--)
|
|
{
|
|
old_cell_H = 0;
|
|
for( row = Nrows-1; row >= 0 ; row--)
|
|
{
|
|
current_cell = GetCell(row,col,BOTTOM) & NO_CELL_ZONE ;
|
|
if(current_cell == 0 ) /* une cellule libre a ete trouvee */
|
|
{
|
|
if( (old_cell_H & CELL_is_ZONE)
|
|
|| (pt_cell_V[row] & CELL_is_ZONE) )
|
|
{
|
|
OrCell(row,col,BOTTOM,CELL_is_ZONE);
|
|
current_cell = CELL_is_ZONE;
|
|
nbpoints++;
|
|
}
|
|
}
|
|
pt_cell_V[row] = old_cell_H = current_cell;
|
|
}
|
|
}
|
|
|
|
/* balayage Bas->Haut de Gauche->Droite*/
|
|
Affiche_1_Parametre(frame, -1, wxEmptyString, wxT("4"),CYAN);
|
|
memset(pt_cell_V, 0, nn);
|
|
for( col = 0 ; col < Ncols ; col++)
|
|
{
|
|
old_cell_H = 0;
|
|
for( row = Nrows-1; row >= 0 ; row--)
|
|
{
|
|
current_cell = GetCell(row,col,BOTTOM) & NO_CELL_ZONE ;
|
|
if(current_cell == 0 ) /* une cellule libre a ete trouvee */
|
|
{
|
|
if( (old_cell_H & CELL_is_ZONE)
|
|
|| (pt_cell_V[row] & CELL_is_ZONE) )
|
|
{
|
|
OrCell(row,col,BOTTOM,CELL_is_ZONE) ;
|
|
current_cell = CELL_is_ZONE;
|
|
nbpoints++;
|
|
}
|
|
}
|
|
pt_cell_V[row] = old_cell_H = current_cell;
|
|
}
|
|
}
|
|
|
|
MyFree(pt_cell_V);
|
|
|
|
return(nbpoints);
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
static bool Genere_Pad_Connexion(WinEDA_PcbFrame *frame, wxDC * DC, int layer)
|
|
/*****************************************************************************/
|
|
/* Generation des segments de zone de connexion zone / pad pour constitution
|
|
de freins thermiques
|
|
*/
|
|
{
|
|
int ii, jj, Npads;
|
|
D_PAD * pt_pad;
|
|
LISTE_PAD * pt_liste_pad;
|
|
TRACK * pt_track, * loctrack;
|
|
int angle;
|
|
int cX, cY, dx, dy;
|
|
int sommet[4][2];
|
|
wxString msg;
|
|
|
|
if( frame->m_Pcb->m_Zone == NULL ) return FALSE; /* pas de zone */
|
|
if( frame->m_Pcb->m_Zone->m_TimeStamp != s_TimeStamp ) /* c'est une autre zone */
|
|
return FALSE;
|
|
|
|
/* Calcul du nombre de pads a traiter et affichage */
|
|
Affiche_1_Parametre(frame, 50, wxT("NPads"),wxT(" "),CYAN);
|
|
pt_liste_pad = (LISTE_PAD*) frame->m_Pcb->m_Pads;
|
|
for ( ii = 0, Npads = 0; ii < frame->m_Pcb->m_NbPads; ii++, pt_liste_pad++)
|
|
{
|
|
pt_pad = *pt_liste_pad;
|
|
/* la pastille doit etre du meme net */
|
|
if(pt_pad->m_NetCode != g_HightLigth_NetCode) continue;
|
|
/* la pastille doit exister sur la couche */
|
|
if( (pt_pad->m_Masque_Layer & g_TabOneLayerMask[layer]) == 0 ) continue;
|
|
Npads++;
|
|
}
|
|
msg.Printf( wxT("%d"), Npads );
|
|
Affiche_1_Parametre(frame, -1, wxEmptyString,msg,CYAN);
|
|
|
|
Affiche_1_Parametre(frame, 57, wxT("Pads"), wxT(" "),CYAN);
|
|
pt_liste_pad = (LISTE_PAD*) frame->m_Pcb->m_Pads;
|
|
for ( ii = 0, Npads = 0; ii < frame->m_Pcb->m_NbPads; ii++, pt_liste_pad++)
|
|
{
|
|
pt_pad = *pt_liste_pad;
|
|
|
|
/* la pastille doit etre du meme net */
|
|
if(pt_pad->m_NetCode != g_HightLigth_NetCode) continue;
|
|
/* la pastille doit exister sur la couche */
|
|
if( (pt_pad->m_Masque_Layer & g_TabOneLayerMask[layer]) == 0 ) continue;
|
|
|
|
/* traitement du pad en cours */
|
|
Npads++; msg.Printf( wxT("%d"), Npads );
|
|
Affiche_1_Parametre(frame, -1, wxEmptyString,msg,CYAN);
|
|
cX = pt_pad->m_Pos.x; cY = pt_pad->m_Pos.y;
|
|
dx = pt_pad->m_Size.x / 2;
|
|
dy = pt_pad->m_Size.y / 2;
|
|
dx += g_DesignSettings.m_TrackClearence + g_GridRoutingSize;
|
|
dy += g_DesignSettings.m_TrackClearence + g_GridRoutingSize;
|
|
|
|
if(pt_pad->m_PadShape == TRAPEZE)
|
|
{
|
|
dx += abs(pt_pad->m_DeltaSize.y) / 2;
|
|
dy += abs(pt_pad->m_DeltaSize.x) / 2;
|
|
}
|
|
|
|
/* calcul des coord des 4 segments a rajouter a partir du centre cX,cY */
|
|
sommet[0][0] = 0; sommet[0][1] = -dy;
|
|
sommet[1][0] = -dx; sommet[1][1] = 0;
|
|
sommet[2][0] = 0; sommet[2][1] = dy;
|
|
sommet[3][0] = dx; sommet[3][1] = 0;
|
|
|
|
angle = pt_pad->m_Orient;
|
|
for(jj = 0; jj < 4; jj++)
|
|
{
|
|
RotatePoint(&sommet[jj][0], &sommet[jj][1], angle);
|
|
|
|
pt_track = new SEGZONE(frame->m_Pcb);
|
|
|
|
pt_track->m_Layer = layer;
|
|
pt_track->m_Width = g_DesignSettings.m_CurrentTrackWidth;
|
|
pt_track->m_NetCode = g_HightLigth_NetCode;
|
|
pt_track->start = pt_pad;
|
|
pt_track->m_Start.x = cX; pt_track->m_Start.y = cY;
|
|
pt_track->m_End.x = cX + sommet[jj][0];
|
|
pt_track->m_End.y = cY + sommet[jj][1];
|
|
pt_track->m_TimeStamp = s_TimeStamp;
|
|
|
|
/* tst si trace possible */
|
|
if( Drc(frame, DC, pt_track,frame->m_Pcb->m_Track,0) == BAD_DRC )
|
|
{
|
|
delete pt_track; continue;
|
|
}
|
|
|
|
/* on doit pouvoir se connecter sur la zone */
|
|
loctrack = Locate_Zone(frame->m_Pcb->m_Zone,pt_track->m_End, layer);
|
|
if( (loctrack == NULL) || (loctrack->m_TimeStamp != s_TimeStamp) )
|
|
{
|
|
delete pt_track; continue;
|
|
}
|
|
|
|
pt_track->Insert(frame->m_Pcb, NULL);
|
|
pt_track->Draw(frame->DrawPanel, DC, GR_OR);
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|