kicad-developers team mailing list archive
-
kicad-developers team
-
Mailing list archive
-
Message #27367
Re: Current state of ActionPlugin
Dear All,
As requested please find attached a patch to create 2 samples for the
action menu:
- add_automatic_border.py
Automaticaly found smaller area including all modules/coper area/text...
and build or update rectangular PCB edge
- text_by_date.py
Change any text with content "$date$" on the PCB to "$date$" + current date.
=> This example was the first I propose. It is also the one I put inside
the documentation.
Regards,
Le 23/01/2017 à 14:30, jp charras a écrit :
> Le 23/01/2017 à 14:19, Nick Østergaard a écrit :
>> Should it be enabled in the windows nightlies now or should we wait a bit?
>>
>
> Before enabling it, please wait for a few tests from devs and J-S.
> Perhaps also a bit of doc and 2 or 3 samples which do not delete anything (could be in demos) is
> welcome.
> This is in the J-S Reynaud's hands.
>
>
>> 2017-01-23 14:13 GMT+01:00 jp charras <jp.charras@xxxxxxxxxx>:
>>> Le 18/01/2017 à 18:00, Jean-Samuel Reynaud a écrit :
>>>> Just to know if this patch is now acceptable ? Did you plan to commit it ?
>>>>
>>>> Thanks,
>>>> Le 17/01/2017 à 19:46, Jean-Samuel Reynaud a écrit :
>>>>>> yes i was trying to subtly imply that :)
>>>>> ok, find attached the patch with the about box updated ;)
>>>>>
>>>>> Regards,
>>>>>
>>>
>>> I committed the patch ( with fixes, see comments) in rev:
>>> 2b5769c0a8568e421c2152177a8f1c27d9bf9cb5
>>>
>>> Jean-Samuel, thanks, and please carefully test this rev, to be sure I did not break anything.
>>>
>>> The action plugin feature must be currently seen as an experimental feature, for developers, because
>>> it can easily break a board.
>>> It is enabled if the option -DKICAD_SCRIPTING_ACTION_MENU=ON is added to the cmake command line.
>>>
>>> I am thinking this feature need to be tested, and enhancements added (especially if a script deletes
>>> a board item), and this is the reason I see it as currently experimental.
>>>
>>> However, now it exists, it can be tested.
>>>
>>>
>>> --
>>> Jean-Pierre CHARRAS
>>>
>>> _______________________________________________
>>> Mailing list: https://launchpad.net/~kicad-developers
>>> Post to : kicad-developers@xxxxxxxxxxxxxxxxxxx
>>> Unsubscribe : https://launchpad.net/~kicad-developers
>>> More help : https://help.launchpad.net/ListHelp
>>
>
>
From bcdd8c17da55b3d3c07252f1a370e7dd3890e96d Mon Sep 17 00:00:00 2001
From: Jean-Samuel Reynaud <js.reynaud@xxxxxxxxx>
Date: Fri, 27 Jan 2017 11:06:28 +0100
Subject: [PATCH] Add ActionPlugin example
---
.../add_automatic_border.py | 247 +++++++++++++++++++++
demos/python_scripts_examples/text_by_date.py | 59 +++++
2 files changed, 306 insertions(+)
create mode 100644 demos/python_scripts_examples/add_automatic_border.py
create mode 100644 demos/python_scripts_examples/text_by_date.py
diff --git a/demos/python_scripts_examples/add_automatic_border.py b/demos/python_scripts_examples/add_automatic_border.py
new file mode 100644
index 0000000..ad71c8f
--- /dev/null
+++ b/demos/python_scripts_examples/add_automatic_border.py
@@ -0,0 +1,247 @@
+# add_automatic_border.py
+#
+# Copyright (C) 2017 KiCad Developers, see CHANGELOG.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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+#
+
+from pcbnew import *
+import re
+import datetime
+
+
+class add_automatic_border( ActionPlugin ):
+ """
+ add_automatic_border: An other sample plugin as an example of ActionPlugin
+ Build PCB edges to include all PCB elements
+ How to use:
+ - add all your modules/track/area/text...
+ - Call the plugin
+ - An including PCB edge will be created automaticaly
+ """
+
+ def defaults( self ):
+ """
+ Method defaults must be redefined
+ self.name should be the menu label to use
+ self.category should be the category (not yet used)
+ self.description should be a comprehensive description
+ of the plugin
+ """
+ self.name = "Add or update automatic PCB edges"
+ self.category = "Modify PCB"
+ self.description = "Automaticaly add or update edges on an existing PCB"
+ # Offset between existing elements and edge we will add/update (fixed at 2.54mm)
+ self.offset = FromMM( 2.54 )
+ # Attach to a grid step (fixed at 2.54mm)
+ self.grid = FromMM( 2.54 )
+
+ def min( self, a, b ):
+ """
+ Method min: Found min between a and b even is one is None
+ """
+ if a is None:
+ return b
+ if b is None:
+ return a
+ if a < b:
+ return a
+ return b
+
+ def max( self, a, b ):
+ """
+ Method max: Found max between a and b even is one is None
+ """
+ if a is None:
+ return b
+ if b is None:
+ return a
+ if a > b:
+ return a
+ return b
+
+ def Run( self ):
+ """
+ Method Run is called by Action menu
+ """
+ pcb = GetBoard()
+ # Find including area on min/max x/y
+ min_x = None
+ max_x = None
+ min_y = None
+ max_y = None
+
+ # Enum all area
+ for i in range( pcb.GetAreaCount() ):
+ min_x = self.min( min_x, pcb.GetArea( i ).GetBoundingBox().GetX() )
+ min_y = self.min( min_y, pcb.GetArea( i ).GetBoundingBox().GetY() )
+ max_x = self.max( max_x, \
+ pcb.GetArea( i ).GetBoundingBox().GetX() \
+ + pcb.GetArea( i ).GetBoundingBox().GetWidth() )
+ max_y = self.max( max_y, \
+ pcb.GetArea( i ).GetBoundingBox().GetY() \
+ + pcb.GetArea( i ).GetBoundingBox().GetHeight() )
+
+ # Same with track
+ for track in pcb.GetTracks():
+ min_x = self.min( min_x, track.GetStart().x )
+ min_y = self.min( min_y, track.GetStart().y )
+ max_x = self.max( max_x, track.GetEnd().x )
+ max_y = self.max( max_y, track.GetEnd().y )
+
+ min_x = self.min( min_x, track.GetEnd().x )
+ min_y = self.min( min_y, track.GetEnd().y )
+ max_x = self.max( max_x, track.GetStart().x )
+ max_y = self.max( max_y, track.GetStart().y )
+
+ # Variable to store PCB edges we found
+ west = None
+ north = None
+ east = None
+ south = None
+
+ for draw in pcb.GetDrawings():
+ edge_candidate = False
+ # Detect if current drawing is a PCB edge
+ # and a candicate for north/south/east or west
+ if draw.GetClass() == 'DRAWSEGMENT' \
+ and draw.GetLayer() == Edge_Cuts:
+ # Try candicate for east/west ?
+ if draw.GetStart().x == draw.GetEnd().x:
+ if west is None and east is None:
+ west = draw
+ edge_candidate = True
+ elif west is None: # east is not none
+ if draw.GetStart().x < east.GetStart().x:
+ west = draw
+ edge_candidate = True
+ else:
+ west = east
+ east = draw
+ edge_candidate = True
+ elif east is None: # west is not none
+ if draw.GetStart().x > west.GetStart().x:
+ east = draw
+ edge_candidate = True
+ else:
+ east = west
+ west = draw
+ edge_candidate = True
+ else:
+ None # west and east are already found...
+
+ # Try candicate for north/south ?
+ if draw.GetStart().y == draw.GetEnd().y:
+ if north is None and south is None:
+ north = draw
+ edge_candidate = True
+ elif north is None: # south is not none
+ if draw.GetStart().y < south.GetStart().y:
+ north = draw
+ edge_candidate = True
+ else:
+ north = south
+ south = draw
+ edge_candidate = True
+ elif south is None: # north is not none
+ if draw.GetStart().y > north.GetStart().y:
+ south = draw
+ edge_candidate = True
+ else:
+ south = north
+ north = draw
+ edge_candidate = True
+ else:
+ None # north and south are already found...
+ # Not a edge candidate: use it to find including edges
+ if not edge_candidate:
+ bbox = draw.GetBoundingBox()
+ min_x = self.min( min_x, bbox.GetX() )
+ min_y = self.min( min_y, bbox.GetY() )
+ max_x = self.max( max_x, bbox.GetX() + bbox.GetWidth() )
+ max_y = self.max( max_y, bbox.GetY() + bbox.GetHeight() )
+
+ # Same with modules: Find including area
+ for module in pcb.GetModules():
+ bbox = module.GetBoundingBox()
+ min_x = self.min( min_x, bbox.GetX() )
+ min_y = self.min( min_y, bbox.GetY() )
+ max_x = self.max( max_x, bbox.GetX() + bbox.GetWidth() )
+ max_y = self.max( max_y, bbox.GetY() + bbox.GetHeight() )
+
+ # Add a space between including area and edge (3mm)
+ min_x = min_x - self.offset
+ min_y = min_y - self.offset
+ max_x = max_x + self.offset
+ max_y = max_y + self.offset
+
+ # Fix on the defined grid
+ min_x = min_x - (min_x % self.grid)
+ min_y = min_y - (min_y % self.grid)
+ if ( max_x % self.grid ) != 0:
+ max_x = max_x - (max_x % self.grid) + self.grid
+ if ( max_y % self.grid ) != 0:
+ max_y = max_y - (max_y % self.grid) + self.grid
+
+ # Add or update all edges
+ need_add = False
+ if west is None:
+ need_add = True
+ west = DRAWSEGMENT()
+ west.SetLayer( Edge_Cuts )
+
+ west.SetStart( wxPoint( min_x, min_y ) )
+ west.SetEnd( wxPoint( min_x, max_y ) )
+ if need_add:
+ pcb.Add( west )
+
+ need_add = False
+ if north is None:
+ need_add = True
+ north = DRAWSEGMENT()
+ north.SetLayer( Edge_Cuts )
+
+ north.SetStart( wxPoint( min_x, min_y ) )
+ north.SetEnd( wxPoint( max_x, min_y ) )
+ if need_add:
+ pcb.Add( north )
+
+ need_add = False
+ if east is None:
+ need_add = True
+ east = DRAWSEGMENT()
+ east.SetLayer( Edge_Cuts )
+
+ east.SetStart( wxPoint( max_x, min_y ) )
+ east.SetEnd( wxPoint( max_x, max_y ) )
+ if need_add:
+ pcb.Add( east )
+
+ need_add = False
+ if south is None:
+ need_add = True
+ south = DRAWSEGMENT()
+ south.SetLayer( Edge_Cuts )
+
+ south.SetStart( wxPoint( min_x, max_y ) )
+ south.SetEnd( wxPoint( max_x, max_y ) )
+ if need_add:
+ pcb.Add( south )
+
+
+# Register the action
+add_automatic_border().register()
diff --git a/demos/python_scripts_examples/text_by_date.py b/demos/python_scripts_examples/text_by_date.py
new file mode 100644
index 0000000..6e96530
--- /dev/null
+++ b/demos/python_scripts_examples/text_by_date.py
@@ -0,0 +1,59 @@
+# text_by_date.py
+#
+# Copyright (C) 2017 KiCad Developers, see CHANGELOG.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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+#
+
+import pcbnew
+import re
+import datetime
+
+
+class text_by_date( pcbnew.ActionPlugin ):
+ """
+ test_by_date: A sample plugin as an example of ActionPlugin
+ Add the date to any text field of the board where the content is '$date$'
+ How to use:
+ - Add a text on your board with the content '$date$'
+ - Call the plugin
+ - Automaticaly the date will be added to the text (format YYYY-MM-DD)
+ """
+
+ def defaults( self ):
+ """
+ Method defaults must be redefined
+ self.name should be the menu label to use
+ self.category should be the category (not yet used)
+ self.description should be a comprehensive description
+ of the plugin
+ """
+ self.name = "Add date on PCB"
+ self.category = "Modify PCB"
+ self.description = "Automaticaly add date on an existing PCB"
+
+ def Run( self ):
+ pcb = pcbnew.GetBoard()
+ for draw in pcb.m_Drawings:
+ if draw.GetClass() == 'PTEXT':
+ txt = re.sub( "\$date\$ [0-9]{4}-[0-9]{2}-[0-9]{2}",
+ "$date$", draw.GetText() )
+ if txt == "$date$":
+ draw.SetText( "$date$ %s"%datetime.date.today() )
+
+
+text_by_date().register()
--
2.7.4
References
-
Re: Current state of ActionPlugin
From: Wayne Stambaugh, 2017-01-04
-
Re: Current state of ActionPlugin
From: Chris Pavlina, 2017-01-10
-
Re: Current state of ActionPlugin
From: Wayne Stambaugh, 2017-01-10
-
Re: Current state of ActionPlugin
From: Jean-Samuel Reynaud, 2017-01-11
-
Re: Current state of ActionPlugin
From: jp charras, 2017-01-11
-
Re: Current state of ActionPlugin
From: Wayne Stambaugh, 2017-01-11
-
Re: Current state of ActionPlugin
From: Jean-Samuel Reynaud, 2017-01-11
-
Re: Current state of ActionPlugin
From: jp charras, 2017-01-11
-
Re: Current state of ActionPlugin
From: Jean-Samuel Reynaud, 2017-01-16
-
Re: Current state of ActionPlugin
From: Simon Wells, 2017-01-16
-
Re: Current state of ActionPlugin
From: Wayne Stambaugh, 2017-01-16
-
Re: Current state of ActionPlugin
From: Jean-Samuel Reynaud, 2017-01-17
-
Re: Current state of ActionPlugin
From: Simon Wells, 2017-01-17
-
Re: Current state of ActionPlugin
From: Jean-Samuel Reynaud, 2017-01-17
-
Re: Current state of ActionPlugin
From: Jean-Samuel Reynaud, 2017-01-18
-
Re: Current state of ActionPlugin
From: jp charras, 2017-01-23
-
Re: Current state of ActionPlugin
From: Nick Østergaard, 2017-01-23
-
Re: Current state of ActionPlugin
From: jp charras, 2017-01-23