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 <[email protected]>: >>> 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 : [email protected] >>> 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 <[email protected]> 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
_______________________________________________ Mailing list: https://launchpad.net/~kicad-developers Post to : [email protected] Unsubscribe : https://launchpad.net/~kicad-developers More help : https://help.launchpad.net/ListHelp

