
def rule_subdivision_SubdivideLoop():
	def fun_n1_pos(context):
		return Point3.middle(context.gmap[context.leftdart].ebd123["pos"], n0@0.pos)
	def fun_n1_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	def fun_n2_orient(context):
		return context.gmap[context.leftdart].ebd["orient"]
	def fun_n3_color(context):
		return Color4.randomColor()
	def fun_n3_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	def fun_n3_normal(context):
		return context.gmap[context.leftdart].ebd01["normal"]
	expr_n1_pos = Expr3DEbd123("pos",fun_n1_pos)
	expr_n1_orient = Expr3DEbdDart("orient",fun_n1_orient)
	expr_n2_orient = Expr3DEbdDart("orient",fun_n2_orient)
	expr_n3_color = Expr3DEbd01("color",fun_n3_color)
	expr_n3_orient = Expr3DEbdDart("orient",fun_n3_orient)
	expr_n3_normal = Expr3DEbd01("normal",fun_n3_normal)
	rule = Rule3D("SubdivideLoop","subdivision")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [0,1,2], True)
	rule.linkLeftNodes(3,ln0,ln0)
	# motif droit 
	rn0 = rule.make_rightnode("n0", [-1,1,2])
	rn1 = rule.make_rightnode("n1", [-1,-1,2],[expr_n1_pos,expr_n1_orient])
	rn2 = rule.make_rightnode("n2", [-1,0,-1],[expr_n2_orient,expr_n1_pos])
	rn3 = rule.make_rightnode("n3", [1,0,-1],[expr_n3_color,expr_n3_orient,expr_n3_normal,expr_n1_pos])
	rule.linkRightNodes(0,rn0,rn1)
	rule.linkRightNodes(1,rn1,rn2)
	rule.linkRightNodes(2,rn2,rn3)
	rule.linkRightNodes(3,rn0,rn0)
	rule.linkRightNodes(3,rn1,rn1)
	rule.linkRightNodes(3,rn2,rn2)
	rule.linkRightNodes(3,rn3,rn3)
	rule.compile()
	return rule

def rule_subdivision_SubdivideCatmullClark():
	def fun_n0_pos(context):
		Point3 old_coord =  Point3(context.gmap[context.leftdart].ebd123["pos"])
		int n_faces = 0
		Point3 avg_face_poss =  Point3()
		for(JerboaDart dart : <1,2,3>_<0,1>(n0)) {
		    Point3 mid = Point3.middle(<0,1>_<0>(dart),"pos")
		    avg_face_poss.add(mid)
		    n_faces++
		}
		avg_face_poss.scale(1.0 / n_faces)
		
		Point3 avg_edge_poss =  Point3()
		int n_edges = 0
		for(JerboaDart dart : <1,2,3>_<2,3>(n0)) {
		    Point3 edgeMid = Point3.middle(<0>_pos(dart))
		    Point3 face1Mid = Point3.middle(<0,1>_pos(dart))
		    Point3 face2Mid = Point3.middle(<0,1>_pos(dart@2))
		    edgeMid.add(face1Mid)
		    edgeMid.add(face2Mid)
		    edgeMid.scale(1.0 / 3.0)
		    avg_edge_poss.add(edgeMid)
		    n_edges++
		}
		avg_edge_poss.scale(1.0 / n_edges)
		double m1 = (n_faces - 3.0) / n_faces
		double m2 = 1.0 / n_faces
		double m3 = 2.0 / n_faces
		old_coord.scale(m1)
		avg_face_poss.scale(m2)
		avg_edge_poss.scale(m3)
		old_coord.add(avg_face_poss)
		old_coord.add(avg_edge_poss)
		return old_coord
		
	def fun_n1_pos(context):
		Point3 edgeMid = Point3.middle(context.gmap[context.leftdart].ebd123["pos"], n0@0.pos)
		Point3 face1Mid = Point3.middle(<0,1>_pos(n0))
		Point3 face2Mid = Point3.middle(<0,1>_pos(n0@2))
		edgeMid.add(face1Mid)
		edgeMid.add(face2Mid)
		edgeMid.scale(1.0 / 3.0)
		
		return edgeMid
	def fun_n1_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	def fun_n2_orient(context):
		return context.gmap[context.leftdart].ebd["orient"]
	def fun_n3_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	def fun_n3_pos(context):
		return Point3.middle(<0,1>_pos(n0))
	expr_n0_pos = Expr3DEbd123("pos",fun_n0_pos)
	expr_n1_pos = Expr3DEbd123("pos",fun_n1_pos)
	expr_n1_orient = Expr3DEbdDart("orient",fun_n1_orient)
	expr_n2_orient = Expr3DEbdDart("orient",fun_n2_orient)
	expr_n3_orient = Expr3DEbdDart("orient",fun_n3_orient)
	expr_n3_pos = Expr3DEbd123("pos",fun_n3_pos)
	rule = Rule3D("SubdivideCatmullClark","subdivision")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [0,1,2], True)
	rule.linkLeftNodes(3,ln0,ln0)
	# motif droit 
	rn0 = rule.make_rightnode("n0", [-1,1,2],[expr_n0_pos])
	rn1 = rule.make_rightnode("n1", [-1,-1,2],[expr_n1_pos,expr_n1_orient])
	rn2 = rule.make_rightnode("n2", [2,-1,-1],[expr_n2_orient,expr_n1_pos])
	rn3 = rule.make_rightnode("n3", [2,1,-1],[expr_n3_orient,expr_n3_pos])
	rule.linkRightNodes(0,rn0,rn1)
	rule.linkRightNodes(1,rn1,rn2)
	rule.linkRightNodes(0,rn2,rn3)
	rule.linkRightNodes(3,rn0,rn0)
	rule.linkRightNodes(3,rn1,rn1)
	rule.linkRightNodes(3,rn2,rn2)
	rule.linkRightNodes(3,rn3,rn3)
	rule.compile()
	return rule

def rule_suppression_DeleteConnex():
	rule = Rule3D("DeleteConnex","suppression")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [0,1,2,3], True)
	# motif droit 
	rule.compile()
	return rule

def rule_suppression_DeleteFace():
	rule = Rule3D("DeleteFace","suppression")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [0,1,3], True)
	rule.linkLeftNodes(2,ln0,ln0)
	# motif droit 
	rule.compile()
	return rule

def rule_translation_TranslateVertex():
	def fun_n0_pos(context):
		Point3 p =  Point3(context.gmap[context.leftdart].ebd123["pos"])
		return p.add(vect)
	expr_n0_pos = Expr3DEbd123("pos",fun_n0_pos)
	rule = Rule3D("TranslateVertex","translation")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [1,2,3], True)
	# motif droit 
	rn0 = rule.make_rightnode("n0", [1,2,3],[expr_n0_pos])
	rule.compile()
	return rule

def rule_translation_TranslateFace():
	def fun_n0_pos(context):
		Point3 p =  Point3(context.gmap[context.leftdart].ebd123["pos"])
		return p.add(vect)
	expr_n0_pos = Expr3DEbd123("pos",fun_n0_pos)
	rule = Rule3D("TranslateFace","translation")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [0,1], True)
	# motif droit 
	rn0 = rule.make_rightnode("n0", [0,1],[expr_n0_pos])
	rule.compile()
	return rule

def rule_translation_TranslateConnex():
	def fun_n0_pos(context):
		Point3 p =  Point3(context.gmap[context.leftdart].ebd123["pos"])
		return p.add(vect)
	expr_n0_pos = Expr3DEbd123("pos",fun_n0_pos)
	rule = Rule3D("TranslateConnex","translation")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [0,1,2,3], True)
	# motif droit 
	rn0 = rule.make_rightnode("n0", [0,1,2,3],[expr_n0_pos])
	rule.compile()
	return rule

def rule_translation_TranslateVolume():
	def fun_n0_pos(context):
		Point3 p =  Point3(context.gmap[context.leftdart].ebd123["pos"])
		return p.add(vect)
	expr_n0_pos = Expr3DEbd123("pos",fun_n0_pos)
	rule = Rule3D("TranslateVolume","translation")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [0,1,2], True)
	# motif droit 
	rn0 = rule.make_rightnode("n0", [0,1,2],[expr_n0_pos])
	rule.compile()
	return rule

def rule_triangulation_TriangulationAllFaces():
	def fun_n1_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	def fun_n2_pos(context):
		return Point3.middle(<0,1>_pos(n0))
	def fun_n2_orient(context):
		return context.gmap[context.leftdart].ebd["orient"]
	expr_n1_orient = Expr3DEbdDart("orient",fun_n1_orient)
	expr_n2_pos = Expr3DEbd123("pos",fun_n2_pos)
	expr_n2_orient = Expr3DEbdDart("orient",fun_n2_orient)
	rule = Rule3D("TriangulationAllFaces","triangulation")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [0,1,2,3], True)
	# motif droit 
	rn0 = rule.make_rightnode("n0", [0,-1,2,3])
	rn1 = rule.make_rightnode("n1", [-1,2,-1,3],[expr_n1_orient])
	rn2 = rule.make_rightnode("n2", [1,2,-1,3],[expr_n2_pos,expr_n2_orient])
	rule.linkRightNodes(1,rn0,rn1)
	rule.linkRightNodes(0,rn1,rn2)
	rule.compile()
	return rule

def rule_triangulation_TriangulationFace():
	def fun_n1_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	def fun_n2_orient(context):
		return context.gmap[context.leftdart].ebd["orient"]
	def fun_n2_pos(context):
		return Point3.middle(<0,1>_pos(n0))
	expr_n1_orient = Expr3DEbdDart("orient",fun_n1_orient)
	expr_n2_orient = Expr3DEbdDart("orient",fun_n2_orient)
	expr_n2_pos = Expr3DEbd123("pos",fun_n2_pos)
	rule = Rule3D("TriangulationFace","triangulation")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [0,1,3], True)
	# motif droit 
	rn0 = rule.make_rightnode("n0", [0,-1,3])
	rn1 = rule.make_rightnode("n1", [-1,2,3],[expr_n1_orient])
	rn2 = rule.make_rightnode("n2", [1,2,3],[expr_n2_orient,expr_n2_pos])
	rule.linkRightNodes(1,rn0,rn1)
	rule.linkRightNodes(0,rn1,rn2)
	rule.compile()
	return rule

def rule_rotation_RotationConnex():
	def fun_n0_pos(context):
		return Point3.rotation(context.gmap[context.leftdart].ebd123["pos"],vect,angle)
	expr_n0_pos = Expr3DEbd123("pos",fun_n0_pos)
	rule = Rule3D("RotationConnex","rotation")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [0,1,2,3], True)
	# motif droit 
	rn0 = rule.make_rightnode("n0", [0,1,2,3],[expr_n0_pos])
	rule.compile()
	return rule

def rule_util_FlipOrient():
	def fun_n0_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	expr_n0_orient = Expr3DEbdDart("orient",fun_n0_orient)
	rule = Rule3D("FlipOrient","util")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [0,1,2,3], True)
	# motif droit 
	rn0 = rule.make_rightnode("n0", [0,1,2,3],[expr_n0_orient])
	rule.compile()
	return rule

def rule_util_SetOrient():
	def fun_n0_orient(context):
		return flag
	expr_n0_orient = Expr3DEbdDart("orient",fun_n0_orient)
	rule = Rule3D("SetOrient","util")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [], True)
	# motif droit 
	rn0 = rule.make_rightnode("n0", [],[expr_n0_orient])
	rule.compile()
	return rule

def rule_solution_SolExtrudeFace():
	def fun_n0_normal(context):
		Point3 n =  Point3(context.gmap[context.leftdart].ebd01["normal"])
		n.scale(-1)
		return n
	def fun_n1_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	def fun_n1_normal(context):
		JerboaDart d = n0
		if(not d.orient) {
		    d = n0.alpha(0)
		}
		Point3 n =  Point3(d.pos, d@0.pos)
		n.normalize()
		return context.gmap[context.leftdart].ebd01["normal"].cross(n)
	def fun_n2_orient(context):
		return context.gmap[context.leftdart].ebd["orient"]
	def fun_n3_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	def fun_n4_orient(context):
		return context.gmap[context.leftdart].ebd["orient"]
	def fun_n5_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	def fun_n5_normal(context):
		return context.gmap[context.leftdart].ebd01["normal"]
	def fun_n5_pos(context):
		return context.gmap[context.leftdart].ebd123["pos"].addConst(context.gmap[context.leftdart].ebd01["normal"])
	expr_n0_normal = Expr3DEbd01("normal",fun_n0_normal)
	expr_n1_orient = Expr3DEbdDart("orient",fun_n1_orient)
	expr_n1_normal = Expr3DEbd01("normal",fun_n1_normal)
	expr_n2_orient = Expr3DEbdDart("orient",fun_n2_orient)
	expr_n3_orient = Expr3DEbdDart("orient",fun_n3_orient)
	expr_n4_orient = Expr3DEbdDart("orient",fun_n4_orient)
	expr_n5_orient = Expr3DEbdDart("orient",fun_n5_orient)
	expr_n5_normal = Expr3DEbd01("normal",fun_n5_normal)
	expr_n5_pos = Expr3DEbd123("pos",fun_n5_pos)
	rule = Rule3D("SolExtrudeFace","solution")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [0,1], True)
	rule.linkLeftNodes(2,ln0,ln0)
	# motif droit 
	rn0 = rule.make_rightnode("n0", [0,1],[expr_n0_normal])
	rn1 = rule.make_rightnode("n1", [0,-1],[expr_n1_orient,expr_n1_normal])
	rn2 = rule.make_rightnode("n2", [-1,2],[expr_n2_orient,expr_n1_normal])
	rn3 = rule.make_rightnode("n3", [-1,2],[expr_n3_orient,expr_n5_pos,expr_n1_normal])
	rn4 = rule.make_rightnode("n4", [0,-1],[expr_n4_orient,expr_n5_pos,expr_n1_normal])
	rn5 = rule.make_rightnode("n5", [0,1],[expr_n5_orient,expr_n5_normal,expr_n5_pos])
	rule.linkRightNodes(2,rn0,rn1)
	rule.linkRightNodes(1,rn1,rn2)
	rule.linkRightNodes(0,rn2,rn3)
	rule.linkRightNodes(1,rn3,rn4)
	rule.linkRightNodes(3,rn4,rn4)
	rule.linkRightNodes(3,rn3,rn3)
	rule.linkRightNodes(3,rn2,rn2)
	rule.linkRightNodes(3,rn1,rn1)
	rule.linkRightNodes(2,rn4,rn5)
	rule.linkRightNodes(3,rn5,rn5)
	rule.compile()
	return rule

def rule_solution_SolLinkEdges():
	def fun_n2_orient(context):
		return context.gmap[context.leftdart].ebd["orient"]
	def fun_n3_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	def fun_n4_orient(context):
		return context.gmap[context.leftdart].ebd["orient"]
	def fun_n5_normal(context):
		return Point3.middle(context.gmap[context.leftdart].ebd01["normal"], n1.normal)
	def fun_n5_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	expr_n2_orient = Expr3DEbdDart("orient",fun_n2_orient)
	expr_n3_orient = Expr3DEbdDart("orient",fun_n3_orient)
	expr_n4_orient = Expr3DEbdDart("orient",fun_n4_orient)
	expr_n5_normal = Expr3DEbd01("normal",fun_n5_normal)
	expr_n5_orient = Expr3DEbdDart("orient",fun_n5_orient)
	rule = Rule3D("SolLinkEdges","solution")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [0], True)
	ln1 = rule.make_leftnode("n1", [0], True)
	rule.linkLeftNodes(2,ln0,ln0)
	rule.linkLeftNodes(2,ln1,ln1)
	# motif droit 
	rn0 = rule.make_rightnode("n0", [0])
	rn1 = rule.make_rightnode("n1", [0])
	rn2 = rule.make_rightnode("n2", [-1],[expr_n2_orient,expr_n5_normal])
	rn3 = rule.make_rightnode("n3", [-1],[expr_n3_orient,expr_n5_normal])
	rn4 = rule.make_rightnode("n4", [0],[expr_n4_orient,expr_n5_normal])
	rn5 = rule.make_rightnode("n5", [0],[expr_n5_normal,expr_n5_orient])
	rule.linkRightNodes(0,rn2,rn3)
	rule.linkRightNodes(1,rn3,rn4)
	rule.linkRightNodes(2,rn0,rn5)
	rule.linkRightNodes(1,rn5,rn2)
	rule.linkRightNodes(2,rn4,rn1)
	rule.linkRightNodes(3,rn5,rn5)
	rule.linkRightNodes(2,rn2,rn2)
	rule.linkRightNodes(2,rn3,rn3)
	rule.linkRightNodes(3,rn3,rn3)
	rule.linkRightNodes(3,rn2,rn2)
	rule.linkRightNodes(3,rn4,rn4)
	rule.compile()
	return rule

def rule_solution_SolExtrudeDir():
	def fun_n0_normal(context):
		Point3 n =  Point3(context.gmap[context.leftdart].ebd01["normal"])
		n.scale(-1)
		return n
	def fun_n1_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	def fun_n1_normal(context):
		JerboaDart d = n0
		if(not d.orient) {
		    d = n0.alpha(0)
		}
		Point3 n =  Point3(d.pos, d@0.pos)
		n.normalize()
		return dir.cross(n)
	def fun_n2_orient(context):
		return context.gmap[context.leftdart].ebd["orient"]
	def fun_n3_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	def fun_n4_orient(context):
		return context.gmap[context.leftdart].ebd["orient"]
	def fun_n5_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	def fun_n5_normal(context):
		return context.gmap[context.leftdart].ebd01["normal"]
	def fun_n5_pos(context):
		return context.gmap[context.leftdart].ebd123["pos"].addConst(dir)
	expr_n0_normal = Expr3DEbd01("normal",fun_n0_normal)
	expr_n1_orient = Expr3DEbdDart("orient",fun_n1_orient)
	expr_n1_normal = Expr3DEbd01("normal",fun_n1_normal)
	expr_n2_orient = Expr3DEbdDart("orient",fun_n2_orient)
	expr_n3_orient = Expr3DEbdDart("orient",fun_n3_orient)
	expr_n4_orient = Expr3DEbdDart("orient",fun_n4_orient)
	expr_n5_orient = Expr3DEbdDart("orient",fun_n5_orient)
	expr_n5_normal = Expr3DEbd01("normal",fun_n5_normal)
	expr_n5_pos = Expr3DEbd123("pos",fun_n5_pos)
	rule = Rule3D("SolExtrudeDir","solution")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [0,1], True)
	rule.linkLeftNodes(2,ln0,ln0)
	# motif droit 
	rn0 = rule.make_rightnode("n0", [0,1],[expr_n0_normal])
	rn1 = rule.make_rightnode("n1", [0,-1],[expr_n1_orient,expr_n1_normal])
	rn2 = rule.make_rightnode("n2", [-1,2],[expr_n2_orient,expr_n1_normal])
	rn3 = rule.make_rightnode("n3", [-1,2],[expr_n3_orient,expr_n5_pos,expr_n1_normal])
	rn4 = rule.make_rightnode("n4", [0,-1],[expr_n4_orient,expr_n5_pos,expr_n1_normal])
	rn5 = rule.make_rightnode("n5", [0,1],[expr_n5_orient,expr_n5_normal,expr_n5_pos])
	rule.linkRightNodes(2,rn0,rn1)
	rule.linkRightNodes(1,rn1,rn2)
	rule.linkRightNodes(0,rn2,rn3)
	rule.linkRightNodes(1,rn3,rn4)
	rule.linkRightNodes(3,rn4,rn4)
	rule.linkRightNodes(3,rn3,rn3)
	rule.linkRightNodes(3,rn2,rn2)
	rule.linkRightNodes(3,rn1,rn1)
	rule.linkRightNodes(2,rn4,rn5)
	rule.linkRightNodes(3,rn5,rn5)
	rule.compile()
	return rule

def rule_extrude_ExtrudeA3():
	def fun_n1_normal(context):
		Point3 n =  Point3(context.gmap[context.leftdart].ebd01["normal"])
		n.scale(-1)
		return n
	def fun_n1_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	def fun_n1_color(context):
		return Color4.brighter(n0.color)
	expr_n1_normal = Expr3DEbd01("normal",fun_n1_normal)
	expr_n1_orient = Expr3DEbdDart("orient",fun_n1_orient)
	expr_n1_color = Expr3DEbd01("color",fun_n1_color)
	rule = Rule3D("ExtrudeA3","extrude")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [0,1], True)
	rule.linkLeftNodes(3,ln0,ln0)
	# motif droit 
	rn0 = rule.make_rightnode("n0", [0,1])
	rn1 = rule.make_rightnode("n1", [0,1],[expr_n1_normal,expr_n1_orient,expr_n1_color])
	rule.linkRightNodes(3,rn0,rn1)
	rule.linkRightNodes(2,rn1,rn1)
	rule.compile()
	return rule

def rule_solution_SolExtrudeSurface():
	def fun_face_normal(context):
		Point3 n =  Point3(face.normal)
		n.scale(-1)
		return n
	def fun_face_orient(context):
		return not face.orient
	def fun_n1_orient(context):
		return face.orient
	def fun_n1_normal(context):
		JerboaDart d = face
		if(not d.orient) {
		    d = face.alpha(0)
		}
		Point3 n =  Point3(d@0.pos, d.pos)
		n.normalize()
		return face.normal.cross(n)
	def fun_n2_orient(context):
		return not face.orient
	def fun_n2_color(context):
		return Color4.brighter(face.color)
	def fun_n3_orient(context):
		return face.orient
	def fun_n4_orient(context):
		return not face.orient
	def fun_n5_orient(context):
		return face.orient
	def fun_n5_normal(context):
		Point3 n =  Point3(face.normal)
		return n
	def fun_n5_pos(context):
		List<Point3> ns = <1,2,3>_normal(face)
		Point3 n = Point3.middle(ns)
		n.scale(0.25)
		return face.pos.addConst(n)
	def fun_n5_color(context):
		return Color4.brighter(Color4.brighter(face.color))
	expr_face_normal = Expr3DEbd01("normal",fun_face_normal)
	expr_face_orient = Expr3DEbdDart("orient",fun_face_orient)
	expr_n1_orient = Expr3DEbdDart("orient",fun_n1_orient)
	expr_n1_normal = Expr3DEbd01("normal",fun_n1_normal)
	expr_n2_orient = Expr3DEbdDart("orient",fun_n2_orient)
	expr_n2_color = Expr3DEbd01("color",fun_n2_color)
	expr_n3_orient = Expr3DEbdDart("orient",fun_n3_orient)
	expr_n4_orient = Expr3DEbdDart("orient",fun_n4_orient)
	expr_n5_orient = Expr3DEbdDart("orient",fun_n5_orient)
	expr_n5_normal = Expr3DEbd01("normal",fun_n5_normal)
	expr_n5_pos = Expr3DEbd123("pos",fun_n5_pos)
	expr_n5_color = Expr3DEbd01("color",fun_n5_color)
	rule = Rule3D("SolExtrudeSurface","solution")
	# motif gauche 
	lface = rule.make_leftnode("face", [0,1,2], True)
	# motif droit 
	rface = rule.make_rightnode("face", [0,1,-1],[expr_face_normal,expr_face_orient])
	rn1 = rule.make_rightnode("n1", [0,-1,3],[expr_n1_orient,expr_n1_normal,expr_n2_color])
	rn2 = rule.make_rightnode("n2", [-1,2,3],[expr_n2_orient,expr_n2_color,expr_n1_normal])
	rn3 = rule.make_rightnode("n3", [-1,2,3],[expr_n3_orient,expr_n5_pos,expr_n1_normal,expr_n2_color])
	rn4 = rule.make_rightnode("n4", [0,-1,3],[expr_n4_orient,expr_n5_pos,expr_n1_normal,expr_n2_color])
	rn5 = rule.make_rightnode("n5", [0,1,-1],[expr_n5_orient,expr_n5_normal,expr_n5_pos,expr_n5_color])
	rule.linkRightNodes(2,rface,rn1)
	rule.linkRightNodes(1,rn1,rn2)
	rule.linkRightNodes(0,rn2,rn3)
	rule.linkRightNodes(1,rn3,rn4)
	rule.linkRightNodes(2,rn4,rn5)
	rule.linkRightNodes(3,rn5,rn5)
	rule.compile()
	return rule

def rule_util_FlipNormal():
	def fun_n0_normal(context):
		Point3 n =  Point3(context.gmap[context.leftdart].ebd01["normal"])
		n.scale(-1)
		return n
	expr_n0_normal = Expr3DEbd01("normal",fun_n0_normal)
	rule = Rule3D("FlipNormal","util")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [0,1,2,3], True)
	# motif droit 
	rn0 = rule.make_rightnode("n0", [0,1,2,3],[expr_n0_normal])
	rule.compile()
	return rule

def rule_subdivision_SubdivideCatmullClark3D():
	def fun_n0_pos(context):
		Point3 old_coord =  Point3(context.gmap[context.leftdart].ebd123["pos"])
		int n_faces = 0
		Point3 avg_face_poss =  Point3()
		for(JerboaDart dart : <1,2,3>_<0,1>(n0)) {
		    Point3 mid = Point3.middle(<0,1>_<0>(dart),"pos")
		    avg_face_poss.add(mid)
		    n_faces++
		}
		avg_face_poss.scale(1.0 / n_faces)
		
		Point3 avg_edge_poss =  Point3()
		int n_edges = 0
		for(JerboaDart dart : <1,2,3>_<2,3>(n0)) {
		    Point3 edgeMid = Point3.middle(<0>_pos(dart))
		    Point3 face1Mid = Point3.middle(<0,1>_pos(dart))
		    Point3 face2Mid = Point3.middle(<0,1>_pos(dart@2))
		    edgeMid.add(face1Mid)
		    edgeMid.add(face2Mid)
		    edgeMid.scale(1.0 / 3.0)
		    avg_edge_poss.add(edgeMid)
		    n_edges++
		}
		avg_edge_poss.scale(1.0 / n_edges)
		double m1 = (n_faces - 3.0) / n_faces
		double m2 = 1.0 / n_faces
		double m3 = 2.0 / n_faces
		old_coord.scale(m1)
		avg_face_poss.scale(m2)
		avg_edge_poss.scale(m3)
		old_coord.add(avg_face_poss)
		old_coord.add(avg_edge_poss)
		return old_coord
		
	def fun_n1_pos(context):
		Point3 edgeMid = Point3.middle(context.gmap[context.leftdart].ebd123["pos"], n0@0.pos)
		Point3 face1Mid = Point3.middle(<0,1>_pos(n0))
		Point3 face2Mid = Point3.middle(<0,1>_pos(n0@2))
		edgeMid.add(face1Mid)
		edgeMid.add(face2Mid)
		edgeMid.scale(1.0 / 3.0)
		
		return edgeMid
	def fun_n1_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	def fun_n2_orient(context):
		return context.gmap[context.leftdart].ebd["orient"]
	def fun_n3_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	def fun_n3_pos(context):
		return Point3.middle(<0,1>_pos(n0))
	expr_n0_pos = Expr3DEbd123("pos",fun_n0_pos)
	expr_n1_pos = Expr3DEbd123("pos",fun_n1_pos)
	expr_n1_orient = Expr3DEbdDart("orient",fun_n1_orient)
	expr_n2_orient = Expr3DEbdDart("orient",fun_n2_orient)
	expr_n3_orient = Expr3DEbdDart("orient",fun_n3_orient)
	expr_n3_pos = Expr3DEbd123("pos",fun_n3_pos)
	rule = Rule3D("SubdivideCatmullClark3D","subdivision")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [0,1,2,3], True)
	# motif droit 
	rn0 = rule.make_rightnode("n0", [-1,1,2,3],[expr_n0_pos])
	rn1 = rule.make_rightnode("n1", [-1,-1,2,3],[expr_n1_pos,expr_n1_orient])
	rn2 = rule.make_rightnode("n2", [2,-1,-1,3],[expr_n2_orient,expr_n1_pos])
	rn3 = rule.make_rightnode("n3", [2,1,-1,3],[expr_n3_orient,expr_n3_pos])
	rule.linkRightNodes(0,rn0,rn1)
	rule.linkRightNodes(1,rn1,rn2)
	rule.linkRightNodes(0,rn2,rn3)
	rule.compile()
	return rule

def rule_creat_CreatDart():
	def fun_n0_pos(context):
		Point3 tmp =  Point3(0,0,0)
		return Point3.askPoint3("Saisissez un vecteur séparé par des ", tmp)
	def fun_n0_normal(context):
		return  Point3(0,0,0)
	expr_n0_pos = Expr3DEbd123("pos",fun_n0_pos)
	expr_n0_normal = Expr3DEbd01("normal",fun_n0_normal)
	rule = Rule3D("CreatDart","creat")
	# motif gauche 
	# motif droit 
	rn0 = rule.make_rightnode("n0", [],[expr_n0_pos,expr_n0_normal])
	rule.linkRightNodes(0,rn0,rn0)
	rule.linkRightNodes(1,rn0,rn0)
	rule.linkRightNodes(2,rn0,rn0)
	rule.linkRightNodes(3,rn0,rn0)
	rule.compile()
	return rule

def rule_subdivision_SubdivideLoop3D():
	def fun_n0_pos(context):
		JerboaList <Point3> voisins
		for (JerboaDart d : <1,2>_<2>(n0)) {
		    voisins.add(d@0.pos) 
		}
		int n = voisins.size()
		
		// mid = (P1 + P2 + ...) / n
		Point3 mid = Point3.middle(voisins)
		
		if (n<=1) {
		    return context.gmap[context.leftdart].ebd123["pos"]
		}
		else if (n==2){
		    return Point3.barycenter(context.gmap[context.leftdart].ebd123["pos"], 3.0/4.0, mid, 1.0/4.0)
		}
		else if (n==3){
		    return Point3.barycenter(context.gmap[context.leftdart].ebd123["pos"], 7.0/16.0, mid, 9.0/16.0)
		}
		else {
		    // grace au milieu beta * mid = (3 * (P1+P2+...))/(8*n)
		    double beta = 3.0 / 8.0
		    double opp = (1 - beta)
		    return Point3.barycenter(context.gmap[context.leftdart].ebd123["pos"], opp, mid, beta)
		}
	def fun_n1_pos(context):
		return Point3.barycenter(context.gmap[context.leftdart].ebd123["pos"], 3.0/8.0, n0@0.pos, 3.0/8.0, n0@1@0.pos, 1.0/8.0, n0@2@1@0.pos, 1.0/8.0)
	def fun_n1_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	def fun_n2_orient(context):
		return context.gmap[context.leftdart].ebd["orient"]
	def fun_n3_color(context):
		return Color4.randomColor()
	def fun_n3_orient(context):
		return not context.gmap[context.leftdart].ebd["orient"]
	def fun_n3_normal(context):
		return context.gmap[context.leftdart].ebd01["normal"]
	expr_n0_pos = Expr3DEbd123("pos",fun_n0_pos)
	expr_n1_pos = Expr3DEbd123("pos",fun_n1_pos)
	expr_n1_orient = Expr3DEbdDart("orient",fun_n1_orient)
	expr_n2_orient = Expr3DEbdDart("orient",fun_n2_orient)
	expr_n3_color = Expr3DEbd01("color",fun_n3_color)
	expr_n3_orient = Expr3DEbdDart("orient",fun_n3_orient)
	expr_n3_normal = Expr3DEbd01("normal",fun_n3_normal)
	rule = Rule3D("SubdivideLoop3D","subdivision")
	# motif gauche 
	ln0 = rule.make_leftnode("n0", [0,1,2,3], True)
	# motif droit 
	rn0 = rule.make_rightnode("n0", [-1,1,2,3],[expr_n0_pos])
	rn1 = rule.make_rightnode("n1", [-1,-1,2,3],[expr_n1_pos,expr_n1_orient])
	rn2 = rule.make_rightnode("n2", [-1,0,-1,3],[expr_n2_orient,expr_n1_pos])
	rn3 = rule.make_rightnode("n3", [1,0,-1,3],[expr_n3_color,expr_n3_orient,expr_n3_normal,expr_n1_pos])
	rule.linkRightNodes(0,rn0,rn1)
	rule.linkRightNodes(1,rn1,rn2)
	rule.linkRightNodes(2,rn2,rn3)
	rule.compile()
	return rule

