aboutsummaryrefslogtreecommitdiff
path: root/src/algebra/space.spad.pamphlet
blob: 6d688e479b6f758c7f9919e4235a6e40273dd8a8 (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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
\documentclass{article}
\usepackage{open-axiom}
\begin{document}
\title{\$SPAD/src/algebra space.spad}
\author{The Axiom Team}
\maketitle
\begin{abstract}
\end{abstract}
\eject
\tableofcontents
\eject
\section{category SPACEC ThreeSpaceCategory}
<<category SPACEC ThreeSpaceCategory>>=
)abbrev category SPACEC ThreeSpaceCategory
++ Author: 
++ Date Created: 
++ Date Last Updated:
++ Basic Operations: create3Space, numberOfComponents, numberOfComposites,
++ merge, composite, components, copy, enterPointData, modifyPointData, point,
++ point?, curve, curve?, closedCurve, closedCurve?, polygon, polygon? mesh,
++ mesh?, lp, lllip, lllp, llprop, lprop, objects, check, subspace, coerce
++ Related Constructors:
++ Also See:
++ AMS Classifications:
++ Keywords: 
++ References:
++ Description: The category ThreeSpaceCategory is used for creating 
++ three dimensional objects using functions for defining points, curves, 
++ polygons, constructs and the subspaces containing them.

ThreeSpaceCategory(R:Ring): Exports == Implementation where
 I    ==> Integer
 PI   ==> PositiveInteger
 NNI  ==> NonNegativeInteger
 L    ==> List
 B    ==> Boolean
 O    ==> OutputForm
 SUBSPACE ==> SubSpace(3,R)
 POINT   ==> Point(R)
 PROP    ==> SubSpaceComponentProperty()
 REP3D   ==> Record(lp:L POINT,llliPt:L L L NNI, llProp:L L PROP, lProp:L PROP)
 OBJ3D   ==> Record(points:NNI, curves:NNI, polygons:NNI, constructs:NNI)

 Exports ==> Category
 Implementation ==>
  SetCategory with
    create3Space : () -> %
      ++ create3Space() creates a \spadtype{ThreeSpace} object capable of 
      ++ holding point, curve, mesh components and any combination.
    create3Space : SUBSPACE -> %
      ++ create3Space(s) creates a \spadtype{ThreeSpace} object containing
      ++ objects pre-defined within some \spadtype{SubSpace} s.
    numberOfComponents : % -> NNI
      ++ numberOfComponents(s) returns the number of distinct
      ++ object components in the indicated \spadtype{ThreeSpace}, s, such
      ++ as points, curves, polygons, and constructs.
    numberOfComposites : % -> NNI
      ++ numberOfComposites(s) returns the number of supercomponents,
      ++ or composites, in the \spadtype{ThreeSpace}, s; Composites are 
      ++ arbitrary groupings of otherwise distinct and unrelated components;
      ++ A \spadtype{ThreeSpace} need not have any composites defined at all
      ++ and, outside of the requirement that no component can belong
      ++ to more than one composite at a time, the definition and
      ++ interpretation of composites are unrestricted.
    merge : L % -> %
      ++ merge([s1,s2,...,sn]) will create a new \spadtype{ThreeSpace} that has 
      ++ the components of all the ones in the list; Groupings of components
      ++ into composites are maintained.
    merge : (%,%) -> %
      ++ merge(s1,s2) will create a new \spadtype{ThreeSpace} that has the
      ++ components of \spad{s1} and \spad{s2}; Groupings of components
      ++ into composites are maintained.
    composite : L % -> %
      ++ composite([s1,s2,...,sn]) will create a new \spadtype{ThreeSpace} that 
      ++ is a union of all the components from each \spadtype{ThreeSpace} in 
      ++ the parameter list, grouped as a composite.
    components : % -> L %
      ++ components(s) takes the \spadtype{ThreeSpace} s, and creates a list 
      ++ containing a unique \spadtype{ThreeSpace} for each single component 
      ++ of s. If s has no components defined, the list returned is empty.
    composites : % -> L %
      ++ composites(s) takes the \spadtype{ThreeSpace} s, and creates a list 
      ++ containing a unique \spadtype{ThreeSpace} for each single composite 
      ++ of s. If s has no composites defined (composites need to be explicitly 
      ++ created), the list returned is empty. Note that not all the components
      ++ need to be part of a composite.
    copy : % -> %
      ++ copy(s) returns a new \spadtype{ThreeSpace} that is an exact copy of s.
    enterPointData  : (%,L POINT) -> NNI
      ++ enterPointData(s,[p0,p1,...,pn]) adds a list of points from p0 through
      ++ pn to the \spadtype{ThreeSpace}, s, and returns the index, to the 
      ++ starting point of the list;
    modifyPointData : (%,NNI,POINT) -> %
      ++ modifyPointData(s,i,p) changes the point at the indexed 
      ++ location i in the \spadtype{ThreeSpace}, s, to that of point p.
      ++ This is useful for making changes to a point which has been 
      ++ transformed.

    -- 3D primitives
    point        : (%,POINT) -> %
      ++ point(s,p) adds a point component defined by the point, p, specified as
      ++ a list from \spad{List(R)}, to the \spadtype{ThreeSpace}, s,
      ++ where R is the \spadtype{Ring} over which the point is defined.
    point        : (%,L R) -> %
      ++ point(s,[x,y,z]) adds a point component defined by a list of elements 
      ++ which are from the \spad{PointDomain(R)} to the \spadtype{ThreeSpace},
      ++ s, where R is the \spadtype{Ring} over which the point elements are 
      ++ defined.
    point        : (%,NNI) -> %
      ++ point(s,i) adds a point component which is placed into a component
      ++ list of the \spadtype{ThreeSpace}, s, at the index given by i.
    point        : POINT -> %  
      ++ point(p) returns a \spadtype{ThreeSpace} object which is composed of 
      ++ one component, the point p.
    point        : % -> POINT
      ++ point(s) checks to see if the \spadtype{ThreeSpace}, s, is composed of
      ++ only a single point and if so, returns the point. An error
      ++ is signaled otherwise.
    point?       : % -> B
      ++ point?(s) queries whether the \spadtype{ThreeSpace}, s, is composed of
      ++ a single component which is a point and returns the boolean result.
    curve        : (%,L POINT) -> %
      ++ curve(s,[p0,p1,...,pn]) adds a space curve component defined by a 
      ++ list of points \spad{p0} through \spad{pn}, to the \spadtype{ThreeSpace} s.
    curve        : (%,L L R) -> %
      ++ curve(s,[[p0],[p1],...,[pn]]) adds a space curve which is a list of 
      ++ points p0 through pn defined by lists of elements from the domain 
      ++ \spad{PointDomain(m,R)}, where R is the \spadtype{Ring} over which the
      ++ point elements are defined and m is the dimension of the points, to 
      ++ the \spadtype{ThreeSpace} s.
    curve         : L POINT -> %
      ++ curve([p0,p1,p2,...,pn]) creates a space curve defined
      ++ by the list of points \spad{p0} through \spad{pn}, and returns the 
      ++ \spadtype{ThreeSpace} whose component is the curve.
    curve         : % -> L POINT
      ++ curve(s) checks to see if the \spadtype{ThreeSpace}, s, is composed of
      ++ a single curve defined by a list of points and if so, returns the 
      ++ curve, i.e., list of points. An error is signaled otherwise.
    curve?        : % -> B
      ++ curve?(s) queries whether the \spadtype{ThreeSpace}, s, is a curve, 
      ++ i.e., has one component, a list of list of points, and returns true if
      ++ it is, or false otherwise.
    closedCurve  : (%,L POINT) -> %
      ++ closedCurve(s,[p0,p1,...,pn,p0]) adds a closed curve component which is
      ++ a list of points defined by the first element p0 through the last 
      ++ element pn and back to the first element p0 again, to the 
      ++ \spadtype{ThreeSpace} s.
    closedCurve  : (%,L L R) -> %
      ++ closedCurve(s,[[lr0],[lr1],...,[lrn],[lr0]]) adds a closed curve 
      ++ component defined by a list of points \spad{lr0} through \spad{lrn}, 
      ++ which are lists of elements from the domain \spad{PointDomain(m,R)}, 
      ++ where R is the \spadtype{Ring} over which the point elements are 
      ++ defined and m is the dimension of the points, in which the last element
      ++ of the list of points contains a copy of the first element list, lr0.
      ++ The closed curve is added to the \spadtype{ThreeSpace}, s.
    closedCurve         : L POINT -> %
      ++ closedCurve(lp) sets a list of points defined by the first element
      ++ of lp through the last element of lp and back to the first elelment
      ++ again and returns a \spadtype{ThreeSpace} whose component is the
      ++ closed curve defined by lp.
    closedCurve         : % -> L POINT
      ++ closedCurve(s) checks to see if the \spadtype{ThreeSpace}, s, is 
      ++ composed of a single closed curve component defined by a list of 
      ++ points in which the first point is also the last point, all of which 
      ++ are from the domain \spad{PointDomain(m,R)} and if so, returns the 
      ++ list of points.  An error is signaled otherwise.
    closedCurve?        : % -> B
      ++ closedCurve?(s) returns true if the \spadtype{ThreeSpace} s contains 
      ++ a single closed curve component, i.e., the first element of the curve 
      ++ is also the last element, or false otherwise.
    polygon      : (%,L POINT) -> %
      ++ polygon(s,[p0,p1,...,pn]) adds a polygon component defined by a list of 
      ++ points, p0 throught pn, to the \spadtype{ThreeSpace} s.
    polygon      : (%,L L R) -> %
      ++ polygon(s,[[r0],[r1],...,[rn]]) adds a polygon component defined
      ++ by a list of points \spad{r0} through \spad{rn}, which are lists of
      ++ elements from the domain \spad{PointDomain(m,R)} to the 
      ++ \spadtype{ThreeSpace} s, where m is the dimension of the points
      ++ and R is the \spadtype{Ring} over which the points are defined.
    polygon         : L POINT -> %
      ++ polygon([p0,p1,...,pn]) creates a polygon defined by a list of points,
      ++ p0 through pn, and returns a \spadtype{ThreeSpace} whose component
      ++ is the polygon.
    polygon         : % -> L POINT
      ++ polygon(s) checks to see if the \spadtype{ThreeSpace}, s, is 
      ++ composed of a single polygon component defined by a list of 
      ++ points, and if so, returns the list of points;  An error is signaled 
      ++ otherwise.
    polygon?        : % -> B
      ++ polygon?(s) returns true if the \spadtype{ThreeSpace} s contains 
      ++ a single polygon component, or false otherwise.
    mesh         : (%,L L POINT,L PROP,PROP) -> %
      ++ mesh(s,[[p0],[p1],...,[pn]],[props],prop) adds a surface component, 
      ++ defined over a list curves which contains lists of points, to the 
      ++ \spadtype{ThreeSpace} s; props is a list which contains the subspace 
      ++ component properties for each surface parameter, and prop is the 
      ++ subspace component property by which the points are defined.
    mesh         : (%,L L L R,L PROP,PROP) -> %
      ++ mesh(s,[ [[r10]...,[r1m]], [[r20]...,[r2m]],..., [[rn0]...,[rnm]] ], [props], prop)
      ++ adds a surface component to the \spadtype{ThreeSpace} s, which is 
      ++ defined over a rectangular domain of size WxH where W is the number 
      ++ of lists of points from the domain \spad{PointDomain(R)} and H is the 
      ++ number of elements in each of those lists; lprops is the list of the 
      ++ subspace component properties for each curve list, and prop is 
      ++ the subspace component property by which the points are defined.
    mesh         : (%,L L POINT,B,B) -> %
      ++ mesh(s,[[p0],[p1],...,[pn]], close1, close2) adds a surface component to
      ++ the \spadtype{ThreeSpace}, which is defined over a list of curves,
      ++ in which each of these curves is a list of points. 
      ++ The boolean arguments close1 and close2 indicate how the surface 
      ++ is to be closed. Argument close1 equal true
      ++ means that each individual list (a curve) is to be closed, i.e. the 
      ++ last point of the list is to be connected to the first point.
      ++ Argument close2 equal true 
      ++ means that the boundary at one end of the surface is to be
      ++ connected to the boundary at the other end, i.e. the boundaries 
      ++ are defined as the first list of points (curve) and 
      ++ the last list of points (curve).
    mesh         : (%,L L L R,B,B) -> %
      ++ mesh(s,[ [[r10]...,[r1m]], [[r20]...,[r2m]],..., [[rn0]...,[rnm]] ], close1, close2)
      ++ adds a surface component to the \spadtype{ThreeSpace} s, which is 
      ++ defined over a rectangular domain of size WxH where W is the number 
      ++ of lists of points from the domain \spad{PointDomain(R)} and H is the 
      ++ number of elements in each of those lists; the booleans close1 and 
      ++ close2 indicate how the surface is to be closed: if close1 is true 
      ++ this means that each individual list (a curve) is to be closed (i.e., 
      ++ the last point of the list is to be connected to the first point);
      ++ if close2 is true, this means that the boundary at one end of the
      ++ surface is to be connected to the boundary at the other end
      ++ (the boundaries are defined as the first list of points (curve)
      ++ and the last list of points (curve)).
    mesh         : L L POINT -> %
      ++ mesh([[p0],[p1],...,[pn]]) creates a surface defined by a list of 
      ++ curves which are lists, p0 through pn, of points, and returns a 
      ++ \spadtype{ThreeSpace} whose component is the surface.
    mesh         : (L L POINT,B,B) -> %
      ++ mesh([[p0],[p1],...,[pn]], close1, close2) creates a surface defined 
      ++ over a list of curves, p0 through pn, which are lists of points;
      ++ the booleans close1 and close2 indicate how the surface is to be 
      ++ closed: close1 set to true means that each individual list (a curve) 
      ++ is to be closed (that is, the last point of the list is to be 
      ++ connected to the first point); close2 set to true means that the 
      ++ boundary at one end of the surface is to be connected to the boundary
      ++ at the other end (the boundaries are defined as the first list of 
      ++ points (curve) and the last list of points (curve)); the
      ++ \spadtype{ThreeSpace} containing this surface is returned.
    mesh         : % -> L L POINT
      ++ mesh(s) checks to see if the \spadtype{ThreeSpace}, s, is 
      ++ composed of a single surface component defined by a list curves which
      ++ contain lists of points, and if so, returns the list of lists of 
      ++ points;  An error is signaled otherwise.
    mesh?        : % -> B
      ++ mesh?(s) returns true if the \spadtype{ThreeSpace} s is composed of one
      ++ component, a mesh comprising a list of curves which are lists
      ++ of points, or returns false if otherwise
    lp           : % -> L POINT
      ++ lp(s) returns the list of points component which the 
      ++ \spadtype{ThreeSpace}, s, contains; these points are used by reference,
      ++ i.e., the component holds indices referring to the points rather
      ++ than the points themselves. This allows for sharing of the points.
    lllip        : % -> L L L NNI
      ++ lllip(s) checks to see if the \spadtype{ThreeSpace}, s, is 
      ++ composed of a list of components, which are lists of curves, 
      ++ which are lists of indices to points, and if so, returns the list of 
      ++ lists of lists;  An error is signaled otherwise.
    lllp         : % -> L L L POINT   -- used by view3D
      ++ lllp(s) checks to see if the \spadtype{ThreeSpace}, s, is 
      ++ composed of a list of components, which are lists of curves, 
      ++ which are lists of points, and if so, returns the list of 
      ++ lists of lists;  An error is signaled otherwise.
    llprop       : % -> L L PROP      -- used by view3D
      ++ llprop(s) checks to see if the \spadtype{ThreeSpace}, s, is 
      ++ composed of a list of curves which are lists of the
      ++ subspace component properties of the curves, and if so, returns the 
      ++ list of lists;  An error is signaled otherwise.
    lprop        : % -> L PROP        -- used by view3D
      ++ lprop(s) checks to see if the \spadtype{ThreeSpace}, s, is 
      ++ composed of a list of subspace component properties, and if so, 
      ++ returns the list;  An error is signaled otherwise.
    objects      : % -> OBJ3D
      ++ objects(s) returns the \spadtype{ThreeSpace}, s, in the form of a 
      ++ 3D object record containing information on the number of points, 
      ++ curves, polygons and constructs comprising the \spadtype{ThreeSpace}..
    check        : % -> %             -- used by mesh
      ++ check(s) returns lllpt, list of lists of lists of point information 
      ++ about the \spadtype{ThreeSpace} s.
    subspace     : % -> SUBSPACE
      ++ subspace(s) returns the \spadtype{SubSpace} which holds all the point
      ++ information in the \spadtype{ThreeSpace}, s.
    coerce       : % -> O
      ++ coerce(s) returns the \spadtype{ThreeSpace} s to Output format.

@
\section{domain SPACE3 ThreeSpace}
<<domain SPACE3 ThreeSpace>>=
)abbrev domain SPACE3 ThreeSpace
++ Author: 
++ Date Created: 
++ Date Last Updated:
++ Basic Operations: create3Space, numberOfComponents, numberOfComposites,
++ merge, composite, components, copy, enterPointData, modifyPointData, point,
++ point?, curve, curve?, closedCurve, closedCurve?, polygon, polygon? mesh,
++ mesh?, lp, lllip, lllp, llprop, lprop, objects, check, subspace, coerce
++ Related Constructors:
++ Also See:
++ AMS Classifications:
++ Keywords: 
++ References:
++ Description: The domain ThreeSpace is used for creating three dimensional 
++ objects using functions for defining points, curves, polygons, constructs 
++ and the subspaces containing them.

ThreeSpace(R:Ring):Exports == Implementation where
  -- m is the dimension of the point
 
  I    ==> Integer
  PI   ==> PositiveInteger
  NNI  ==> NonNegativeInteger
  L    ==> List
  B    ==> Boolean
  O    ==> OutputForm
  SUBSPACE ==> SubSpace(3,R)
  POINT  ==> Point(R)
  PROP   ==> SubSpaceComponentProperty()
  REP3D  ==> Record(lp:L POINT,llliPt:L L L NNI, llProp:L L PROP, lProp:L PROP)
  OBJ3D  ==> Record(points:NNI, curves:NNI, polygons:NNI, constructs:NNI)

  Exports ==> ThreeSpaceCategory(R)
  Implementation ==> add
    import COMPPROP
    import POINT
    import SUBSPACE
    import ListFunctions2(List(R),POINT)
    import Set(NNI)

    Rep := Record( subspaceField:SUBSPACE, compositesField:L SUBSPACE, _
                   rep3DField:REP3D, objectsField:OBJ3D, _
                   converted:B)
 
--% Local Functions
    convertSpace : % -> %
    convertSpace space ==
      space.converted => space
      space.converted := true
      lllipt : L L L NNI := [] 
      llprop : L L PROP := []
      lprop : L PROP := []
      for component in children space.subspaceField repeat
        lprop := cons(extractProperty component,lprop)  
        tmpllipt : L L NNI := []
        tmplprop : L PROP := []
        for curve in children component repeat
          tmplprop := cons(extractProperty curve,tmplprop)
          tmplipt : L NNI := []
          for point in children curve repeat
            tmplipt := cons(extractIndex point,tmplipt)
          tmpllipt := cons(reverse! tmplipt,tmpllipt)
        llprop := cons(reverse! tmplprop, llprop)
        lllipt := cons(reverse! tmpllipt, lllipt)
      space.rep3DField := [pointData space.subspaceField, 
                           reverse! lllipt,reverse! llprop,reverse! lprop]
      space
      

--% Exported Functions
    polygon(space:%,points:L POINT) ==
      #points < 3 =>
        error "You need at least 3 points to define a polygon"
      pt := addPoint2(space.subspaceField,first points)
      points := rest points
      addPointLast(space.subspaceField, pt, first points, 1)
      for p in rest points repeat
        addPointLast(space.subspaceField, pt, p, 2)
      space.converted := false
      space
    create3Space() == [ new()$SUBSPACE, [], [ [], [], [], [] ], [0,0,0,0], false ]
    create3Space(s) == [ s, [], [ [], [], [], [] ], [0,0,0,0], false ]
    numberOfComponents(space) == #(children((space::Rep).subspaceField))
    numberOfComposites(space) == #((space::Rep).compositesField)
    merge(listOfThreeSpaces) ==
          -- * -- we may want to remove duplicate components when that functionality exists in List
      newspace := create3Space(merge([ts.subspaceField for ts in listOfThreeSpaces]))
--      newspace.compositesField := [for cs in ts.compositesField for ts in listOfThreeSpaces]
      for ts in listOfThreeSpaces repeat 
        newspace.compositesField := append(ts.compositesField,newspace.compositesField)
      newspace
    merge(s1,s2) == merge([s1,s2])
    composite(listOfThreeSpaces) ==
      space := create3Space()
      space.subspaceField := merge [s.subspaceField for s in listOfThreeSpaces]
      space.compositesField := [deepCopy space.subspaceField]
--      for aSpace in listOfThreeSpaces repeat
          -- create a composite (which are supercomponents that group
          -- separate components together) out of all possible components
--        space.compositesField := append(children aSpace.subspaceField,space.compositesField)
      space
    components(space) == [create3Space(s) for s in separate space.subspaceField]
    composites(space) == [create3Space(s) for s in space.compositesField]
    copy(space) ==
      spc := create3Space(deepCopy(space.subspaceField))
      spc.compositesField := [deepCopy s for s in space.compositesField]
      spc

    enterPointData(space,listOfPoints) ==
      for p in listOfPoints repeat
        addPoint(space.subspaceField,p)
      #(pointData space.subspaceField)
    modifyPointData(space,i,p) ==
      modifyPoint(space.subspaceField,i,p)
      space

      -- 3D primitives, each grouped in the following order
      --     xxx?(s)  : query whether the threespace, s, holds an xxx
      --     xxx(s)   : extract xxx from threespace, s
      --     xxx(p)   : create a new three space with xxx, p
      --     xxx(s,p) : add xxx, p, to a three space, s
      --     xxx(s,q) : add an xxx, convertable from q, to a three space, s
      --     xxx(s,i) : add an xxx, the data for xxx being indexed by reference  *** complete this
    point?(space:%) ==
      #(c:=children space.subspaceField) > 1$NNI => 
        error "This ThreeSpace has more than one component"
        -- our 3-space has one component, a list of list of points
      #(kid:=children first c) = 1$NNI => -- the component has one subcomponent (a list of points)
        #(children first kid) = 1$NNI  -- this list of points only has one entry, so it's a point
      false
    point(space:%) ==
      point? space => extractPoint(traverse(space.subspaceField,[1,1,1]::L NNI))
      error "This ThreeSpace holds something other than a single point - try the objects() command"
    point(aPoint:POINT) == point(create3Space(),aPoint)
    point(space:%,aPoint:POINT) ==
      addPoint(space.subspaceField,[],aPoint)
      space.converted := false
      space
    point(space:%,l:L R) ==
      pt := point(l)
      point(space,pt)
    point(space:%,i:NNI) ==
      addPoint(space.subspaceField,[],i)
      space.converted := false
      space

    curve?(space:%) ==
      #(c:=children space.subspaceField) > 1$NNI => 
        error "This ThreeSpace has more than one component"
        -- our 3-space has one component, a list of list of points
      #(children first c) = 1$NNI -- there is only one subcomponent, so it's a list of points
    curve(space:%) ==
      curve? space => 
        spc := first children first children space.subspaceField
        [extractPoint(s) for s in children spc]
      error "This ThreeSpace holds something other than a curve - try the objects() command"
    curve(points:L POINT) == curve(create3Space(),points)
    curve(space:%,points:L POINT) ==
      addPoint(space.subspaceField,[],first points)
      path : L NNI := [#(children space.subspaceField),1]
      for p in rest points repeat
        addPoint(space.subspaceField,path,p)
      space.converted := false
      space
    curve(space:%,points:L L R) ==
      pts := map(point,points)
      curve(space,pts)
      
    closedCurve?(space:%) ==
      #(c:=children space.subspaceField) > 1$NNI => 
        error "This ThreeSpace has more than one component"
        -- our 3-space has one component, a list of list of points
      #(kid := children first c) = 1$NNI => -- there is one subcomponent => it's a list of points
        extractClosed first kid   -- is it a closed curve?
      false
    closedCurve(space:%) ==
      closedCurve? space => 
        spc := first children first children space.subspaceField 
          -- get the list of points
        [extractPoint(s) for s in children spc]  
          -- for now, we are not repeating points...
      error "This ThreeSpace holds something other than a curve - try the objects() command"
    closedCurve(points:L POINT) == closedCurve(create3Space(),points)
    closedCurve(space:%,points:L POINT) ==
      addPoint(space.subspaceField,[],first points)
      path : L NNI := [#(children space.subspaceField),1]
      closeComponent(space.subspaceField,path,true)
      for p in rest points repeat
        addPoint(space.subspaceField,path,p)
      space.converted := false
      space
    closedCurve(space:%,points:L L R) ==
      pts := map(point,points)
      closedCurve(space,pts)

    polygon?(space:%) ==
      #(c:=children space.subspaceField) > 1$NNI => 
        error "This ThreeSpace has more than one component"
        -- our 3-space has one component, a list of list of points
      #(kid:=children first c) = 2::NNI => 
          -- there are two subcomponents
          -- the convention is to have one point in the first child and to put 
          -- the remaining points (2 or more) in the second, and last, child
        #(children first kid) = 1$NNI and #(children second kid) > 2::NNI
      false  -- => returns Void...?
    polygon(space:%) ==
      polygon? space =>
        listOfPoints : L POINT := 
          [extractPoint(first children first (cs := children first children space.subspaceField))]
        [extractPoint(s) for s in children second cs]
      error "This ThreeSpace holds something other than a polygon - try the objects() command"
    polygon(points:L POINT) == polygon(create3Space(),points)
    polygon(space:%,points:L L R) ==
      pts := map(point,points)
      polygon(space,pts) 

    mesh?(space:%) ==
      #(c:=children space.subspaceField) > 1$NNI => 
        error "This ThreeSpace has more than one component"
        -- our 3-space has one component, a list of list of points
      #(kid:=children first c) > 1$NNI => 
          -- there are two or more subcomponents (list of points)
          -- so this may be a definition of a mesh; if the size
          -- of each list of points is the same and they are all
          -- greater than 1(?) then we have an acceptable mesh
          -- use a set to hold the curve size info: if heterogenous
          -- curve sizes exist, then the set would hold all the sizes;
          -- otherwise it would just have the one element indicating
          -- the sizes for all the curves
          whatSizes := brace()$Set(NNI)
          for eachCurve in kid repeat
            insert!(#children eachCurve,whatSizes)
          #whatSizes > 1 => error "Mesh defined with curves of different sizes"
          first parts whatSizes < 2 => 
            error "Mesh defined with single point curves (use curve())"
          true
      false
    mesh(space:%) ==
      mesh? space =>
        llp : L L POINT := []
        for lpSpace in children first children space.subspaceField repeat
          llp := cons([extractPoint(s) for s in children lpSpace],llp)
        llp
      error "This ThreeSpace holds something other than a mesh - try the objects() command"
    mesh(points:L L POINT) == mesh(create3Space(),points,false,false)
    mesh(points:L L POINT,prop1:B,prop2:B) == mesh(create3Space(),points,prop1,prop2)
--+ old ones \/
    mesh(space:%,llpoints:L L L R,lprops:L PROP,prop:PROP) ==
      pts := [map(point,points) for points in llpoints]
      mesh(space,pts,lprops,prop)
    mesh(space:%,llp:L L POINT,lprops:L PROP,prop:PROP) ==
      addPoint(space.subspaceField,[],first first llp)
      defineProperty(space.subspaceField,path:L NNI:=[#children space.subspaceField],prop)
      path := append(path,[1])
      defineProperty(space.subspaceField,path,first lprops)
      for p in rest (first llp) repeat
        addPoint(space.subspaceField,path,p)
      for lp in rest llp for aProp in rest lprops for count in 2.. repeat
        addPoint(space.subspaceField,path := [first path],first lp)
        path := append(path,[count])
        defineProperty(space.subspaceField,path,aProp)
        for p in rest lp repeat
          addPoint(space.subspaceField,path,p)
      space.converted := false
      space
--+ old ones /\
    mesh(space:%,llpoints:L L L R,prop1:B,prop2:B) ==
      pts := [map(point,points) for points in llpoints]
      mesh(space,pts,prop1,prop2)
    mesh(space:%,llp:L L POINT,prop1:B,prop2:B) ==
        -- prop2 refers to property of the ends of a surface (list of lists of points)
        -- while prop1 refers to the individual curves (list of points)
        -- ** note we currently use Booleans for closed (rather than a pair
        -- ** of booleans for closed and solid)
      propA : PROP := new()
      close(propA,prop1)
      propB : PROP := new()
      close(propB,prop2)
      addPoint(space.subspaceField,[],first first llp)
      defineProperty(space.subspaceField,path:L NNI:=[#children space.subspaceField],propB)
      path := append(path,[1])
      defineProperty(space.subspaceField,path,propA)
      for p in rest (first llp) repeat
        addPoint(space.subspaceField,path,p)
      for lp in rest llp for count in 2.. repeat
        addPoint(space.subspaceField,path := [first path],first lp)
        path := append(path,[count])
        defineProperty(space.subspaceField,path,propA)
        for p in rest lp repeat
          addPoint(space.subspaceField,path,p)
      space.converted := false
      space

    lp space ==
      if not space.converted then space := convertSpace space 
      space.rep3DField.lp
    lllip space   == 
      if not space.converted then space := convertSpace space 
      space.rep3DField.llliPt
--    lllp space   == 
--      if not space.converted then space := convertSpace space 
--      space.rep3DField.lllPt
    llprop space == 
      if not space.converted then space := convertSpace space 
      space.rep3DField.llProp
    lprop space  == 
      if not space.converted then space := convertSpace space 
      space.rep3DField.lProp

      -- this function is just to see how this representation really
      -- does work
    objects space ==
      if not space.converted then space := convertSpace space 
      numPts        := 0$NNI
      numCurves     := 0$NNI
      numPolys      := 0$NNI
      numConstructs := 0$NNI
      for component in children space.subspaceField repeat
        #(kid:=children component) = 1 =>
          #(children first kid) = 1 => numPts := numPts + 1
          numCurves := numCurves + 1
        (#kid = 2) and _
          (#children first kid = 1) and _
          (#children first rest kid ~= 1) =>
             numPolys := numPolys + 1
        numConstructs := numConstructs + 1
        -- otherwise, a mathematical surface is assumed
        -- there could also be garbage representation
        -- since there are always more permutations that
        -- we could ever want, so the user should not
        -- fumble around too much with the structure
        -- as other applications need to interpret it
      [numPts,numCurves,numPolys,numConstructs]

    check(s) ==
      not s.converted => convertSpace s
      s

    subspace(s) == s.subspaceField

    coerce(s) == 
      if not s.converted then s := convertSpace s
      hconcat(["3-Space with "::O, _
               (sizo:=#(s.rep3DField.llliPt))::O, _
               (sizo=1=>" component"::O;" components"::O)])

@
\section{package TOPSP TopLevelThreeSpace}
<<package TOPSP TopLevelThreeSpace>>=
)abbrev package TOPSP TopLevelThreeSpace
++ Description:
++ This package exports a function for making a \spadtype{ThreeSpace}
TopLevelThreeSpace(): with
    createThreeSpace: () -> ThreeSpace DoubleFloat
      ++ createThreeSpace() creates a \spadtype{ThreeSpace(DoubleFloat)} object 
      ++ capable of holding point, curve, mesh components and any combination.
  == add
    createThreeSpace() == create3Space()$ThreeSpace(DoubleFloat)

@
\section{License}
<<license>>=
--Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
--All rights reserved.
--
--Redistribution and use in source and binary forms, with or without
--modification, are permitted provided that the following conditions are
--met:
--
--    - Redistributions of source code must retain the above copyright
--      notice, this list of conditions and the following disclaimer.
--
--    - Redistributions in binary form must reproduce the above copyright
--      notice, this list of conditions and the following disclaimer in
--      the documentation and/or other materials provided with the
--      distribution.
--
--    - Neither the name of The Numerical ALgorithms Group Ltd. nor the
--      names of its contributors may be used to endorse or promote products
--      derived from this software without specific prior written permission.
--
--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
--IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
--TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
--PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
--OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
--EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
--PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
--PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
--LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
--NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
--SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@
<<*>>=
<<license>>

<<category SPACEC ThreeSpaceCategory>>
<<domain SPACE3 ThreeSpace>>
<<package TOPSP TopLevelThreeSpace>>
@
\eject
\begin{thebibliography}{99}
\bibitem{1} nothing
\end{thebibliography}
\end{document}