+/*---------- main energy computation, weights, etc. ----------*/
+
+typedef double CostComputation(const Vertices vertices, int section);
+typedef void PreComputation(const Vertices vertices, int section);
+
+typedef struct {
+ double weight;
+ CostComputation *fn;
+} CostContribution;
+
+#define NPRECOMPS ((sizeof(precomps)/sizeof(precomps[0])))
+#define NCOSTS ((sizeof(costs)/sizeof(costs[0])))
+#define COST(weight, compute) { (weight),(compute) },
+
+static PreComputation *const precomps[]= {
+ compute_edge_lengths,
+ compute_vertex_areas,
+ compute_rim_twist_angles
+};
+
+static const CostContribution costs[]= {
+
+#if XBITS==3
+#define STOP_EPSILON 1e-6
+ COST( 3e3, vertex_displacement_cost)
+ COST( 0.4e3, rim_proximity_cost)
+ COST( 1e7, edge_angle_cost)
+ #define EDGE_ANGLE_COST_CIRCCIRCRAT (0.2/1.7)
+ COST( 1e2, small_triangles_cost)
+ COST( 1e12, noncircular_rim_cost)
+#endif
+
+#if XBITS==4
+#define STOP_EPSILON 5e-3
+ COST( 3e4, vertex_displacement_cost) // NB this is probably wrong now
+ COST( 3e4, vertex_edgewise_displ_cost) // we have changed the power
+ COST( 0.2e3, rim_proximity_cost)
+ COST( 1e4, rim_twist_cost)
+ COST( 1e12, noncircular_rim_cost)
+ COST( 10e1, nonequilateral_triangles_cost)
+// COST( 1e1, small_triangles_cost)
+// COST( 1e6, edge_angle_cost)
+ #define EDGE_ANGLE_COST_CIRCCIRCRAT (0.5/1.7)
+#endif
+
+#if XBITS==5
+#define STOP_EPSILON 1e-5
+ COST( 3e4, vertex_displacement_cost)
+ COST( 3e4, vertex_edgewise_displ_cost)
+ COST( 2e-1, rim_proximity_cost)
+ COST( 3e3, rim_twist_cost)
+ COST( 1e12, noncircular_rim_cost)
+ COST( 3e2, nonequilateral_triangles_cost)
+// COST( 1e1, small_triangles_cost)
+// COST( 1e6, edge_angle_cost)
+ #define EDGE_ANGLE_COST_CIRCCIRCRAT (0.5/1.7)
+#endif
+
+#if XBITS==6
+#define STOP_EPSILON 1.2e-5
+ COST( 3e4, vertex_displacement_cost)
+ COST( 3e4, vertex_edgewise_displ_cost)
+ COST( 3e-2, rim_proximity_cost)
+ COST( 1e4, rim_twist_cost)
+ COST( 1e12, noncircular_rim_cost)
+ COST( 10e1, nonequilateral_triangles_cost)
+// COST( 1e1, small_triangles_cost)
+// COST( 1e6, edge_angle_cost)
+ #define EDGE_ANGLE_COST_CIRCCIRCRAT (0.5/1.7)
+#endif
+
+#if XBITS>=7 /* nonsense follows but never mind */
+#define STOP_EPSILON 1e-6
+ COST( 3e5, line_bending_cost)
+ COST( 10e2, edge_length_variation_cost)
+ COST( 9.0e1, rim_proximity_cost) // 5e1 is too much
+ // 2.5e1 is too little
+ // 0.2e1 grows compared to previous ?
+ // 0.6e0 shrinks compared to previous ?
+
+ COST( 1e12, edge_angle_cost)
+ #define EDGE_ANGLE_COST_CIRCCIRCRAT (0.5/1.3)
+ COST( 1e18, noncircular_rim_cost)
+#endif
+
+};
+
+const double edge_angle_cost_circcircrat= EDGE_ANGLE_COST_CIRCCIRCRAT;
+
+void energy_init(void) {
+ stop_epsilon= STOP_EPSILON;
+}