| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | """This module contains FreeCAD commands for the Draft workbench""" |
| |
|
| | import os |
| | from PySide.QtCore import QT_TRANSLATE_NOOP |
| |
|
| | import FreeCAD as App |
| | from draftgeoutils.general import geomType |
| | from draftobjects.base import DraftObject |
| | from draftutils import gui_utils |
| | from draftutils.messages import _err |
| | from draftutils.translate import translate |
| |
|
| |
|
| | class Hatch(DraftObject): |
| |
|
| | def __init__(self, obj): |
| |
|
| | obj.Proxy = self |
| | self.Type = "Hatch" |
| | self.setProperties(obj) |
| |
|
| | def setProperties(self, obj): |
| |
|
| | pl = obj.PropertiesList |
| | if not "Base" in pl: |
| | obj.addProperty( |
| | "App::PropertyLink", |
| | "Base", |
| | "Hatch", |
| | QT_TRANSLATE_NOOP("App::Property", "The base object used by this object"), |
| | locked=True, |
| | ) |
| | if not "File" in pl: |
| | obj.addProperty( |
| | "App::PropertyFile", |
| | "File", |
| | "Hatch", |
| | QT_TRANSLATE_NOOP("App::Property", "The PAT file used by this object"), |
| | locked=True, |
| | ) |
| | if not "Pattern" in pl: |
| | obj.addProperty( |
| | "App::PropertyString", |
| | "Pattern", |
| | "Hatch", |
| | QT_TRANSLATE_NOOP("App::Property", "The pattern name used by this object"), |
| | locked=True, |
| | ) |
| | if not "Scale" in pl: |
| | obj.addProperty( |
| | "App::PropertyFloat", |
| | "Scale", |
| | "Hatch", |
| | QT_TRANSLATE_NOOP("App::Property", "The pattern scale used by this object"), |
| | locked=True, |
| | ) |
| | if not "Rotation" in pl: |
| | obj.addProperty( |
| | "App::PropertyAngle", |
| | "Rotation", |
| | "Hatch", |
| | QT_TRANSLATE_NOOP("App::Property", "The pattern rotation used by this object"), |
| | locked=True, |
| | ) |
| | if not "Translate" in pl: |
| | obj.addProperty( |
| | "App::PropertyBool", |
| | "Translate", |
| | "Hatch", |
| | QT_TRANSLATE_NOOP( |
| | "App::Property", |
| | "If set to False, hatch is applied as is to the faces, without translation (this might give wrong results for non-XY faces)", |
| | ), |
| | locked=True, |
| | ) |
| | obj.Translate = True |
| |
|
| | def onDocumentRestored(self, obj): |
| | self.setProperties(obj) |
| | super().onDocumentRestored(obj) |
| | gui_utils.restore_view_object( |
| | obj, vp_module="view_hatch", vp_class="ViewProviderDraftHatch" |
| | ) |
| |
|
| | def dumps(self): |
| | return |
| |
|
| | def loads(self, state): |
| | self.Type = "Hatch" |
| |
|
| | def execute(self, obj): |
| |
|
| | if ( |
| | self.props_changed_placement_only(obj) |
| | or not obj.Base |
| | or not obj.File |
| | or not obj.Pattern |
| | or not obj.Scale |
| | or not obj.Base.isDerivedFrom("Part::Feature") |
| | or not obj.Base.Shape.Faces |
| | ): |
| | self.props_changed_clear() |
| | return |
| |
|
| | if obj.File[0] == ".": |
| | |
| | pat_file = os.path.join(os.path.dirname(obj.Document.FileName), obj.File) |
| | |
| | pat_file = os.path.abspath(pat_file) |
| | else: |
| | pat_file = obj.File |
| |
|
| | |
| | if not os.path.exists(pat_file): |
| | _err(obj.Label + ": " + translate("draft", "PAT file not found")) |
| | self.props_changed_clear() |
| | return |
| | if not os.path.isfile(pat_file): |
| | _err(obj.Label + ": " + translate("draft", "Specified PAT file is not a file")) |
| | self.props_changed_clear() |
| | return |
| | if os.path.splitext(pat_file)[1].lower() != ".pat": |
| | _err(obj.Label + ": " + translate("draft", "Specified file type is not supported")) |
| | self.props_changed_clear() |
| | return |
| | if not obj.Pattern in self.getPatterns(pat_file): |
| | _err(obj.Label + ": " + translate("draft", "Pattern not found in PAT file")) |
| | self.props_changed_clear() |
| | return |
| |
|
| | import Part |
| | import TechDraw |
| |
|
| | |
| | |
| | param_grp = App.ParamGet("User parameter:BaseApp/Preferences/Mod/TechDraw/debug") |
| | if "allowCrazyEdge" not in param_grp.GetBools(): |
| | old_allow_crazy_edge = None |
| | else: |
| | old_allow_crazy_edge = param_grp.GetBool("allowCrazyEdge") |
| | param_grp.SetBool("allowCrazyEdge", True) |
| |
|
| | shapes = [] |
| | for face in obj.Base.Shape.Faces: |
| | if face.findPlane(): |
| | face = face.copy() |
| | if obj.Translate: |
| | mtx = None |
| | w = face.normalAt(0, 0) |
| | |
| | |
| | for e in face.Edges: |
| | if geomType(e) == "Line": |
| | sta = e.firstVertex().Point |
| | end = e.lastVertex().Point |
| | u = end.sub(sta) |
| | if u.Length > 0.001: |
| | u = u.normalize() |
| | v = w.cross(u) |
| | |
| | mtx = App.Matrix(u.x, v.x, w.x, sta.x, |
| | u.y, v.y, w.y, sta.y, |
| | u.z, v.z, w.z, sta.z, |
| | 0.0, 0.0, 0.0, 1.0) |
| | |
| | break |
| | |
| | if not mtx: |
| | cen = face.CenterOfMass |
| | rot = App.Rotation(App.Vector(0, 0, 1), w) |
| | mtx = App.Placement(cen, rot).Matrix |
| | face = face.transformShape(mtx.inverse()).Faces[0] |
| | if obj.Rotation.Value: |
| | face.rotate(App.Vector(), App.Vector(0, 0, 1), -obj.Rotation) |
| |
|
| | shape = TechDraw.makeGeomHatch(face, obj.Scale, obj.Pattern, pat_file) |
| |
|
| | if obj.Rotation.Value: |
| | shape.rotate(App.Vector(), App.Vector(0, 0, 1), obj.Rotation) |
| | if obj.Translate: |
| | shape = shape.transformShape(mtx) |
| | shapes.append(shape) |
| |
|
| | if old_allow_crazy_edge is None: |
| | param_grp.RemBool("allowCrazyEdge") |
| | else: |
| | param_grp.SetBool("allowCrazyEdge", old_allow_crazy_edge) |
| |
|
| | if shapes: |
| | obj.Shape = Part.makeCompound(shapes) |
| | self.props_changed_clear() |
| |
|
| | def onChanged(self, obj, prop): |
| |
|
| | self.props_changed_store(prop) |
| |
|
| | def getPatterns(self, filename): |
| | """returns a list of pattern names found in a PAT file""" |
| | patterns = [] |
| | if os.path.exists(filename): |
| | with open(filename) as patfile: |
| | for line in patfile: |
| | if line.startswith("*"): |
| | patterns.append(line.split(",")[0][1:]) |
| | return patterns |
| |
|