FreeCAD

Форк
0
/
make_label.py 
392 строки · 15.1 Кб
1
# -*- coding: utf-8 -*-
2
# ***************************************************************************
3
# *   Copyright (c) 2009, 2010 Yorik van Havre <yorik@uncreated.net>        *
4
# *   Copyright (c) 2009, 2010 Ken Cline <cline@frii.com>                   *
5
# *   Copyright (c) 2020 Eliud Cabrera Castillo <e.cabrera-castillo@tum.de> *
6
# *                                                                         *
7
# *   This file is part of the FreeCAD CAx development system.              *
8
# *                                                                         *
9
# *   This program is free software; you can redistribute it and/or modify  *
10
# *   it under the terms of the GNU Lesser General Public License (LGPL)    *
11
# *   as published by the Free Software Foundation; either version 2 of     *
12
# *   the License, or (at your option) any later version.                   *
13
# *   for detail see the LICENCE text file.                                 *
14
# *                                                                         *
15
# *   FreeCAD is distributed in the hope that it will be useful,            *
16
# *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17
# *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18
# *   GNU Library General Public License for more details.                  *
19
# *                                                                         *
20
# *   You should have received a copy of the GNU Library General Public     *
21
# *   License along with FreeCAD; if not, write to the Free Software        *
22
# *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
23
# *   USA                                                                   *
24
# *                                                                         *
25
# ***************************************************************************
26
"""Provides functions to create Label objects."""
27
## @package make_label
28
# \ingroup draftmake
29
# \brief Provides functions to create Label objects.
30

31
## \addtogroup draftmake
32
# @{
33
import FreeCAD as App
34
from draftobjects import label
35
from draftutils import gui_utils
36
from draftutils import params
37
from draftutils import utils
38
from draftutils.messages import _wrn, _err
39
from draftutils.translate import translate
40

41
if App.GuiUp:
42
    from draftviewproviders.view_label import ViewProviderLabel
43

44

45
def make_label(target_point=App.Vector(0, 0, 0),
46
               placement=App.Vector(30, 30, 0),
47
               target_object=None, subelements=None,
48
               label_type="Custom", custom_text="Label",
49
               direction="Horizontal", distance=-10,
50
               points=None):
51
    """Create a Label object containing different types of information.
52

53
    The current color and text height and font specified in preferences
54
    are used.
55

56
    Parameters
57
    ----------
58
    target_point: Base::Vector3, optional
59
        It defaults to the origin `App.Vector(0, 0, 0)`.
60
        This is the point which is pointed to by the label's leader line.
61
        This point can be adorned with a marker like an arrow or circle.
62

63
    placement: Base::Placement, Base::Vector3, or Base::Rotation, optional
64
        It defaults to `App.Vector(30, 30, 0)`.
65
        If it is provided, it defines the base point of the textual
66
        label.
67
        The input could be a full placement, just a vector indicating
68
        the translation, or just a rotation.
69

70
    target_object: Part::Feature or str, optional
71
        It defaults to `None`.
72
        If it exists it should be an object which will be used to provide
73
        information to the label, as long as `label_type` is different
74
        from `'Custom'`.
75

76
        If it is a string, it must be the `Label` of that object.
77
        Since a `Label` is not guaranteed to be unique in a document,
78
        it will use the first object found with this `Label`.
79

80
    subelements: str, optional
81
        It defaults to `None`.
82
        If `subelements` is provided, `target_object` should be provided
83
        as well, otherwise it is ignored.
84

85
        It should be a string indicating a subelement name, either
86
        `'VertexN'`, `'EdgeN'`, or `'FaceN'` which should exist
87
        within `target_object`.
88
        In this case `'N'` is an integer that indicates the specific number
89
        of vertex, edge, or face in `target_object`.
90

91
        Both `target_object` and `subelements` are used to link the label
92
        to a particular object, or to the particular vertex, edge, or face,
93
        and get information from them.
94
        ::
95
            make_label(..., target_object=App.ActiveDocument.Box)
96
            make_label(..., target_object="My box", subelements="Face3")
97

98
        These two parameters can be can be obtained from the `Gui::Selection`
99
        module.
100
        ::
101
            sel_object = Gui.Selection.getSelectionEx()[0]
102
            target_object = sel_object.Object
103
            subelements = sel_object.SubElementNames[0]
104

105
    label_type: str, optional
106
        It defaults to `'Custom'`.
107
        It indicates the type of information that will be shown in the label.
108
        See the get_label_types function in label.py for supported types.
109

110
        Only `'Custom'` allows you to manually set the text
111
        by defining `custom_text`. The other types take their information
112
        from the object included in `target`.
113

114
        - `'Position'` will show the base position of the target object,
115
          or of the indicated `'VertexN'` in `target`.
116
        - `'Length'` will show the `Length` of the target object's `Shape`,
117
          or of the indicated `'EdgeN'` in `target`.
118
        - `'Area'` will show the `Area` of the target object's `Shape`,
119
          or of the indicated `'FaceN'` in `target`.
120

121
    custom_text: str, or list of str, optional
122
        It defaults to `'Label'`.
123
        If it is a list, each element in the list represents a new text line.
124

125
        It is the text that will be displayed by the label when
126
        `label_type` is `'Custom'`.
127

128
    direction: str, optional
129
        It defaults to `'Horizontal'`.
130
        It can be `'Horizontal'`, `'Vertical'`, or `'Custom'`.
131
        It indicates the direction of the straight segment of the leader line
132
        that ends up next to the textual label.
133

134
        If `'Custom'` is selected, the leader line can be manually drawn
135
        by specifying the value of `points`.
136
        Normally, the leader line has only three points, but with `'Custom'`
137
        you can specify as many points as needed.
138

139
    distance: int, float, Base::Quantity, optional
140
        It defaults to -10.
141
        It indicates the length of the horizontal or vertical segment
142
        of the leader line.
143

144
        The leader line is composed of two segments, the first segment is
145
        inclined, while the second segment is either horizontal or vertical
146
        depending on the value of `direction`.
147
        ::
148
            T
149
            |
150
            |
151
            o------- L text
152

153
        The `oL` segment's length is defined by `distance`
154
        while the `oT` segment is automatically calculated depending
155
        on the values of `placement` (L) and `distance` (o).
156

157
        This `distance` is oriented, meaning that if it is positive
158
        the segment will be to the right and above of the textual
159
        label, depending on if `direction` is `'Horizontal'` or `'Vertical'`,
160
        respectively.
161
        If it is negative, the segment will be to the left
162
        and below of the text.
163

164
    points: list of Base::Vector3, optional
165
        It defaults to `None`.
166
        It is a list of vectors defining the shape of the leader line;
167
        the list must have at least two points.
168
        This argument must be used together with `direction='Custom'`
169
        to display this custom leader.
170

171
        However, notice that if the Label's `StraightDirection` property
172
        is later changed to `'Horizontal'` or `'Vertical'`,
173
        the custom point list will be overwritten with a new,
174
        automatically calculated three-point list.
175

176
        For the object to use custom points, `StraightDirection`
177
        must remain `'Custom'`, and then the `Points` property
178
        can be overwritten by a suitable list of points.
179

180
    Returns
181
    -------
182
    App::FeaturePython
183
        A scripted object of type `'Label'`.
184
        This object does not have a `Shape` attribute, as the text and lines
185
        are created on screen by Coin (pivy).
186

187
    None
188
        If there is a problem it will return `None`.
189
    """
190
    _name = "make_label"
191

192
    found, doc = utils.find_doc(App.activeDocument())
193
    if not found:
194
        _err(translate("draft","No active document. Aborting."))
195
        return None
196

197
    if not target_point:
198
        target_point = App.Vector(0, 0, 0)
199
    try:
200
        utils.type_check([(target_point, App.Vector)], name=_name)
201
    except TypeError:
202
        _err(translate("draft","Wrong input: must be a vector."))
203
        return None
204

205
    if not placement:
206
        placement = App.Placement()
207
    try:
208
        utils.type_check([(placement, (App.Placement,
209
                                       App.Vector,
210
                                       App.Rotation))], name=_name)
211
    except TypeError:
212
        _err(translate("draft","Wrong input: must be a placement, a vector, or a rotation."))
213
        return None
214

215
    # Convert the vector or rotation to a full placement
216
    if isinstance(placement, App.Vector):
217
        placement = App.Placement(placement, App.Rotation())
218
    elif isinstance(placement, App.Rotation):
219
        placement = App.Placement(App.Vector(), placement)
220
        
221
    if target_object:
222
        if isinstance(target_object, (list, tuple)):
223
            _err(translate("draft","Wrong input: target_object must not be a list."))
224
            return None
225

226
        found, target_object = utils.find_object(target_object, doc)
227
        if not found:
228
            _err(translate("draft","Wrong input: target_object not in document."))
229
            return None
230

231
    if target_object and subelements:
232
        try:
233
            # Make a list
234
            if isinstance(subelements, str):
235
                subelements = [subelements]
236

237
            utils.type_check([(subelements, (list, tuple, str))],
238
                             name=_name)
239
        except TypeError:
240
            _err(translate("draft","Wrong input: subelements must be a list or tuple of strings, or a single string."))
241
            return None
242

243
        # The subelements list is used to build a special list
244
        # called a LinkSub, which includes the target_object
245
        # and the subelements.
246
        # Single: (target_object, "Edge1")
247
        # Multiple: (target_object, ("Edge1", "Edge2"))
248
        for sub in subelements:
249
            _sub = target_object.getSubObject(sub)
250
            if not _sub:
251
                _err(translate("draft","Wrong input: subelement {} not in object.").format(sub))
252
                return None
253

254
    if not label_type:
255
        label_type = "Custom"
256
    try:
257
        utils.type_check([(label_type, str)], name=_name)
258
    except TypeError:
259
        _err(translate("draft","Wrong input: label_type must be a string."))
260
        return None
261

262
    types = label.get_label_types()
263
    if label_type not in types:
264
        _err(translate("draft", "Wrong input: label_type must be one of the following:") + " " + str(types).strip("[]"))
265
        return None
266

267
    if not custom_text:
268
        custom_text = "Label"
269
    try:
270
        utils.type_check([(custom_text, (str, list))], name=_name)
271
    except TypeError:
272
        _err(translate("draft","Wrong input: must be a list of strings or a single string."))
273
        return None
274

275
    if (type(custom_text) is list
276
            and not all(isinstance(element, str) for element in custom_text)):
277
        _err(translate("draft","Wrong input: must be a list of strings or a single string."))
278
        return None
279

280
    if not direction:
281
        direction = "Horizontal"
282
    try:
283
        utils.type_check([(direction, str)], name=_name)
284
    except TypeError:
285
        _err(translate("draft","Wrong input: must be a string, 'Horizontal', 'Vertical', or 'Custom'."))
286
        return None
287

288
    if direction not in ("Horizontal", "Vertical", "Custom"):
289
        _err(translate("draft","Wrong input: must be a string, 'Horizontal', 'Vertical', or 'Custom'."))
290
        return None
291

292
    if not distance:
293
        distance = 1
294
    try:
295
        utils.type_check([(distance, (int, float))], name=_name)
296
    except TypeError:
297
        _err(translate("draft","Wrong input: must be a number."))
298
        return None
299

300
    if points:
301
        _err_msg = translate("draft","Wrong input: points {} must be a list of at least two vectors.").format(points)
302
        try:
303
            utils.type_check([(points, (tuple, list))], name=_name)
304
        except TypeError:
305
            _err(_err_msg)
306
            return None
307

308
        if len(points) < 2:
309
            _err(_err_msg)
310
            return None
311

312
        if not all(isinstance(p, App.Vector) for p in points):
313
            _err(_err_msg)
314
            return None
315

316
    new_obj = doc.addObject("App::FeaturePython",
317
                            "dLabel")
318
    label.Label(new_obj)
319

320
    new_obj.TargetPoint = target_point
321
    new_obj.Placement = placement
322
    if target_object:
323
        if subelements:
324
            new_obj.Target = [target_object, subelements]
325
        else:
326
            new_obj.Target = [target_object, []]
327

328
    new_obj.LabelType = label_type
329
    new_obj.CustomText = custom_text
330

331
    new_obj.StraightDirection = direction
332
    new_obj.StraightDistance = distance
333
    if points:
334
        if direction != "Custom":
335
            _wrn(translate("draft","Direction is not 'Custom'; points won't be used."))
336
        new_obj.Points = points
337

338
    if App.GuiUp:
339
        ViewProviderLabel(new_obj.ViewObject)
340
        h = params.get_param("textheight")
341
        new_obj.ViewObject.FontSize = h
342

343
        gui_utils.format_object(new_obj)
344
        gui_utils.select(new_obj)
345

346
    return new_obj
347

348

349
def makeLabel(targetpoint=None, target=None, direction=None,
350
              distance=None, labeltype=None, placement=None):
351
    """Create a Label. DEPRECATED. Use 'make_label'."""
352
    utils.use_instead("make_label")
353

354
    _name = "makeLabel"
355
    subelements = None
356

357
    if target:
358
        try:
359
            utils.type_check([(target, (tuple, list))],
360
                             name=_name)
361
        except TypeError:
362
            _err(translate("draft","Wrong input: must be a list of two elements. For example, [object, 'Edge1']."))
363
            return None
364

365
    # In the old function `target` is the original parameter,
366
    # a list of two elements, the target object itself, and the subelement.
367
    # If the list is a single element, it is expanded to two elements
368
    # with the second being empty
369
    # target = [object]
370
    # target = [object, ]
371
    # target = [object, []]
372
    # target = (object, )
373
    # target = (object, ())
374

375
    # Parentheses can be used as well except a single pair
376
    # target = (object)
377
    target = list(target)
378
    if len(target) == 1:
379
        target.append([])
380

381
    target_object = target[0]
382
    subelements = target[1]
383

384
    return make_label(target_point=targetpoint,
385
                      placement=placement,
386
                      target_object=target_object,
387
                      subelements=subelements,
388
                      label_type=labeltype,
389
                      direction=direction,
390
                      distance=distance)
391

392
## @}
393

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.