# In various places we consider points in the fundamental domain # of a cromulent surface, which may be permitted to move. # Some points may be constrained to lie on one of the four sides # of the domain, which are the curves C[0], C[1], C[3] and C[5]. # Other points may be constrained to lie at one of the four # corners, which are v[0], v[3], v[6] and v[11]. We use numerical # codes for these cases, as follows: #@ CONSTRAINT CONSTRAINT["FREE"] := 0: CONSTRAINT["C1"] := 2: CONSTRAINT["C3"] := 4: CONSTRAINT["C5"] := 5: CONSTRAINT["C0"] := 8: CONSTRAINT["FIXED"] := 15: CONSTRAINT["V0"] := 15: CONSTRAINT["V3"] := 31: CONSTRAINT["V6"] := 47: CONSTRAINT["V11"] := 63: # The following block sets things up so that constraint_name[31] # (for example) is the string "CONSTRAINT_V3". #@ constraint_name constraint_name := table(): proc() local i,n; global constraint_name; for i in map(op,[indices(CONSTRAINT)]) do n := cat("CONSTRAINT_",i); assign(convert(n,name),CONSTRAINT[i]); constraint_name[CONSTRAINT[i]] := i; od: end(): #@ curve_index_by_constraint curve_index_by_constraint := table(): curve_index_by_constraint[CONSTRAINT_FREE] := NULL: curve_index_by_constraint[CONSTRAINT_C1] := 1: curve_index_by_constraint[CONSTRAINT_C3] := 3: curve_index_by_constraint[CONSTRAINT_C5] := 5: curve_index_by_constraint[CONSTRAINT_C0] := 0: curve_index_by_constraint[CONSTRAINT_FIXED] := NULL: curve_index_by_constraint[CONSTRAINT_V0] := NULL: curve_index_by_constraint[CONSTRAINT_V3] := NULL: curve_index_by_constraint[CONSTRAINT_V6] := NULL: curve_index_by_constraint[CONSTRAINT_V11] := NULL: #@ constraint_colour constraint_colour := table(): constraint_colour[CONSTRAINT_FREE] := black: constraint_colour[CONSTRAINT_C1] := c_colour[1]: constraint_colour[CONSTRAINT_C3] := c_colour[3]: constraint_colour[CONSTRAINT_C5] := c_colour[5]: constraint_colour[CONSTRAINT_C0] := c_colour[0]: constraint_colour[CONSTRAINT_FIXED] := black: constraint_colour[CONSTRAINT_V0] := black: constraint_colour[CONSTRAINT_V3] := black: constraint_colour[CONSTRAINT_V6] := black: constraint_colour[CONSTRAINT_V11] := black: #@ constraint_table constraint_table := [ [CONSTRAINT_V6,CONSTRAINT_C1,CONSTRAINT_V0], [CONSTRAINT_C0,CONSTRAINT_FREE,CONSTRAINT_C5], [CONSTRAINT_V3,CONSTRAINT_C3,CONSTRAINT_V11] ]: #@ constraint_for_square constraint_for_square := proc(x,y) local i,j; i := `if`(x = 0,1,`if`(x = 1,3,2)); j := `if`(y = 0,1,`if`(y = 1,3,2)); return constraint_table[j][i]; end: ###################################################################### #@ CLASS: domain `Class/Declare`("domain", "An instance represents the fundamental domain in a cromulent surface", ["Field","type"::string = "abstract", "A string describing the type of domain (e.g. @E@ for a member of the embedded family)" ], ["Field","dim"::posint, "All domains are expected to be subsets of $\\mathbb{R}^d$ for some integer $d$, stored in this field." ], ["Field","point_class_name", "Points in the domain will be represented by instances of a subclass of the abstract class @domain_point@. The name of the relevant subclass is stored in this field, and the table representing the subclass is stored in the @point_class@ field. Both fields should be set using the @set_point_class@ method. Analogous comments apply to the fields @edge_class_name@, @edge_class@, @face_class_name@, @face_class@, @grid_class_name@ and @grid_class@." ], ["Field","point_class", "" ], ["Field","edge_class_name"], ["Field","edge_class"], ["Field","face_class_name"], ["Field","face_class"], ["Field","grid_class_name"], ["Field","grid_class"], ["Constructor","", proc(this) this["point_class_name"] := "domain_point"; this["edge_class_name" ] := "domain_edge"; this["face_class_name"] := "domain_face"; this["grid_class_name"] := "domain_grid"; this["point_class"] := eval(`class/domain_point`); this["edge_class" ] := eval(`class/domain_edge`); this["face_class"] := eval(`class/domain_face`); this["grid_class"] := eval(`class/domain_grid`); end ], ["Method","set_point_class"::void,"", proc(this,classname::string) this["point_class_name"] := classname; this["point_class"] := eval(convert(cat("class/",classname),name)); NULL; end ], ["Method","set_edge_class"::void,"", proc(this,classname::string) this["edge_class_name"] := classname; this["edge_class"] := eval(convert(cat("class/",classname),name)); NULL; end ], ["Method","set_face_class"::void,"", proc(this,classname::string) this["face_class_name"] := classname; this["face_class"] := eval(convert(cat("class/",classname),name)); NULL; end ], ["Method","set_grid_class"::void,"", proc(this,classname::string) this["grid_class_name"] := classname; this["grid_class"] := eval(convert(cat("class/",classname),name)); NULL; end ], ["Method","new_point"::void, "This method returns a new instance of the relevant point class.", proc(this) eval(this["point_class"]["FullConstructor"]()); end ], ["Method","new_edge"::void, "This method returns a new instance of the relevant edge class.", proc(this,P0,P1) eval(this["edge_class"]["FullConstructor"](P0,P1)); end ], ["Method","new_face"::void, "This method returns a new instance of the relevant face class.", proc(this,S0,S1,S2,s_) eval(this["face_class"]["FullConstructor"](args[2..-1])); end ], ["Method","new_grid"::void, "This method returns a new instance of the relevant grid class.", proc(this) local G; G := eval(this["grid_class"]["FullConstructor"]()); G["domain"] := eval(this); return eval(G); end ], NULL );