summaryrefslogtreecommitdiff
path: root/cad/src/exprs/scratch/Polyline_G.py
blob: 4ff6a60ada9142a130f08835cba0781446b781fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
$Id$

class ControlPoint:
    """
    abstract class for any kind of control point for use inside another object like a polyline;
    subclasses can include ones on a reference object 
    # note: obs name: PointOnReferenceObject
    """
    pass

class PolylineSegment:
    """
    abstract class for any kind of polyline segment
    """
    pass


class ModelObject: pass # rename Model3D_Component or so?


class Polyline(ModelObject):
    """
    A version of a polyline model object type based on a graph,
    with control points able to be on different ref objects;
    this class provides the data type and necessary low-level operations;
    it does NOT provide drawing and editing-UI code --
    when those are needed they must be provided by associated classes.
    """
    # each one has a graph of control points and segments
    # which have to have types that meet some APIs for them
    # (which depend only on our own code, since it uses those APIs)
    # (but note that if methods are added to this class that might add to the list of required APIs for the parts!)

    controlPointType = ControlPoint ### REVIEW: capitalize attr name?
        # note: this is the data type, not the UI, so we have the
        # most general type we can; a typical UI would encourage or require
        # the creation of points of some more specific type;
        # if so, that's declared in that UI code.

    segmentType = PolylineSegment
    
    _graph = Instance( Graph( vertexType = controlPointType,
                              edgeType = segmentType ) )
        # Q. is Instance required?
        # Note: this declaration implicitly says that this member is part of our data
        # (to be inspected, saved, copied, etc)...
        # Q. but what about the private name? does it indicate we'd rather save it
        # in terms of the separate accessors with public names??

    controlPoints = _graph.vertices

    segments = _graph.edges

    ## addControlPoint = _graph.addVertex #e or is it better to require use of controlPoints as a dict, adding or extending?
        # not necessarily... e.g. this method would require that the point was not already there.
        # OTOH we can use it as a set instead and make sure the set.add method requires that... ###k

        # the price of not doing this is having to alias tons of method names...

    # but these aliases seem useful
    addControlPoint = controlPoints.add
    addSegment = segments.add

    pass
    
class Polyline_drawer(Drawer):
    """
    a view of a polyline for the purpose of drawing it
    """
    
    delegate = Arg(Polyline, doc = "the Polyline we draw")
        ###e rename to self.polyline? but we do need to delegate to it for convenience.
    
    def draw(self):
        ### IMPLEM self.drawer as something to draw objects in their usual way,
        # subject to usual env rules for that (drawing styles and filters);
        # drawset can have optims for drawing a large set;
        # maybe we'll pass options about their role in us,
        # for it to use when looking up display styles.
        #
        # OR it can just be self, if this doesn't cause confusion due to delegation
        # by hiding parts of self.delegate. Hmm... should we declare what attrs to delegate?
        self.drawer.drawset( self.controlPoints )
        self.drawer.drawset( self.segments )
        return
    
    pass


def Polyline_UI_helper: #k super? should provide helper methods for this kind of component
        # (one which adds data editing ops for use by a graphical UI)
    """
    methods for editing polylines for use by a graphical UI
    """
    data = Arg(Polyline, doc = "the Polyline we help to edit") #e rename to self.polyline?

    def addControlPoint(self, pointType): #k not sure if we need this, but it's like addSegment below...
        # note that it takes the type, not the object! because we know it's new...
        # but it's not really a type, it's a description, since it has all the data as well. ### RENAME the arg!
        ## point = pointType() ###k ?? no, the container needs to make it, from the description... or is it an expr with code? HMM #####
        point = self.data.makeControlPoint(pointType)
            # note: this implem is generic for things that can instantiate descriptions,
            # except for knowing to call makeControlPoint rather than make...
            # which differs from make in having defaults suitable for self.data.ControlPointType
        self.data.addControlPoint(point)
        
    def addSegment(self, fromPoint, toPoint, segmentType):
            # note: this is sort of like self.make(segmentType(fromPoint, toPoint))
            # if we imagine that those descriptions (in the arg) carried enough info
            # for us to know their roles in self.
        """
        Add a new segment of type Line from fromPoint to point toPoint,
        each of which might be either an existing Point object in self
        or a description of a new one we should create
        (e.g. as coords and ref object or frame).
        """
        ## fromPoint = self.canonicalizePoint(fromPoint)
            #e rename: find or make? this adds the points if needed. # Note re choosing the name:
            # it is a purely UI method -- the only reason to not know, here, if it's an existing or new point,
            # is that we had user mouse position data, then we saw if user was hovering over an existing point,
            # and if so passed that point, else the mouse position.
            # (So should the caller turn the posn into a new point, for clarity?
            #  maybe only the caller knows the point type, whether that's ok given what's near, etc?
            #  YES, make caller do that, thus we comment this out.)
        ## toPoint = self.canonicalizePoint(toPoint)
        line = segmentType(fromPoint, toPoint)
            ###k? old code said self.Line... self.Line is a type and constructor for whatever we use as a line...
            # but does this method care whether the points are in the same ref object? no, it does not require that.
        self.data.addSegment(line) # the more fundamental method; so self.data is our polyline data, not self! ###k
        return
    def 

# now bring in code from:
# - my polyline drawing eg code -- it can add lines or sketched curves
#   for the latter, add the angle cond from squeak --
#   or is that part of separate UI class for a stroke? yes, it is... in this code
#   just say: collect a stroke from the drag, give me the points to be drawing
#   (if we want to optim, give me the permanent and tentative ones seply, and give permanent ones incrly)
#   (so my stroke-drawing code can optim for a stroke being built up, by making a displist tree...)

# - my scratch code for drawing this with its construction lines, in xor mode

# - if i like this way of splitting up classes, then split the file and make separate files

# conclusions:
# - yes, do it like this, keep this (at least as scratch to make clean & real)
#   - want separate classes
#   - want formulae
#   - want types
# - maybe it's more like a sketch than a line... as you added sketch elements, they might share one set of control points,
#   and those might be kept by the sketch in per-ref-object sets for efficiency.
#   so one sketch element (entity) might then refer to or own various sketch primitives including points and segments.
#   So this object here is really more like the sketch itself.
#   (But do sketches share points between them? No -- if you want that, promote those points to ReferencePoints outside the sketch.)
# - note we'll have folding paths, etc, in future, related to this code
#   - note they're like sketches in being able to have disconected pieces, other things in them, etc
#   - and fancier -- tags on the elements, etc
#   - they'd make good use of using generic helper objects but with more specific implem and UI classes for those obj's components.
#     (eg a graph but of a specific kind of points)