FreeCAD-Doc/localwiki/Macro_Shake_Sketch.html
2018-07-08 12:11:49 -05:00

213 lines
7.1 KiB
HTML

<html><head><title>Macro Shake Sketch</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><link type='text/css' href='wiki.css' rel='stylesheet'></head><body><h1>Macro Shake Sketch</h1></div>
<div id="mw-content-text" lang="en" dir="ltr" class="mw-content-ltr"><div class="mw-parser-output"><table class="fcinfobox wikitable ct" width="100%" style="float: right; width: 230px; margin-left: 10px;">
<tr>
<td class="ctTitle">
<h3><span class="mw-headline" id="Macro_Shake_Sketch"><a href="https://www.freecadweb.org/wiki/index.php?title=File:Text-x-python.png" class="image"><img alt="Text-x-python.png" src="32px-Text-x-python.png" width="32" height="32" srcset="/wiki/images/2/2c/Text-x-python.png 1.5x" /></a> Macro Shake Sketch</span></h3>
</td></tr>
<tr>
<th class="ctOdd">Description
</th></tr>
<tr>
<td class="ctEven left macro-description">Shake a sketch in order to discover its unconstrained parts
</td></tr>
<tr>
<th class="ctOdd">Author
</th></tr>
<tr>
<td class="ctEven macro-author"><a href="https://www.freecadweb.org/wiki/index.php?title=User:Ga%C3%ABl_Ecorchard&amp;action=edit&amp;redlink=1" class="new" title="User:Gaël Ecorchard (page does not exist)">Gaël Ecorchard</a>
</td></tr>
<tr>
<th class="ctOdd">Links
</th></tr>
<tr>
<td class="ctEven"><a href="Macros_recipes.html" title="Macros recipes">Macros recipes</a><br /><a href="How_to_install_macros.html" title="How to install macros">How to install macros</a><br /><a href="Customize_Toolbars.html" title="Customize Toolbars">How to customize toolbars</a>
</td></tr>
<tr>
<th class="ctOdd">Version
</th></tr>
<tr>
<td class="ctEven macro-version">1.1
</td></tr>
<tr>
<th class="ctOdd">Date last modification
</th></tr>
<tr>
<td class="ctEven macro-date">2014-10-31
</td></tr>
<tr>
<th class="ctOdd">
</th></tr>
<tr>
<td class="ctToc"><br /><div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div>
<ul>
<li class="toclevel-1"><a href="#Macro_Shake_Sketch"><span class="tocnumber">1</span> <span class="toctext">Macro Shake Sketch</span></a></li>
<li class="toclevel-1 tocsection-1"><a href="#Script"><span class="tocnumber">2</span> <span class="toctext">Script</span></a></li>
</ul>
</div>
</td></tr>
</table>
<p><br />
</p><p>Shake a sketch in order to discover its unconstrained parts. Enter edit mode for a sketch and launch the macro. The macro will add a random noise on all sketch points. The sketch is then solved, constrained parts will retain their position, free parts will move.
</p><p><b>But be careful working on a copy of your file because the macro "dismantles all" to display and you may start over.</b>
</p>
<h3><span class="mw-headline" id="Script">Script</span></h3>
<p>Macro Shake_Sketch.py
</p>
<pre># -*- coding: utf-8 -*-
# FreeCAD macro to shake a sketch in order to discover its unconstrained parts.
#
# A Gaussian noise is introduced in all sketch points and the sketch is then
# solved.
# Beware that the sketch can look different because some constraints have
# several solutions. In this case, just undo.
#
# This file is released under the MIT License.
# Author: Gaël Ecorchard
# Version:
# - 1.1, 2014-10-31
# * correct import for Part
# - 1.0, 2014-08, first release.
# Amplitude of the point displacements.
# The standard deviation of the Gaussian noise is the largest sketch dimension
# multiplied by this factor.
displacement_amplitude = 0.1
# End of configuration.
from random import gauss
import FreeCADGui as Gui
from FreeCAD import Base
import Part
# For each sketch geometry type, map a list of points to move.
g_geom_points = {
Base.Vector: [1],
Part.Line: [1, 2], # first point, last point
Part.Circle: [0, 3], # curve, center
Part.ArcOfCircle: [1, 2, 3], # first point, last point, center
}
class BoundingBox(object):
xmin = None
xmax = None
ymin = None
ymax = None
def enlarge_x(self, x):
if self.xmin is None:
self.xmin = x
self.xmax = x
return
if self.xmin &gt; x:
self.xmin = x
return
if self.xmax &lt; x:
self.xmax = x
return
def enlarge_y(self, y):
if self.ymin is None:
self.ymin = y
self.ymax = y
return
if self.ymin &gt; y:
self.ymin = y
return
if self.ymax &lt; y:
self.ymax = y
return
def enlarge_point(self, point):
self.enlarge_x(point.x)
self.enlarge_y(point.y)
def enlarge_line(self, line):
self.enlarge_x(line.StartPoint.x)
self.enlarge_x(line.EndPoint.x)
self.enlarge_y(line.StartPoint.y)
self.enlarge_y(line.EndPoint.y)
def enlarge_circle(self, circle):
self.enlarge_x(circle.Center.x - circle.Radius)
self.enlarge_x(circle.Center.x + circle.Radius)
self.enlarge_y(circle.Center.y - circle.Radius)
self.enlarge_y(circle.Center.y + circle.Radius)
def enlarge_arc_of_circle(self, arc):
# TODO: correctly compute the arc extrema (cf. toShape().BoundBox)
self.enlarge_x(arc.Center.x)
self.enlarge_y(arc.Center.y)
def get_sketch_dims(sketch):
bbox = BoundingBox()
for geom in sketch.Geometry:
if isinstance(geom, Base.Vector):
bbox.enlarge_point(geom)
elif isinstance(geom, Part.Line):
bbox.enlarge_line(geom)
elif isinstance(geom, Part.Circle):
bbox.enlarge_circle(geom)
elif isinstance(geom, Part.ArcOfCircle):
bbox.enlarge_arc_of_circle(geom)
if (bbox.xmin is not None) and (bbox.ymin is not None):
return bbox.xmax - bbox.xmin, bbox.ymax - bbox.ymin
else:
return 0, 0
def add_noise(point, sigma):
"""Add a Gaussian noise with standard deviation sigma"""
point.x = gauss(point.x, sigma)
point.y = gauss(point.y, sigma)
def move_points(sketch, geom_index, sigma):
point_indexes = g_geom_points[type(sketch.Geometry[i])]
# Direct access to sketch.Geometry[index] does not work. This would,
# however prevent repeated recompute.
for point_index in point_indexes:
point = sketch.getPoint(geom_index, point_index)
add_noise(point, sigma)
sketch.movePoint(geom_index, point_index, point)
view_provider = Gui.activeDocument().getInEdit()
# Don't know how to exit from a macro.
do_move = True
if not view_provider:
do_move = False
if do_move:
sketch = view_provider.Object
if sketch.TypeId&#160;!= 'Sketcher::SketchObject':
do_move = False
if do_move:
sigma = max(get_sketch_dims(sketch)) * displacement_amplitude
for i in range(len((sketch.Geometry))):
move_points(sketch, i, sigma) </pre>
<div style="clear:both"></div>
</div>
</div>
</div><div class="printfooter">
Online version: "<a dir="ltr" href="https://www.freecadweb.org/wiki/index.php?title=Macro_Shake_Sketch&amp;oldid=240984">http://www.freecadweb.org/wiki/index.php?title=Macro_Shake_Sketch&amp;oldid=240984</a>"</div>
<div id="catlinks" class="catlinks" data-mw="interface"></div><div class="visualClear"></div>
</div>
</div>
<div id="mw-navigation">
<h2>Navigation menu</h2>
</body></html>