FreeCAD

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

27
The objects can be simple linear dimensions that measure between two arbitrary
28
points, or linear dimensions linked to an edge.
29
It can also be radius or diameter dimensions that measure circles
30
and circular arcs.
31
And it can also be an angular dimension measuring the angle between
32
two straight lines.
33
"""
34
## @package gui_dimensions
35
# \ingroup draftguitools
36
# \brief Provides GUI tools to create dimension objects.
37

38
import math
39
import lazy_loader.lazy_loader as lz
40
from PySide.QtCore import QT_TRANSLATE_NOOP
41

42
import FreeCAD as App
43
import FreeCADGui as Gui
44
import Draft_rc
45
import DraftVecUtils
46
import draftguitools.gui_base_original as gui_base_original
47
import draftguitools.gui_tool_utils as gui_tool_utils
48
import draftguitools.gui_trackers as trackers
49
import draftutils.gui_utils as gui_utils
50

51
from draftutils.translate import translate
52
from draftutils.messages import _toolmsg, _msg
53

54
DraftGeomUtils = lz.LazyLoader("DraftGeomUtils", globals(), "DraftGeomUtils")
55

56
# The module is used to prevent complaints from code checkers (flake8)
57
True if Draft_rc.__name__ else False
58

59
## \addtogroup draftguitools
60
# @{
61

62

63
class Dimension(gui_base_original.Creator):
64
    """Gui command for the Dimension tool.
65

66
    This includes at the moment linear, radial, diametrical,
67
    and angular dimensions depending on the selected object
68
    and the modifier key (ALT) used.
69

70
    Maybe in the future each type can be in its own class,
71
    and they can inherit their basic properties from a parent class.
72
    """
73

74
    def __init__(self):
75
        super().__init__()
76
        self.max = 2
77
        self.cont = None
78
        self.dir = None
79

80
    def GetResources(self):
81
        """Set icon, menu and tooltip."""
82

83
        return {'Pixmap': 'Draft_Dimension',
84
                'Accel': "D, I",
85
                'MenuText': QT_TRANSLATE_NOOP("Draft_Dimension", "Dimension"),
86
                'ToolTip': QT_TRANSLATE_NOOP("Draft_Dimension", "Creates a dimension.\n\n- Pick three points to create a simple linear dimension.\n- Select a straight line to create a linear dimension linked to that line.\n- Select an arc or circle to create a radius or diameter dimension linked to that arc.\n- Select two straight lines to create an angular dimension between them.\nCTRL to snap, SHIFT to constrain, ALT to select an edge or arc.\n\nYou may select a single line or single circular arc before launching this command\nto create the corresponding linked dimension.\nYou may also select an 'App::MeasureDistance' object before launching this command\nto turn it into a 'Draft Dimension' object.")}
87

88
    def Activated(self):
89
        """Execute when the command is called."""
90
        if self.cont:
91
            self.finish()
92
        elif self.selected_app_measure():
93
            super().Activated(name="Dimension")
94
            self.dimtrack = trackers.dimTracker()
95
            self.arctrack = trackers.arcTracker()
96
            self.create_with_app_measure()
97
            self.finish()
98
        else:
99
            super().Activated(name="Dimension")
100
            if self.ui:
101
                self.ui.pointUi(title=translate("draft", "Dimension"), icon="Draft_Dimension")
102
                self.ui.continueCmd.show()
103
                self.ui.selectButton.show()
104
                self.altdown = False
105
                self.call = self.view.addEventCallback("SoEvent", self.action)
106
                self.dimtrack = trackers.dimTracker()
107
                self.arctrack = trackers.arcTracker()
108
                self.link = None
109
                self.edges = []
110
                self.angles = []
111
                self.angledata = None
112
                self.indices = []
113
                self.center = None
114
                self.arcmode = False
115
                self.point1 = None
116
                self.point2 = None
117
                self.proj_point1 = None
118
                self.proj_point2 = None
119
                self.force = None
120
                self.info = None
121
                self.selectmode = False
122
                self.set_selection()
123
                _toolmsg(translate("draft", "Pick first point"))
124

125
    def set_selection(self):
126
        """Fill the nodes according to the selected geometry."""
127
        sel = Gui.Selection.getSelectionEx()
128
        if (len(sel) == 1
129
                and len(sel[0].SubElementNames) == 1
130
                and "Edge" in sel[0].SubElementNames[0]):
131
            # The selection is just a single `Edge`
132
            sel_object = sel[0]
133
            edge = sel_object.SubObjects[0]
134

135
            # `n` is the edge number starting from 0 not from 1.
136
            # The reason is lists in Python start from 0, although
137
            # in the object's `Shape`, they start from 1
138
            n = int(sel_object.SubElementNames[0].lstrip("Edge")) - 1
139
            self.indices.append(n)
140

141
            if DraftGeomUtils.geomType(edge) == "Line":
142
                self.node.extend([edge.Vertexes[0].Point,
143
                                  edge.Vertexes[1].Point])
144

145
                # Iterate over the vertices of the parent `Object`;
146
                # when the vertices match those of the selected `edge`
147
                # save the index of vertex in the parent object
148
                v1 = None
149
                v2 = None
150
                for i, v in enumerate(sel_object.Object.Shape.Vertexes):
151
                    if v.Point == edge.Vertexes[0].Point:
152
                        v1 = i
153
                    if v.Point == edge.Vertexes[1].Point:
154
                        v2 = i
155

156
                if v1 is not None and v2 is not None: # note that v1 or v2 can be zero
157
                    self.link = [sel_object.Object, v1, v2]
158
            elif DraftGeomUtils.geomType(edge) == "Circle":
159
                self.node.extend([edge.Curve.Center,
160
                                  edge.Vertexes[0].Point])
161
                self.edges = [edge]
162
                self.arcmode = "diameter"
163
                self.link = [sel_object.Object, n]
164

165
    def selected_app_measure(self):
166
        """Check if App::MeasureDistance objects are selected."""
167
        sel = Gui.Selection.getSelection()
168
        if not sel:
169
            return False
170
        for o in sel:
171
            if not o.isDerivedFrom("App::MeasureDistance"):
172
                return False
173
        return True
174

175
    def finish(self, cont=False):
176
        """Terminate the operation."""
177
        self.end_callbacks(self.call)
178
        self.cont = None
179
        self.dir = None
180
        if self.ui:
181
            self.dimtrack.finalize()
182
            self.arctrack.finalize()
183
        super().finish()
184

185
    def angle_dimension_normal(self, edge1, edge2):
186
        rot = App.Rotation(DraftGeomUtils.vec(edge1),
187
                           DraftGeomUtils.vec(edge2),
188
                           self.wp.axis,
189
                           "XYZ")
190
        norm = rot.multVec(App.Vector(0, 0, 1))
191
        vnorm = gui_utils.get_3d_view().getViewDirection()
192
        if vnorm.getAngle(norm) < math.pi / 2:
193
            norm = norm.negative()
194
        return norm
195

196
    def create_with_app_measure(self):
197
        """Create on measurement objects.
198

199
        This is used when the selection is an `'App::MeasureDistance'`,
200
        which is created with the basic tool `Std_MeasureDistance`.
201
        This object is removed and in its place a `Draft Dimension`
202
        is created.
203
        """
204
        for o in Gui.Selection.getSelection():
205
            p1 = o.P1
206
            p2 = o.P2
207
            _root = o.ViewObject.RootNode
208
            _ch = _root.getChildren()[1].getChildren()[0].getChildren()[0]
209
            pt = _ch.getChildren()[3]
210
            p3 = App.Vector(pt.point.getValues()[2].getValue())
211

212
            Gui.addModule("Draft")
213
            _cmd = 'Draft.make_linear_dimension'
214
            _cmd += '('
215
            _cmd += DraftVecUtils.toString(p1) + ', '
216
            _cmd += DraftVecUtils.toString(p2) + ', '
217
            _cmd += 'dim_line=' + DraftVecUtils.toString(p3)
218
            _cmd += ')'
219
            _rem = 'FreeCAD.ActiveDocument.removeObject("' + o.Name + '")'
220
            _cmd_list = ['_dim_ = ' + _cmd,
221
                         _rem,
222
                         'Draft.autogroup(_dim_)',
223
                         'FreeCAD.ActiveDocument.recompute()']
224
            self.commit(translate("draft", "Create Dimension"),
225
                        _cmd_list)
226

227
    def create_angle_dimension(self):
228
        """Create an angular dimension from a center and two angles."""
229
        ang1 = math.degrees(self.angledata[1])
230
        ang2 = math.degrees(self.angledata[0])
231
        norm = self.angle_dimension_normal(self.edges[0], self.edges[1])
232

233
        _cmd = 'Draft.make_angular_dimension'
234
        _cmd += '('
235
        _cmd += 'center=' + DraftVecUtils.toString(self.center) + ', '
236
        _cmd += 'angles='
237
        _cmd += '['
238
        _cmd += str(ang1) + ', '
239
        _cmd += str(ang2)
240
        _cmd += '], '
241
        _cmd += 'dim_line=' + DraftVecUtils.toString(self.node[-1]) + ', '
242
        _cmd += 'normal=' + DraftVecUtils.toString(norm)
243
        _cmd += ')'
244
        _cmd_list = ['_dim_ = ' + _cmd,
245
                     'Draft.autogroup(_dim_)',
246
                     'FreeCAD.ActiveDocument.recompute()']
247
        self.commit(translate("draft", "Create Dimension"),
248
                    _cmd_list)
249

250
    def create_linear_dimension(self):
251
        """Create a simple linear dimension, not linked to an edge."""
252
        _cmd = 'Draft.make_linear_dimension'
253
        _cmd += '('
254
        _cmd += DraftVecUtils.toString(self.node[0]) + ', '
255
        _cmd += DraftVecUtils.toString(self.node[1]) + ', '
256
        _cmd += 'dim_line=' + DraftVecUtils.toString(self.node[2])
257
        _cmd += ')'
258
        _cmd_list = ['_dim_ = ' + _cmd,
259
                     'Draft.autogroup(_dim_)',
260
                     'FreeCAD.ActiveDocument.recompute()']
261
        self.commit(translate("draft", "Create Dimension"),
262
                    _cmd_list)
263

264
    def create_linear_dimension_obj(self, direction=None):
265
        """Create a linear dimension linked to an edge.
266

267
        The `link` attribute has indices of vertices as they appear
268
        in the list `Shape.Vertexes`, so they start as zero 0.
269

270
        The `LinearDimension` class, created by `make_linear_dimension_obj`,
271
        considers the vertices of a `Shape` which are numbered to start
272
        with 1, that is, `Vertex1`.
273
        Therefore the value in `link` has to be incremented by 1.
274
        """
275
        _cmd = 'Draft.make_linear_dimension_obj'
276
        _cmd += '('
277
        _cmd += 'FreeCAD.ActiveDocument.' + self.link[0].Name + ', '
278
        _cmd += 'i1=' + str(self.link[1] + 1) + ', '
279
        _cmd += 'i2=' + str(self.link[2] + 1) + ', '
280
        _cmd += 'dim_line=' + DraftVecUtils.toString(self.node[2])
281
        _cmd += ')'
282
        _cmd_list = ['_dim_ = ' + _cmd]
283

284
        dir_u = DraftVecUtils.toString(self.wp.u)
285
        dir_v = DraftVecUtils.toString(self.wp.v)
286
        if direction == "X":
287
            _cmd_list += ['_dim_.Direction = ' + dir_u]
288
        elif direction == "Y":
289
            _cmd_list += ['_dim_.Direction = ' + dir_v]
290

291
        _cmd_list += ['Draft.autogroup(_dim_)',
292
                      'FreeCAD.ActiveDocument.recompute()']
293
        self.commit(translate("draft", "Create Dimension"),
294
                    _cmd_list)
295

296
    def create_radial_dimension_obj(self):
297
        """Create a radial dimension linked to a circular edge."""
298
        _cmd = 'Draft.make_radial_dimension_obj'
299
        _cmd += '('
300
        _cmd += 'FreeCAD.ActiveDocument.' + self.link[0].Name + ', '
301
        _cmd += 'index=' + str(self.link[1] + 1) + ', '
302
        _cmd += 'mode="' + str(self.arcmode) + '", '
303
        _cmd += 'dim_line=' + DraftVecUtils.toString(self.node[2])
304
        _cmd += ')'
305
        _cmd_list = ['_dim_ = ' + _cmd,
306
                     'Draft.autogroup(_dim_)',
307
                     'FreeCAD.ActiveDocument.recompute()']
308
        self.commit(translate("draft", "Create Dimension (radial)"),
309
                    _cmd_list)
310

311
    def createObject(self):
312
        """Create the actual object in the current document."""
313
        Gui.addModule("Draft")
314

315
        if self.angledata:
316
            # Angle dimension, with two angles provided
317
            self.create_angle_dimension()
318
        elif self.link and not self.arcmode:
319
            # Linear dimension, linked to a straight edge
320
            if self.force == 1:
321
                self.create_linear_dimension_obj("Y")
322
            elif self.force == 2:
323
                self.create_linear_dimension_obj("X")
324
            else:
325
                self.create_linear_dimension_obj()
326
        elif self.arcmode:
327
            # Radius or dimeter dimension, linked to a circular edge
328
            self.create_radial_dimension_obj()
329
        else:
330
            # Linear dimension, not linked to any edge
331
            self.create_linear_dimension()
332

333
        if self.ui.continueMode:
334
            self.cont = self.node[2]
335
            if not self.dir:
336
                if self.link:
337
                    v1 = self.link[0].Shape.Vertexes[self.link[1]].Point
338
                    v2 = self.link[0].Shape.Vertexes[self.link[2]].Point
339
                    self.dir = v2.sub(v1)
340
                else:
341
                    self.dir = self.node[1].sub(self.node[0])
342

343
            self.node = [self.node[1]]
344

345
        self.link = None
346

347
    def selectEdge(self):
348
        """Toggle the select mode to the opposite state."""
349
        self.selectmode = not self.selectmode
350

351
    def action(self, arg):
352
        """Handle the 3D scene events.
353

354
        This is installed as an EventCallback in the Inventor view.
355

356
        Parameters
357
        ----------
358
        arg: dict
359
            Dictionary with strings that indicates the type of event received
360
            from the 3D view.
361
        """
362
        if arg["Type"] == "SoKeyboardEvent":
363
            if arg["Key"] == "ESCAPE":
364
                self.finish()
365
        elif arg["Type"] == "SoLocation2Event":  # mouse movement detection
366
            shift = gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_constrain_key())
367
            if self.arcmode or self.point2:
368
                gui_tool_utils.setMod(arg, gui_tool_utils.get_mod_constrain_key(), False)
369
            (self.point,
370
             ctrlPoint, self.info) = gui_tool_utils.getPoint(self, arg,
371
                                                             noTracker=(len(self.node)>0))
372
            if (gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key())
373
                    or self.selectmode) and (len(self.node) < 3):
374
                self.dimtrack.off()
375
                if not self.altdown:
376
                    self.altdown = True
377
                    self.ui.switchUi(True)
378
                    if hasattr(Gui, "Snapper"):
379
                        Gui.Snapper.setSelectMode(True)
380
                snapped = self.view.getObjectInfo((arg["Position"][0],
381
                                                   arg["Position"][1]))
382
                if snapped:
383
                    ob = self.doc.getObject(snapped['Object'])
384
                    if "Edge" in snapped['Component']:
385
                        num = int(snapped['Component'].lstrip('Edge')) - 1
386
                        ed = ob.Shape.Edges[num]
387
                        v1 = ed.Vertexes[0].Point
388
                        v2 = ed.Vertexes[-1].Point
389
                        self.dimtrack.update([v1, v2, self.cont])
390
            else:
391
                if self.node and (len(self.edges) < 2):
392
                    self.dimtrack.on()
393
                if len(self.edges) == 2:
394
                    # angular dimension
395
                    self.dimtrack.off()
396

397
                    vnorm = gui_utils.get_3d_view().getViewDirection()
398
                    anorm = self.arctrack.normal
399

400
                    # Code below taken from WorkingPlane.projectPoint:
401
                    cos = vnorm.dot(anorm)
402
                    delta_ax_proj = (self.point - self.center).dot(anorm)
403
                    proj = self.point - delta_ax_proj / cos * vnorm
404
                    self.point = proj
405

406
                    r = self.point.sub(self.center)
407
                    self.arctrack.setRadius(r.Length)
408
                    a = self.arctrack.getAngle(self.point)
409
                    pair = DraftGeomUtils.getBoundaryAngles(a, self.angles)
410
                    if not (pair[0] < a < pair[1]):
411
                        self.angledata = [4 * math.pi - pair[0],
412
                                          2 * math.pi - pair[1]]
413
                    else:
414
                        self.angledata = [2 * math.pi - pair[0],
415
                                          2 * math.pi - pair[1]]
416
                    self.arctrack.setStartAngle(self.angledata[0])
417
                    self.arctrack.setEndAngle(self.angledata[1])
418
                if self.altdown:
419
                    self.altdown = False
420
                    self.ui.switchUi(False)
421
                    if hasattr(Gui, "Snapper"):
422
                        Gui.Snapper.setSelectMode(False)
423
                if self.node and self.dir and len(self.node) < 2:
424
                    _p = DraftVecUtils.project(self.point.sub(self.node[0]),
425
                                               self.dir)
426
                    self.point = self.node[0].add(_p)
427
                if len(self.node) == 2:
428
                    if self.arcmode and self.edges:
429
                        cen = self.edges[0].Curve.Center
430
                        rad = self.edges[0].Curve.Radius
431
                        baseray = self.point.sub(cen)
432
                        v2 = DraftVecUtils.scaleTo(baseray, rad)
433
                        v1 = v2.negative()
434
                        if shift:
435
                            self.node = [cen, cen.add(v2)]
436
                            self.arcmode = "radius"
437
                        else:
438
                            self.node = [cen.add(v1), cen.add(v2)]
439
                            self.arcmode = "diameter"
440
                        self.dimtrack.update(self.node)
441
                # Draw constraint tracker line.
442
                if shift and (not self.arcmode):
443
                    if len(self.node) == 2:
444
                        if not self.point1:
445
                            self.point1 = self.node[0]
446
                        if not self.point2:
447
                            self.point2 = self.node[1]
448
                        # else:
449
                        #     self.node[1] = self.point2
450
                        self.set_constraint_node()
451
                else:
452
                    self.force = None
453
                    self.proj_point1 = None
454
                    self.proj_point2 = None
455
                    if self.point1:
456
                        self.node[0] = self.point1
457
                    if self.point2 and (len(self.node) > 1):
458
                        self.node[1] = self.point2
459
                        # self.point2 = None
460
                # update the dimline
461
                if self.node and not self.arcmode:
462
                    self.dimtrack.update(self.node
463
                                         + [self.point] + [self.cont])
464
            gui_tool_utils.redraw3DView()
465
        elif arg["Type"] == "SoMouseButtonEvent":
466
            if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
467
                if self.point:
468
                    self.ui.redraw()
469
                    if (not self.node) and (not self.support):
470
                        gui_tool_utils.getSupport(arg)
471
                    if (gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key())
472
                            or self.selectmode) and (len(self.node) < 3):
473
                        # print("snapped: ",self.info)
474
                        if self.info:
475
                            ob = self.doc.getObject(self.info['Object'])
476
                            if 'Edge' in self.info['Component']:
477
                                num = int(self.info['Component'].lstrip('Edge')) - 1
478
                                ed = ob.Shape.Edges[num]
479
                                v1 = ed.Vertexes[0].Point
480
                                v2 = ed.Vertexes[-1].Point
481
                                i1 = i2 = None
482
                                for i in range(len(ob.Shape.Vertexes)):
483
                                    if v1 == ob.Shape.Vertexes[i].Point:
484
                                        i1 = i
485
                                    if v2 == ob.Shape.Vertexes[i].Point:
486
                                        i2 = i
487
                                if (i1 is not None) and (i2 is not None):
488
                                    self.indices.append(num)
489
                                    if not self.edges:
490
                                        # nothing snapped yet, we treat it
491
                                        # as a normal edge-snapped dimension
492
                                        self.node = [v1, v2]
493
                                        self.link = [ob, i1, i2]
494
                                        self.edges.append(ed)
495
                                        if DraftGeomUtils.geomType(ed) == "Circle":
496
                                            # snapped edge is an arc
497
                                            self.arcmode = "diameter"
498
                                            self.link = [ob, num]
499
                                    else:
500
                                        # there is already a snapped edge,
501
                                        # so we start angular dimension
502
                                        self.edges.append(ed)
503
                                        # self.node now has the 4 endpoints
504
                                        self.node.extend([v1, v2])
505
                                        c = DraftGeomUtils.findIntersection(self.node[0],
506
                                                                            self.node[1],
507
                                                                            self.node[2],
508
                                                                            self.node[3],
509
                                                                            True, True)
510
                                        if c:
511
                                            # print("centers:",c)
512
                                            self.center = c[0]
513
                                            self.arctrack.setCenter(self.center)
514
                                            self.arctrack.normal = self.angle_dimension_normal(self.edges[0], self.edges[1])
515
                                            self.arctrack.on()
516
                                            for e in self.edges:
517
                                                if e.Length < 0.00003: # Edge must be long enough for the tolerance of 0.00001mm to make sense.
518
                                                    _msg(translate("draft", "Edge too short!"))
519
                                                    self.finish()
520
                                                    return
521
                                                for i in [0, 1]:
522
                                                    pt = e.Vertexes[i].Point
523
                                                    if pt.isEqual(self.center, 0.00001): # A relatively high tolerance is required.
524
                                                        pt = e.Vertexes[i - 1].Point     # Use the other point instead.
525
                                                    self.angles.append(self.arctrack.getAngle(pt))
526
                                            self.link = [self.link[0], ob]
527
                                        else:
528
                                            _msg(translate("draft", "Edges don't intersect!"))
529
                                            self.finish()
530
                                            return
531
                                self.dimtrack.on()
532
                    else:
533
                        self.node.append(self.point)
534
                    self.selectmode = False
535
                    # print("node", self.node)
536
                    self.dimtrack.update(self.node)
537
                    if len(self.node) == 2:
538
                        self.point2 = self.node[1]
539
                    if len(self.node) == 1:
540
                        self.dimtrack.on()
541
                        if self.planetrack:
542
                            self.planetrack.set(self.node[0])
543
                    elif len(self.node) == 2 and self.cont:
544
                        self.node.append(self.cont)
545
                        self.createObject()
546
                        if not self.cont:
547
                            self.finish()
548
                    elif len(self.node) == 3:
549
                        # for unlinked arc mode:
550
                        # if self.arcmode:
551
                        #     v = self.node[1].sub(self.node[0])
552
                        #     v.multiply(0.5)
553
                        #     cen = self.node[0].add(v)
554
                        #     self.node = [self.node[0], self.node[1], cen]
555
                        self.createObject()
556
                        if not self.cont:
557
                            self.finish()
558
                    elif self.angledata:
559
                        self.node.append(self.point)
560
                        self.createObject()
561
                        self.finish()
562

563
    def numericInput(self, numx, numy, numz):
564
        """Validate the entry fields in the user interface.
565

566
        This function is called by the toolbar or taskpanel interface
567
        when valid x, y, and z have been entered in the input fields.
568
        """
569
        self.point = App.Vector(numx, numy, numz)
570
        self.node.append(self.point)
571
        self.dimtrack.update(self.node)
572
        if len(self.node) == 1:
573
            self.dimtrack.on()
574
        elif len(self.node) == 3:
575
            self.createObject()
576
            if not self.cont:
577
                self.finish()
578

579
    def set_constraint_node(self):
580
        """Set constrained nodes for vertical or horizontal dimension
581
        by projecting on the working plane.
582
        """
583
        if not self.proj_point1 or not self.proj_point2:
584
            self.proj_point1 = self.wp.project_point(self.node[0])
585
            self.proj_point2 = self.wp.project_point(self.node[1])
586
            proj_u= self.wp.u.dot(self.proj_point2 - self.proj_point1)
587
            proj_v= self.wp.v.dot(self.proj_point2 - self.proj_point1)
588
            active_view = Gui.ActiveDocument.ActiveView
589
            cursor = active_view.getCursorPos()
590
            cursor_point = active_view.getPoint(cursor)
591
            self.point = self.wp.project_point(cursor_point)
592
            if not self.force:
593
                ref_point = self.point - (self.proj_point2 + self.proj_point1)*1/2
594
                ref_angle = abs(ref_point.getAngle(self.wp.u))
595
                if (ref_angle > math.pi/4) and (ref_angle <= 0.75*math.pi):
596
                    self.force = 2
597
                else:
598
                    self.force = 1
599
            if self.force == 1:
600
                self.node[0] = self.proj_point1
601
                self.node[1] = self.proj_point1 + self.wp.v*proj_v
602
            elif self.force == 2:
603
                self.node[0] = self.proj_point1
604
                self.node[1] = self.proj_point1 + self.wp.u*proj_u
605

606

607
Gui.addCommand('Draft_Dimension', Dimension())
608

609
## @}
610

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

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

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

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