← Back to team overview

kicad-developers team mailing list archive

Zone keepouts within modules

 

Hi everyone,

I am a new developer in kicad community. I have been working on adding zones to modules, so I would like to share this work.
Find attached a patch to have this functionality.

Regards,

Simon
From c4781992a8d4cd17e4a4592fea3bdaf3ec25e31f Mon Sep 17 00:00:00 2001
From: Simon Santesteban <tech@xxxxxxxxxxxx>
Date: Mon, 19 Mar 2018 01:10:18 +0100
Subject: [PATCH] Add support for Zone keepout areas within modules
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.7.4"

This is a multi-part message in MIME format.
--------------2.7.4
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit

---
 pcbnew/board_commit.cpp                  |   4 +
 pcbnew/class_board.cpp                   |   6 ++
 pcbnew/class_board.h                     |  74 +++++++++++++
 pcbnew/class_module.cpp                  | 102 ++++++++++++++++++
 pcbnew/class_module.h                    |  45 ++++++++
 pcbnew/collectors.cpp                    |   2 +
 pcbnew/controle.cpp                      |   1 +
 pcbnew/drc.cpp                           |  24 ++---
 pcbnew/footprint_editor_onclick.cpp      |  91 +++++++++++++++-
 pcbnew/footprint_editor_utils.cpp        |   4 +
 pcbnew/kicad_clipboard.cpp               |   7 +-
 pcbnew/kicad_plugin.cpp                  |  21 +++-
 pcbnew/menubar_footprint_editor.cpp      |   5 +
 pcbnew/pcb_parser.cpp                    |  23 +++-
 pcbnew/pcbnew_id.h                       |   1 +
 pcbnew/tool_footprint_editor.cpp         |   4 +
 pcbnew/tools/drawing_tool.cpp            |   8 +-
 pcbnew/tools/pcb_actions.cpp             |   1 +
 pcbnew/tools/pcbnew_control.cpp          |   5 +
 pcbnew/tools/selection_tool.cpp          |  11 ++
 pcbnew/tools/zone_create_helper.cpp      |   9 ++
 pcbnew/zone_filler.cpp                   |   5 +-
 pcbnew/zones_functions_for_undo_redo.cpp | 173 +++++++++++++++++++++++++++++++
 pcbnew/zones_functions_for_undo_redo.h   |  24 +++++
 24 files changed, 629 insertions(+), 21 deletions(-)


--------------2.7.4
Content-Type: text/x-patch; name="0001-Add-support-for-Zone-keepout-areas-within-modules.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0001-Add-support-for-Zone-keepout-areas-within-modules.patch"

diff --git a/pcbnew/board_commit.cpp b/pcbnew/board_commit.cpp
index 57a5d62..1ae83e3 100644
--- a/pcbnew/board_commit.cpp
+++ b/pcbnew/board_commit.cpp
@@ -297,6 +297,10 @@ EDA_ITEM* BOARD_COMMIT::parentObject( EDA_ITEM* aItem ) const
         case PCB_MODULE_EDGE_T:
         case PCB_MODULE_TEXT_T:
             return aItem->GetParent();
+        case PCB_ZONE_AREA_T:
+			if(aItem->GetParent() && aItem->GetParent()->Type() == PCB_MODULE_T)
+				return aItem->GetParent();
+			// else do default
         default:
             return aItem;
     }
diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp
index c5486d8..3067f95 100644
--- a/pcbnew/class_board.cpp
+++ b/pcbnew/class_board.cpp
@@ -955,6 +955,12 @@ void BOARD::Remove( BOARD_ITEM* aBoardItem )
                 break;
             }
         }
+        
+		// search inside modules
+		for( MODULE* module = m_Modules; module; module = module->Next() )
+        {
+			module->Remove(aBoardItem);
+		}
         break;
 
     case PCB_MODULE_T:
diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h
index 81a048e..22389cd 100644
--- a/pcbnew/class_board.h
+++ b/pcbnew/class_board.h
@@ -47,6 +47,8 @@
 
 #include <memory>
 
+#include <class_module.h>
+
 using std::unique_ptr;
 
 class PCB_BASE_FRAME;
@@ -1013,6 +1015,78 @@ public:
         return (int) m_ZoneDescriptorList.size();
     }
 
+
+    /**
+     * Function GetAreaIncludingModules
+     * returns the Area (Zone Container) at a given index, including modules.
+     * @param index The array type index into a collection of ZONE_CONTAINER *.
+     * @return ZONE_CONTAINER* - a pointer to the Area or NULL if index out of range.
+     */
+    ZONE_CONTAINER* GetAreaIncludingModules( int index ) const
+    {
+        if( (unsigned) index < m_ZoneDescriptorList.size() )
+            return m_ZoneDescriptorList[index];
+
+		int count = (int) m_ZoneDescriptorList.size();
+		for( MODULE* module = m_Modules; module; module = module->Next() )
+        {
+			int n_mod = module->GetAreaCount();
+			
+			if(index < count + n_mod) {
+				// is inside this module
+				int idx = index - count;
+				return module->GetArea(idx);
+			}
+			count += n_mod;
+		}
+		
+        return NULL;
+    }
+
+    /**
+     * Function GetAreaIndexIncludingModules
+     * returns the Area Index  for the given Zone Container, including modules.
+     * @param  aArea :The ZONE_CONTAINER to find.
+     * @return an Area Index in m_ZoneDescriptorList or -1 if non found.
+     */
+    int GetAreaIndexIncludingModules( const ZONE_CONTAINER* aArea ) const
+    {
+        for( int ii = 0; ii < GetAreaCount(); ii++ )    // Search for aArea in list
+        {
+            if( aArea == GetArea( ii ) )                // Found !
+                return ii;
+        }
+
+		int count = GetAreaCount();
+		for( MODULE* module = m_Modules; module; module = module->Next() )
+        {
+			int n_mod = module->GetAreaCount();
+			int idx = module->GetAreaIndex(aArea);
+			
+			if(idx >= 0) {
+				return idx + count;
+			}
+			count += n_mod;
+		}
+        return -1;
+    }
+
+    /**
+     * Function GetAreaCountIncludingModules
+     * @return int - The number of Areas or ZONE_CONTAINER including modules.
+     */
+    int GetAreaCountIncludingModules() const
+    {
+        int ret = GetAreaCount();
+        
+        for( MODULE* module = m_Modules; module; module = module->Next() )
+        {
+			ret += module->GetAreaCount();
+		}
+        
+        return ret;
+    }
+	
     /* Functions used in test, merge and cut outlines */
 
     /**
diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp
index c201a0f..5204965 100644
--- a/pcbnew/class_module.cpp
+++ b/pcbnew/class_module.cpp
@@ -77,6 +77,8 @@ MODULE::MODULE( BOARD* parent ) :
     m_Value = new TEXTE_MODULE( this, TEXTE_MODULE::TEXT_is_VALUE );
 
     m_3D_Drawings.clear();
+    
+    m_ZoneDescriptorList.clear();
 }
 
 
@@ -139,6 +141,15 @@ MODULE::MODULE( const MODULE& aModule ) :
 
     m_arflag = 0;
 
+	// Copy zones
+	m_ZoneDescriptorList.clear();
+	for( int ii = 0; ii < aModule.GetAreaCount(); ii++ )
+	{
+		ZONE_CONTAINER* zone = aModule.GetArea( ii );
+		ZONE_CONTAINER* zone_clone = new ZONE_CONTAINER(*zone);
+		Add(static_cast<BOARD_ITEM*>(zone_clone), ADD_APPEND );
+	}
+
     // Ensure auxiliary data is up to date
     CalculateBoundingBox();
 
@@ -149,6 +160,12 @@ MODULE::MODULE( const MODULE& aModule ) :
 
 MODULE::~MODULE()
 {
+	while( m_ZoneDescriptorList.size() )
+    {
+        ZONE_CONTAINER* area_to_remove = m_ZoneDescriptorList[0];
+        Delete( area_to_remove );
+    }
+    
     delete m_Reference;
     delete m_Value;
     delete m_initial_comments;
@@ -217,6 +234,15 @@ MODULE& MODULE::operator=( const MODULE& aOther )
     m_Doc         = aOther.m_Doc;
     m_KeyWord     = aOther.m_KeyWord;
 
+	// Copy zones
+	m_ZoneDescriptorList.clear();
+	for( int ii = 0; ii < aOther.GetAreaCount(); ii++ )
+	{
+		ZONE_CONTAINER* zone = aOther.GetArea( ii );
+		ZONE_CONTAINER* zone_clone = new ZONE_CONTAINER(*zone);
+		Add(static_cast<BOARD_ITEM*>(zone_clone), ADD_APPEND );
+	}
+
     // Ensure auxiliary data is up to date
     CalculateBoundingBox();
 
@@ -224,6 +250,16 @@ MODULE& MODULE::operator=( const MODULE& aOther )
 }
 
 
+void MODULE::DeleteZONEOutlines()
+{
+    // the vector does not know how to delete the ZONE Outlines, it holds
+    // pointers
+    for( unsigned i = 0; i<m_ZoneDescriptorList.size(); ++i )
+        delete m_ZoneDescriptorList[i];
+
+    m_ZoneDescriptorList.clear();
+}
+
 void MODULE::ClearAllNets()
 {
     // Force the ORPHANED dummy net info for all pads.
@@ -273,6 +309,11 @@ void MODULE::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
             m_Pads.PushFront( static_cast<D_PAD*>( aBoardItem ) );
         break;
 
+    // this one uses a vector 
+    case PCB_ZONE_AREA_T:
+			m_ZoneDescriptorList.push_back( (ZONE_CONTAINER*) aBoardItem );
+        break;
+        
     default:
     {
         wxString msg;
@@ -301,6 +342,11 @@ void MODULE::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
         static_cast<D_PAD*>( aBoardItem )->SetLocalCoord();
         break;
 
+	case PCB_ZONE_AREA_T:
+		//static_cast<ZONE_CONTAINER*>( aBoardItem )->SetLocalCoord();
+		// TODO : create setlocalcoord function
+        break;
+    
     default:
         // Huh? It should have been filtered out by the previous switch
         assert(false);
@@ -327,6 +373,18 @@ void MODULE::Remove( BOARD_ITEM* aBoardItem )
         m_Pads.Remove( static_cast<D_PAD*>( aBoardItem ) );
         break;
 
+    case PCB_ZONE_AREA_T:    // this one uses a vector 
+        // find the item in the vector, then delete then erase it.
+        for( unsigned i = 0; i<m_ZoneDescriptorList.size(); ++i )
+        {
+            if( m_ZoneDescriptorList[i] == (ZONE_CONTAINER*) aBoardItem )
+            {
+                m_ZoneDescriptorList.erase( m_ZoneDescriptorList.begin() + i );
+                break;
+            }
+        }
+        break;
+        
     default:
     {
         wxString msg;
@@ -813,6 +871,19 @@ SEARCH_RESULT MODULE::Visit( INSPECTOR inspector, void* testData, const KICAD_T
 
             break;
 
+        case PCB_ZONE_AREA_T:
+            // PCB_ZONE_AREA_T are in the m_ZoneDescriptorList std::vector
+            for( unsigned i = 0; i< m_ZoneDescriptorList.size(); ++i )
+            {
+                result = m_ZoneDescriptorList[i]->Visit( inspector, testData, p );
+
+                if( result == SEARCH_QUIT )
+                    break;
+            }
+
+            ++p;
+            break;
+
         default:
             done = true;
             break;
@@ -859,6 +930,15 @@ void MODULE::RunOnChildren( const std::function<void (BOARD_ITEM*)>& aFunction )
         for( BOARD_ITEM* drawing = m_Drawings; drawing; drawing = drawing->Next() )
             aFunction( drawing );
 
+    	// for each module, its zones
+		for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
+		{
+			ZONE_CONTAINER* zone = this->GetArea( ii );
+
+		
+			aFunction( static_cast<BOARD_ITEM*>( zone ) );
+		}
+
         aFunction( static_cast<BOARD_ITEM*>( m_Reference ) );
         aFunction( static_cast<BOARD_ITEM*>( m_Value ) );
     }
@@ -1014,6 +1094,13 @@ void MODULE::Flip( const wxPoint& aCentre )
             break;
         }
     }
+    
+	for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
+	{
+		ZONE_CONTAINER* zone = this->GetArea( ii );
+
+		zone->Flip( m_Pos );	
+	}
 
     CalculateBoundingBox();
 }
@@ -1056,6 +1143,14 @@ void MODULE::SetPosition( const wxPoint& newpos )
             break;
         }
     }
+    
+	for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
+	{
+		ZONE_CONTAINER* zone = this->GetArea( ii );
+
+		zone->Move( delta );
+	}
+
 
     CalculateBoundingBox();
 }
@@ -1151,6 +1246,13 @@ void MODULE::SetOrientation( double newangle )
         }
     }
 
+	for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
+	{
+		ZONE_CONTAINER* zone = this->GetArea( ii );
+
+		zone->Rotate( GetPosition(), angleChange );		
+	}
+    
     CalculateBoundingBox();
 }
 
diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h
index 3eca1a0..e811ca7 100644
--- a/pcbnew/class_module.h
+++ b/pcbnew/class_module.h
@@ -47,6 +47,9 @@
 
 #include <functional>
 
+#include <class_zone.h>
+
+
 class LINE_READER;
 class EDA_3D_CANVAS;
 class EDA_DRAW_PANEL;
@@ -101,6 +104,8 @@ class MODULE_3D_SETTINGS
         wxString m_Filename;    ///< The 3D shape filename in 3D library
 };
 
+DECL_VEC_FOR_SWIG(ZONE_CONTAINERS, ZONE_CONTAINER*)
+
 class MODULE : public BOARD_ITEM_CONTAINER
 {
 public:
@@ -682,13 +687,53 @@ public:
      */
     bool BuildPolyCourtyard();
 
+	void DeleteZONEOutlines();
+
     virtual void SwapData( BOARD_ITEM* aImage ) override;
 
+    ZONE_CONTAINERS& Zones() { return m_ZoneDescriptorList; }
+    
+    ZONE_CONTAINER* GetArea( int index ) const
+    {
+        if( (unsigned) index < m_ZoneDescriptorList.size() )
+            return m_ZoneDescriptorList[index];
+
+        return NULL;
+    }
+
+    /**
+     * Function GetAreaIndex
+     * returns the Area Index  for the given Zone Container.
+     * @param  aArea :The ZONE_CONTAINER to find.
+     * @return an Area Index in m_ZoneDescriptorList or -1 if non found.
+     */
+    int GetAreaIndex( const ZONE_CONTAINER* aArea ) const
+    {
+        for( int ii = 0; ii < GetAreaCount(); ii++ )    // Search for aArea in list
+        {
+            if( aArea == GetArea( ii ) )                // Found !
+                return ii;
+        }
+
+        return -1;
+    }
+
+    /**
+     * Function GetAreaCount
+     * @return int - The number of Areas or ZONE_CONTAINER.
+     */
+    int GetAreaCount() const
+    {
+        return (int) m_ZoneDescriptorList.size();
+    }
+
 #if defined(DEBUG)
     virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
 #endif
 
 private:
+    ZONE_CONTAINERS         m_ZoneDescriptorList;
+
     DLIST<D_PAD> m_Pads;                ///< Linked list of pads.
     DLIST<BOARD_ITEM> m_Drawings;       ///< Linked list of graphical items.
     std::list<MODULE_3D_SETTINGS> m_3D_Drawings;  ///< Linked list of 3D models.
diff --git a/pcbnew/collectors.cpp b/pcbnew/collectors.cpp
index 8b3e7d3..1d19da1 100644
--- a/pcbnew/collectors.cpp
+++ b/pcbnew/collectors.cpp
@@ -115,6 +115,7 @@ const KICAD_T GENERAL_COLLECTOR::ModulesAndTheirItems[] = {
     PCB_MODULE_EDGE_T,
     PCB_PAD_T,
     PCB_MODULE_T,
+    PCB_ZONE_AREA_T,
     EOT
 };
 
@@ -123,6 +124,7 @@ const KICAD_T GENERAL_COLLECTOR::ModuleItems[] = {
     PCB_MODULE_TEXT_T,
     PCB_MODULE_EDGE_T,
     PCB_PAD_T,
+    PCB_ZONE_AREA_T,
     EOT
 };
 
diff --git a/pcbnew/controle.cpp b/pcbnew/controle.cpp
index 8ae024a..9e5e617 100644
--- a/pcbnew/controle.cpp
+++ b/pcbnew/controle.cpp
@@ -143,6 +143,7 @@ BOARD_ITEM* PCB_BASE_FRAME::PcbGeneralLocateAndDisplay( int aHotKeyCode )
 
         case ID_PCB_ZONES_BUTT:
         case ID_PCB_KEEPOUT_AREA_BUTT:
+        case ID_MODEDIT_KEEPOUT_AREA_TOOL:
             scanList = GENERAL_COLLECTOR::Zones;
             break;
 
diff --git a/pcbnew/drc.cpp b/pcbnew/drc.cpp
index f1bb551..4c7ac7f 100644
--- a/pcbnew/drc.cpp
+++ b/pcbnew/drc.cpp
@@ -186,9 +186,9 @@ int DRC::TestZoneToZoneOutline( ZONE_CONTAINER* aZone, bool aCreateMarkers )
     int nerrors = 0;
 
     // iterate through all areas
-    for( int ia = 0; ia < board->GetAreaCount(); ia++ )
+    for( int ia = 0; ia < board->GetAreaCountIncludingModules(); ia++ )
     {
-        ZONE_CONTAINER* zoneRef = board->GetArea( ia );
+		ZONE_CONTAINER* zoneRef = board->GetAreaIncludingModules( ia );
         SHAPE_POLY_SET refSmoothedPoly;
 
         zoneRef->BuildSmoothedPoly( refSmoothedPoly );
@@ -200,9 +200,9 @@ int DRC::TestZoneToZoneOutline( ZONE_CONTAINER* aZone, bool aCreateMarkers )
         if( aZone && ( aZone != zoneRef) )
             continue;
 
-        for( int ia2 = 0; ia2 < board->GetAreaCount(); ia2++ )
+        for( int ia2 = 0; ia2 < board->GetAreaCountIncludingModules(); ia2++ )
         {
-            ZONE_CONTAINER* zoneToTest = board->GetArea( ia2 );
+            ZONE_CONTAINER* zoneToTest = board->GetAreaIncludingModules( ia2 );
             SHAPE_POLY_SET testSmoothedPoly;
 
             zoneToTest->BuildSmoothedPoly( testSmoothedPoly );
@@ -758,9 +758,9 @@ void DRC::testZones()
     // In recent Pcbnew versions, the netcode is always >= 0, but an internal net name
     // is stored, and initialized from the file or the zone properties editor.
     // if it differs from the net name from net code, there is a DRC issue
-    for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
+    for( int ii = 0; ii < m_pcb->GetAreaCountIncludingModules(); ii++ )
     {
-        ZONE_CONTAINER* test_area = m_pcb->GetArea( ii );
+		ZONE_CONTAINER* test_area = m_pcb->GetAreaIncludingModules( ii );
 
         if( !test_area->IsOnCopperLayer() )
             continue;
@@ -788,10 +788,10 @@ void DRC::testZones()
 
 void DRC::testKeepoutAreas()
 {
-    // Test keepout areas for vias, tracks and pads inside keepout areas
-    for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
+    // Test keepout areas for vias, tracks and pads inside keepout areas, including modules'
+    for( int ii = 0; ii < m_pcb->GetAreaCountIncludingModules(); ii++ )
     {
-        ZONE_CONTAINER* area = m_pcb->GetArea( ii );
+		ZONE_CONTAINER* area = m_pcb->GetAreaIncludingModules( ii );
 
         if( !area->GetIsKeepout() )
         {
@@ -966,10 +966,10 @@ void DRC::testTexts()
 
 bool DRC::doTrackKeepoutDrc( TRACK* aRefSeg )
 {
-    // Test keepout areas for vias, tracks and pads inside keepout areas
-    for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
+    // Test keepout areas for vias, tracks and pads inside keepout areas, including modules'
+    for( int ii = 0; ii < m_pcb->GetAreaCountIncludingModules(); ii++ )
     {
-        ZONE_CONTAINER* area = m_pcb->GetArea( ii );
+		ZONE_CONTAINER* area = m_pcb->GetAreaIncludingModules( ii );
 
         if( !area->GetIsKeepout() )
             continue;
diff --git a/pcbnew/footprint_editor_onclick.cpp b/pcbnew/footprint_editor_onclick.cpp
index 0277cee..d698c6a 100644
--- a/pcbnew/footprint_editor_onclick.cpp
+++ b/pcbnew/footprint_editor_onclick.cpp
@@ -44,6 +44,12 @@
 #include <dialog_edit_module_for_Modedit.h>
 #include <menus_helpers.h>
 
+#include <zones_functions_for_undo_redo.h>
+#include <board_commit.h>
+#include <zone_filler.h>
+
+static PICKED_ITEMS_LIST s_PickedList;              // a picked list to save zones for undo/redo command
+static PICKED_ITEMS_LIST s_AuxiliaryList;           // a picked list to store zones that are deleted or added when combined
 
 void FOOTPRINT_EDIT_FRAME::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
 {
@@ -519,7 +525,6 @@ void FOOTPRINT_EDIT_FRAME::OnLeftDClick( wxDC* DC, const wxPoint& MousePos )
     }
 }
 
-
 void FOOTPRINT_EDIT_FRAME::OnEditItemRequest( wxDC* aDC, BOARD_ITEM* aItem )
 {
     switch( aItem->Type() )
@@ -550,6 +555,90 @@ void FOOTPRINT_EDIT_FRAME::OnEditItemRequest( wxDC* aDC, BOARD_ITEM* aItem )
         m_canvas->Refresh();
         break;
 
+	case PCB_ZONE_AREA_T:
+		{
+			ZONE_EDIT_T     edited;
+			ZONE_SETTINGS   zoneInfo = GetZoneSettings();
+
+			BOARD_COMMIT commit( this );
+			m_canvas->SetIgnoreMouseEvents( true );
+
+			ZONE_CONTAINER* aZone = static_cast<ZONE_CONTAINER*> ( aItem );
+			wxDC* DC = aDC;
+			
+			MODULE* parentModule = static_cast<MODULE*> ( aZone->GetParent() );
+			
+			if( !parentModule ) {
+				return;
+			}
+			
+			// Save initial zones configuration, for undo/redo, before adding new zone
+			// note the net name and the layer can be changed, so we must save all zones
+			s_AuxiliaryList.ClearListAndDeleteItems();
+			s_PickedList.ClearListAndDeleteItems();
+			SaveCopyOfZones( s_PickedList, parentModule, -1, UNDEFINED_LAYER );
+
+			if( aZone->GetIsKeepout() )
+			{
+				// edit a keepout area on a copper layer
+				zoneInfo << *aZone;
+				edited = InvokeKeepoutAreaEditor( this, &zoneInfo );
+			}
+			else if( IsCopperLayer( aZone->GetLayer() ) )
+			{
+				// edit a zone on a copper layer
+
+				zoneInfo << *aZone;
+
+				edited = InvokeCopperZonesEditor( this, &zoneInfo );
+			}
+			else
+			{
+				edited = InvokeNonCopperZonesEditor( this, aZone, &zoneInfo );
+			}
+
+			m_canvas->MoveCursorToCrossHair();
+			m_canvas->SetIgnoreMouseEvents( false );
+
+			if( edited == ZONE_ABORT )
+			{
+				s_AuxiliaryList.ClearListAndDeleteItems();
+				s_PickedList.ClearListAndDeleteItems();
+				return;
+			}
+
+			if( edited == ZONE_EXPORT_VALUES )
+			{
+				UpdateCopyOfZonesList( s_PickedList, s_AuxiliaryList, parentModule );
+				commit.Stage( s_PickedList );
+				commit.Push( _( "Modify zone properties" ) );
+				s_PickedList.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items
+				return;
+			}
+
+			wxBusyCursor dummy;
+
+			// Undraw old zone outlines
+			for( int ii = 0; ii < parentModule->GetAreaCount(); ii++ )
+			{
+				ZONE_CONTAINER* edge_zone = parentModule->GetArea( ii );
+				edge_zone->Draw( m_canvas, DC, GR_XOR );
+
+				if( IsGalCanvasActive() )
+				{
+					GetGalCanvas()->GetView()->Update( edge_zone );
+				}
+			}
+
+			zoneInfo.ExportSetting( *aZone );
+
+			commit.Stage( s_PickedList );
+			commit.Push( _( "Modify zone properties" ) );
+
+			s_PickedList.ClearItemsList();  // s_ItemsListPicker is no longer owner of picked items
+		}
+        break;
+
     default:
         break;
     }
diff --git a/pcbnew/footprint_editor_utils.cpp b/pcbnew/footprint_editor_utils.cpp
index b49ee80..04a6eb8 100644
--- a/pcbnew/footprint_editor_utils.cpp
+++ b/pcbnew/footprint_editor_utils.cpp
@@ -959,6 +959,10 @@ void FOOTPRINT_EDIT_FRAME::OnVerticalToolbar( wxCommandEvent& aEvent )
         SetToolID( id, wxCURSOR_PENCIL, _( "Set grid origin" ) );
         break;
 
+    case ID_MODEDIT_KEEPOUT_AREA_TOOL:
+        SetToolID( id, wxCURSOR_PENCIL, _( "Add keepout" ) );
+        break;
+
     case ID_MODEDIT_PAD_TOOL:
         if( GetBoard()->m_Modules )
         {
diff --git a/pcbnew/kicad_clipboard.cpp b/pcbnew/kicad_clipboard.cpp
index a5680c4..05bc033 100644
--- a/pcbnew/kicad_clipboard.cpp
+++ b/pcbnew/kicad_clipboard.cpp
@@ -78,10 +78,13 @@ void CLIPBOARD_IO::SaveSelection( const SELECTION& aSelected )
     bool onlyModuleParts = true;
     for( const auto i : aSelected )
     {
-        // check if it not one of the module primitives
+        // check if it not one of the module primitives               
         if( ( i->Type() != PCB_MODULE_EDGE_T ) &&
                 ( i->Type() != PCB_MODULE_TEXT_T ) &&
-                ( i->Type() != PCB_PAD_T ) )
+                ( i->Type() != PCB_PAD_T ) &&
+                !( (i->Type() == PCB_ZONE_AREA_T ) && 
+					(i->GetParent()) && 
+					(i->GetParent()->Type() == PCB_MODULE_T) ) )
         {
             onlyModuleParts = false;
             continue;
diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp
index d2c0da2..2311891 100644
--- a/pcbnew/kicad_plugin.cpp
+++ b/pcbnew/kicad_plugin.cpp
@@ -1171,7 +1171,14 @@ void PCB_IO::format( MODULE* aModule, int aNestLevel ) const
         }
         ++bs3D;
     }
-
+    
+    // save zones
+	for( int ii = 0; ii < aModule->GetAreaCount(); ii++ )
+	{
+		ZONE_CONTAINER* zone = aModule->GetArea( ii );
+		format( zone, aNestLevel+1 );
+	};
+		
     m_out->Print( aNestLevel, ")\n" );
 }
 
@@ -1193,6 +1200,11 @@ void PCB_IO::formatLayers( LSET aLayerMask, int aNestLevel ) const
     static const LSET mask(  2, B_Mask,     F_Mask );
     static const LSET crt_yd(2, B_CrtYd,    F_CrtYd );
     static const LSET fab(   2, B_Fab,      F_Fab );
+    static const LSET inner(   30,
+		In1_Cu, In2_Cu, In3_Cu, In4_Cu, In5_Cu, In6_Cu, In7_Cu, In8_Cu, In9_Cu, In10_Cu,
+		In11_Cu, In12_Cu, In13_Cu, In14_Cu, In15_Cu, In16_Cu, In17_Cu, In18_Cu, In19_Cu, In20_Cu,
+		In21_Cu, In22_Cu, In23_Cu, In24_Cu, In25_Cu, In26_Cu, In27_Cu, In28_Cu, In29_Cu, In30_Cu
+	);
 
     LSET cu_mask = cu_all;
 
@@ -1248,6 +1260,13 @@ void PCB_IO::formatLayers( LSET aLayerMask, int aNestLevel ) const
         aLayerMask &= ~fab;
     }
 
+    if( ( aLayerMask & inner ) == inner )
+    {
+        output += " In*.Cu";
+        aLayerMask &= ~inner;
+    }
+
+
     // output any individual layers not handled in wildcard combos above
 
     if( m_board )
diff --git a/pcbnew/menubar_footprint_editor.cpp b/pcbnew/menubar_footprint_editor.cpp
index a3bf894..6db3211 100644
--- a/pcbnew/menubar_footprint_editor.cpp
+++ b/pcbnew/menubar_footprint_editor.cpp
@@ -315,6 +315,11 @@ void FOOTPRINT_EDIT_FRAME::ReCreateMenuBar()
                  _( "Place footprint reference anchor" ),
                  KiBitmap( anchor_xpm ) );
 
+    placeMenu->AppendSeparator();
+
+    AddMenuItem( placeMenu, ID_MODEDIT_KEEPOUT_AREA_TOOL,
+                 _( "&Keepout Area" ), _( "Add keepout areas" ), KiBitmap( add_keepout_area_xpm ) );
+
 
     //----- Preferences menu -----------------
     wxMenu* prefs_menu = new wxMenu;
diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp
index f6049dd..c062411 100644
--- a/pcbnew/pcb_parser.cpp
+++ b/pcbnew/pcb_parser.cpp
@@ -79,6 +79,11 @@ void PCB_PARSER::init()
     m_layerMasks[ "*.SilkS" ]   = LSET( 2, B_SilkS, F_SilkS );
     m_layerMasks[ "*.Fab" ]     = LSET( 2, B_Fab,   F_Fab );
     m_layerMasks[ "*.CrtYd" ]   = LSET( 2, B_CrtYd, F_CrtYd );
+    m_layerMasks[ "In*.Cu" ]   = LSET( 30,
+		In1_Cu, In2_Cu, In3_Cu, In4_Cu, In5_Cu, In6_Cu, In7_Cu, In8_Cu, In9_Cu, In10_Cu,
+		In11_Cu, In12_Cu, In13_Cu, In14_Cu, In15_Cu, In16_Cu, In17_Cu, In18_Cu, In19_Cu, In20_Cu,
+		In21_Cu, In22_Cu, In23_Cu, In24_Cu, In25_Cu, In26_Cu, In27_Cu, In28_Cu, In29_Cu, In30_Cu
+	);
 
     // This is for the first pretty & *.kicad_pcb formats, which had
     // Inner1_Cu - Inner14_Cu with the numbering sequence
@@ -2009,6 +2014,10 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
             module->Add3DModel( parse3DModel() );
             break;
 
+        case T_zone:
+			module->Add( parseZONE_CONTAINER(), ADD_APPEND );
+            break;
+
         default:
             Expecting( "locked, placed, tedit, tstamp, at, descr, tags, path, "
                        "autoplace_cost90, autoplace_cost180, solder_mask_margin, "
@@ -2834,7 +2843,19 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER()
     // bigger scope since each filled_polygon is concatenated in here
     SHAPE_POLY_SET pts;
 
-    std::unique_ptr< ZONE_CONTAINER > zone( new ZONE_CONTAINER( m_board ) );
+	std::unique_ptr< ZONE_CONTAINER > zone;
+	if(m_board != nullptr)
+	{
+		zone = std::unique_ptr< ZONE_CONTAINER > ( new ZONE_CONTAINER( m_board ) );
+	}else {
+		std::unique_ptr<BOARD> aBoard( new BOARD( ) );
+		//zone = std::unique_ptr< ZONE_CONTAINER > ( new ZONE_CONTAINER( nullptr ) );
+		//aBoard.get()->GetZoneSettings().ExportSetting( *(zone.get()) );
+		//aBoard->GetZoneSettings().ExportSetting( *zone );
+		
+		zone = std::unique_ptr< ZONE_CONTAINER > ( new ZONE_CONTAINER( aBoard.get() ) );
+		zone->SetParent( nullptr );
+	}
 
     zone->SetPriority( 0 );
 
diff --git a/pcbnew/pcbnew_id.h b/pcbnew/pcbnew_id.h
index 02d35e4..04924ed 100644
--- a/pcbnew/pcbnew_id.h
+++ b/pcbnew/pcbnew_id.h
@@ -340,6 +340,7 @@ enum pcbnew_ids
 
     // Module editor right vertical tool bar commands.
     ID_MODEDIT_PAD_TOOL,
+    ID_MODEDIT_KEEPOUT_AREA_TOOL,
     ID_MODEDIT_LINE_TOOL,
     ID_MODEDIT_CIRCLE_TOOL,
     ID_MODEDIT_ARC_TOOL,
diff --git a/pcbnew/tool_footprint_editor.cpp b/pcbnew/tool_footprint_editor.cpp
index 62c6b54..a77ec34 100644
--- a/pcbnew/tool_footprint_editor.cpp
+++ b/pcbnew/tool_footprint_editor.cpp
@@ -164,6 +164,10 @@ void FOOTPRINT_EDIT_FRAME::ReCreateVToolbar()
     m_drawToolBar->AddTool( ID_MODEDIT_PAD_TOOL, wxEmptyString, KiScaledBitmap( pad_xpm, this ),
                             _( "Add pad" ), wxITEM_CHECK );
 
+    m_drawToolBar->AddTool( ID_MODEDIT_KEEPOUT_AREA_TOOL, wxEmptyString,
+                            KiScaledBitmap( add_keepout_area_xpm, this ),
+                            _( "Add keepout areas" ), wxITEM_CHECK );
+
     KiScaledSeparator( m_drawToolBar, this );
     m_drawToolBar->AddTool( ID_MODEDIT_LINE_TOOL, wxEmptyString, KiScaledBitmap( add_graphical_segments_xpm, this ),
                             _( "Add graphic line" ), wxITEM_CHECK );
diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp
index 6fc8914..791ec90 100644
--- a/pcbnew/tools/drawing_tool.cpp
+++ b/pcbnew/tools/drawing_tool.cpp
@@ -643,7 +643,13 @@ int DRAWING_TOOL::DrawZoneKeepout( const TOOL_EVENT& aEvent )
 {
     SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::KEEPOUT );
 
-    m_frame->SetToolID( ID_PCB_KEEPOUT_AREA_BUTT, wxCURSOR_PENCIL, _( "Add keepout" ) );
+	if( m_editModules )
+	{
+		m_frame->SetToolID( ID_MODEDIT_KEEPOUT_AREA_TOOL, wxCURSOR_PENCIL, _( "Add keepout" ) );
+	} else
+	{
+		m_frame->SetToolID( ID_PCB_KEEPOUT_AREA_BUTT, wxCURSOR_PENCIL, _( "Add keepout" ) );
+	}
 
     return drawZone( true, ZONE_MODE::ADD );
 }
diff --git a/pcbnew/tools/pcb_actions.cpp b/pcbnew/tools/pcb_actions.cpp
index bc10bc2..2a5ba40 100644
--- a/pcbnew/tools/pcb_actions.cpp
+++ b/pcbnew/tools/pcb_actions.cpp
@@ -61,6 +61,7 @@ OPT<TOOL_EVENT> PCB_ACTIONS::TranslateLegacyId( int aId )
     case ID_PCB_DRAW_VIA_BUTT:
         return PCB_ACTIONS::drawVia.MakeEvent();
 
+    case ID_MODEDIT_KEEPOUT_AREA_TOOL:
     case ID_PCB_KEEPOUT_AREA_BUTT:
         return PCB_ACTIONS::drawZoneKeepout.MakeEvent();
 
diff --git a/pcbnew/tools/pcbnew_control.cpp b/pcbnew/tools/pcbnew_control.cpp
index b8bc07e..225ebea 100644
--- a/pcbnew/tools/pcbnew_control.cpp
+++ b/pcbnew/tools/pcbnew_control.cpp
@@ -795,6 +795,11 @@ int PCBNEW_CONTROL::PasteItemsFromClipboard( const TOOL_EVENT& aEvent )
                     item->SetParent ( board()->m_Modules.GetFirst() );
                     items.push_back( item );
                 }
+                for( auto zone : mod->Zones() )
+				{
+					zone->SetParent ( board()->m_Modules.GetFirst() );
+					items.push_back( zone );
+				}
             }
             else
             {
diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp
index f651785..1ae8ac0 100644
--- a/pcbnew/tools/selection_tool.cpp
+++ b/pcbnew/tools/selection_tool.cpp
@@ -1524,6 +1524,17 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const
         {
             auto* zone = static_cast<const ZONE_CONTAINER*>( aItem );
 
+			//check if zone has a parent of type module
+			if( zone && zone->GetParent() && (zone->GetParent()->Type() == PCB_MODULE_T) )
+			{
+				// only if not editing module
+				if(m_frame->IsType(FRAME_PCB_MODULE_EDITOR) == false)
+				{
+					return false;
+				}	
+				
+			}
+			
             if( zone && zone->GetIsKeepout() )
             {
                 auto zoneLayers = zone->GetLayerSet().Seq();
diff --git a/pcbnew/tools/zone_create_helper.cpp b/pcbnew/tools/zone_create_helper.cpp
index 1e14a91..315f7cc 100644
--- a/pcbnew/tools/zone_create_helper.cpp
+++ b/pcbnew/tools/zone_create_helper.cpp
@@ -92,6 +92,15 @@ std::unique_ptr<ZONE_CONTAINER> ZONE_CREATE_HELPER::createNewZone( bool aKeepout
 
     // Apply the selected settings
     zoneInfo.ExportSetting( *newZone );
+    
+    if(frame.IsType(FRAME_PCB_MODULE_EDITOR)) {
+		for( auto module : board.Modules() )
+		{
+			newZone->SetParent(module);
+			break;
+		}
+		
+	}
 
     return newZone;
 }
diff --git a/pcbnew/zone_filler.cpp b/pcbnew/zone_filler.cpp
index 0bd9e34..bcb42f9 100644
--- a/pcbnew/zone_filler.cpp
+++ b/pcbnew/zone_filler.cpp
@@ -528,10 +528,9 @@ void ZONE_FILLER::buildZoneFeatureHoleList( const ZONE_CONTAINER* aZone,
         }
     }
 
-    // Add zones outlines having an higher priority and keepout
-    for( int ii = 0; ii < m_board->GetAreaCount(); ii++ )
+    for( int ii = 0; ii < m_board->GetAreaCountIncludingModules(); ii++ )
     {
-        ZONE_CONTAINER* zone = m_board->GetArea( ii );
+        ZONE_CONTAINER* zone = m_board->GetAreaIncludingModules( ii );
 
         // If the zones share no common layers
         if( !aZone->CommonLayerExists( zone->GetLayerSet() ) )
diff --git a/pcbnew/zones_functions_for_undo_redo.cpp b/pcbnew/zones_functions_for_undo_redo.cpp
index 97b02cb..9322f96 100644
--- a/pcbnew/zones_functions_for_undo_redo.cpp
+++ b/pcbnew/zones_functions_for_undo_redo.cpp
@@ -162,6 +162,33 @@ int SaveCopyOfZones( PICKED_ITEMS_LIST& aPickList, BOARD* aPcb, int aNetCode, LA
     return copyCount;
 }
 
+/**
+ * Function SaveCopyOfZones
+ * creates a copy of zones in a module having a given netcode on a given layer,
+ * and fill a pick list with pickers to handle these copies
+ * the UndoRedo status is set to UR_CHANGED for all items in list
+ * Later, UpdateCopyOfZonesList will change and update these pickers after a zone edition
+ * @param aPickList = the pick list
+ * @param aModule = the Module
+ * @param aNetCode = the reference netcode. if aNetCode < 0 all netcodes are used
+ * @param aLayer = the layer of zones. if aLayer < 0, all layers are used
+ * @return the count of saved copies
+ */
+int SaveCopyOfZones( PICKED_ITEMS_LIST& aPickList, MODULE* aModule, int aNetCode, LAYER_NUM aLayer )
+{
+    int copyCount = 0;
+
+	MODULE* moduleDup = new MODULE( *aModule );
+	moduleDup->SetParent ( aModule->GetParent () );
+	ITEM_PICKER picker( aModule, UR_CHANGED );
+	picker.SetLink( moduleDup );
+	aPickList.PushItem( picker );
+	copyCount++;	
+
+    return copyCount;
+}
+
+
 
 /**
  * Function UpdateCopyOfZonesList
@@ -307,3 +334,149 @@ void UpdateCopyOfZonesList( PICKED_ITEMS_LIST& aPickList,
     wxASSERT_MSG( aAuxiliaryList.GetCount() == 0,
                   wxT( "UpdateCopyOfZonesList() error: aAuxiliaryList not empty." ) );
 }
+
+/**
+ * Function UpdateCopyOfZonesList
+ * check a pick list to remove zones identical to their copies in a module
+ * and set the type of operation in picker (UR_DELETED, UR_CHANGED)
+ * if an item is deleted, the initial values are retrievered,
+ * because they can have changed in edition
+ * @param aPickList = the main pick list
+ * @param aAuxiliaryList = the list of deleted or added (new created) items after calculations
+ * @param aModule = the Module
+ *
+ * aAuxiliaryList is a list of pickers updated by zone algorithms:
+ *  This list contains zones which were added or deleted during the zones combine process
+ * aPickList :is a list of zones that can be modified (changed or deleted, or not modified)
+ *  Typically, this is the list of existing zones on the layer of the edited zone,
+ *  before any change.
+ *  >> if the picked zone is not changed, it is removed from list
+ *  >> if the picked zone was deleted (i.e. not found in board list), the picker is modified:
+ *          its status becomes UR_DELETED
+ *          the aAuxiliaryList corresponding picker is removed (if not found : set an error)
+ *  >> if the picked zone was flagged as UR_NEW, and was after deleted ,
+ *  perhaps combined with an other zone  (i.e. not found in board list):
+ *          the picker is removed
+ *          the zone itself if really deleted
+ *          the aAuxiliaryList corresponding picker is removed (if not found : set an error)
+ * After aPickList is cleaned, the aAuxiliaryList is read
+ *  All pickers flagged UR_NEW are moved to aPickList
+ * (the corresponding zones are zone that were created by the zone normalize and combine process,
+ * mainly when adding cutout areas, or creating self intersecting contours)
+ *  All pickers flagged UR_DELETED are removed, and the coresponding zones actually deleted
+ * (the corresponding zones are new zone that were created by the zone normalize process,
+ * when creating self intersecting contours, and after combined with an existing zone.
+ * At the end of the update process the aAuxiliaryList must be void,
+ *  because all pickers created by the combine process
+ *  must have been removed (removed for new and deleted zones, or moved in aPickList.)
+ * If not an error is set.
+ */
+void UpdateCopyOfZonesList( PICKED_ITEMS_LIST& aPickList,
+                            PICKED_ITEMS_LIST& aAuxiliaryList,
+                            MODULE*             aModule )
+{
+    for( unsigned kk = 0; kk < aPickList.GetCount(); kk++ )
+    {
+        UNDO_REDO_T  status = aPickList.GetPickedItemStatus( kk );
+
+        ZONE_CONTAINER* ref = (ZONE_CONTAINER*) aPickList.GetPickedItem( kk );
+
+        for( unsigned ii = 0; ; ii++ )  // analyse the main picked list
+        {
+            ZONE_CONTAINER* zone = aModule->GetArea( ii );
+
+            if( zone == NULL )
+            {
+                /* End of list: the stored item is not found:
+                 * it must be in aDeletedList:
+                 * search it and restore initial values
+                 * or
+                 * if flagged UR_NEW: remove it definitively
+                 */
+                if( status == UR_NEW )
+                {
+                    delete ref;
+                    ref = NULL;
+                    aPickList.RemovePicker( kk );
+                    kk--;
+                }
+                else
+                {
+                    ZONE_CONTAINER* zcopy = (ZONE_CONTAINER*) aPickList.GetPickedItemLink( kk );
+                    aPickList.SetPickedItemStatus( UR_DELETED, kk );
+
+                    wxASSERT_MSG( zcopy != NULL,
+                                  wxT( "UpdateCopyOfZonesList() error: link = NULL" ) );
+
+                    *ref = *zcopy;
+
+                    // the copy was deleted; the link does not exists now.
+                    aPickList.SetPickedItemLink( NULL, kk );
+                    delete zcopy;
+                }
+
+                // Remove this item from aAuxiliaryList, mainly for tests purpose
+                bool notfound = true;
+
+                for( unsigned nn = 0; nn < aAuxiliaryList.GetCount(); nn++ )
+                {
+                    if( ref != NULL && aAuxiliaryList.GetPickedItem( nn ) == ref )
+                    {
+                        aAuxiliaryList.RemovePicker( nn );
+                        notfound = false;
+                        break;
+                    }
+                }
+
+                if( notfound )  // happens when the new zone overlaps an existing zone
+                                // and these zones are combined
+                {
+                    DBG( printf(
+                        "UpdateCopyOfZonesList(): item not found in aAuxiliaryList,"
+                        "combined with an other zone\n" ) );
+                }
+                break;
+            }
+
+            if( zone == ref )      // picked zone found
+            {
+                if( aPickList.GetPickedItemStatus( kk ) != UR_NEW )
+                {
+                    ZONE_CONTAINER* zcopy = (ZONE_CONTAINER*) aPickList.GetPickedItemLink( kk );
+
+                    if( zone->IsSame( *zcopy ) )    // Remove picked, because no changes
+                    {
+                        delete zcopy;               // Delete copy
+                        aPickList.RemovePicker( kk );
+                        kk--;
+                    }
+                }
+
+                break;
+            }
+        }
+    }
+
+    // Add new zones in main pick list, and remove pickers from Auxiliary List
+    for( unsigned ii = 0; ii < aAuxiliaryList.GetCount(); )
+    {
+        if( aAuxiliaryList.GetPickedItemStatus( ii ) == UR_NEW )
+        {
+            ITEM_PICKER picker = aAuxiliaryList.GetItemWrapper( ii );
+            aPickList.PushItem( picker );
+            aAuxiliaryList.RemovePicker( ii );
+        }
+        else if( aAuxiliaryList.GetPickedItemStatus( ii ) == UR_DELETED )
+        {
+            delete aAuxiliaryList.GetPickedItemLink( ii );
+            aAuxiliaryList.RemovePicker( ii );
+        }
+        else
+            ii++;
+    }
+
+    // Should not occur:
+    wxASSERT_MSG( aAuxiliaryList.GetCount() == 0,
+                  wxT( "UpdateCopyOfZonesList() error: aAuxiliaryList not empty." ) );
+}
+
diff --git a/pcbnew/zones_functions_for_undo_redo.h b/pcbnew/zones_functions_for_undo_redo.h
index a5260a3..c420dde 100644
--- a/pcbnew/zones_functions_for_undo_redo.h
+++ b/pcbnew/zones_functions_for_undo_redo.h
@@ -58,6 +58,17 @@
  */
 int SaveCopyOfZones(PICKED_ITEMS_LIST & aPickList, BOARD* aPcb, int aNetCode, LAYER_NUM aLayer );
 
+/**
+ * Function SaveCopyOfZones
+ * creates a copy of zones in a module having a given netcode on a given layer,
+ * and fill a pick list with pickers to handle these copies
+ * @param aPickList = the pick list
+ * @param aModule = the Module
+ * @param aNetCode = the reference netcode. if aNetCode < 0 all netcodes are used
+ * @param aLayer = the layer of zones. if aLayer < 0, all layers are used
+ * @return the count of saved copies
+ */
+int SaveCopyOfZones( PICKED_ITEMS_LIST& aPickList, MODULE* aModule, int aNetCode, LAYER_NUM aLayer );
 
 /**
  * Function UpdateCopyOfZonesList
@@ -69,4 +80,17 @@ int SaveCopyOfZones(PICKED_ITEMS_LIST & aPickList, BOARD* aPcb, int aNetCode, LA
  */
 void UpdateCopyOfZonesList( PICKED_ITEMS_LIST& aPickList, PICKED_ITEMS_LIST& aAuxiliaryList, BOARD* aPcb );
 
+
+/**
+ * Function UpdateCopyOfZonesList
+ * check a pick list to remove zones identical to their copies in a module
+ * and set the type of operation in picker (UR_DELETED, UR_CHANGED)
+ * @param aPickList = the main pick list
+ * @param aAuxiliaryList = the list of deleted or added (new created) items after calculations
+ * @param aModule = the Module
+ */
+void UpdateCopyOfZonesList( PICKED_ITEMS_LIST& aPickList,
+                            PICKED_ITEMS_LIST& aAuxiliaryList,
+                            MODULE*             aModule );
+
 #endif      // ZONES_FUNCTIONS_TO_UNDO_REDO_H

--------------2.7.4--



Follow ups

References