Initial triangle generation

This commit is contained in:
2026-08-06 23:36:41 -04:00
parent cc0af89820
commit 38af0bcdea
3 changed files with 135 additions and 1 deletions
+108
View File
@@ -0,0 +1,108 @@
#include "triangles.h"
#include <pebble.h>
static void triangle_layer_update_proc(Layer *layer, GContext *ctx) {
// retrieve the TriangleLayer pointer stored in the layer's data slot
TriangleLayer *tri = *(TriangleLayer **)layer_get_data(layer);
if (!tri)
return;
GRect bounds = layer_get_bounds(layer);
graphics_context_set_stroke_color(ctx, tri->color);
// pick the longest side as the horizontal base
uint16_t base_side, left_side;
uint8_t left_angle;
if (tri->side_a >= tri->side_b && tri->side_a >= tri->side_c) {
base_side = tri->side_a;
left_side = tri->side_c; // C → A
left_angle = tri->angle_B; // at vertex B
} else if (tri->side_b >= tri->side_a && tri->side_b >= tri->side_c) {
base_side = tri->side_b;
left_side = tri->side_c; // C → B
left_angle = tri->angle_A; // at vertex A
} else {
base_side = tri->side_c;
left_side = tri->side_b; // B → C
left_angle = tri->angle_A; // at vertex A
}
// draw the base, centered horizontally
// TODO center whole triangle vertically
uint16_t padded_base = (base_side % 2 == 0) ? base_side : base_side + 1;
uint16_t margin = (bounds.size.w / 2) - (padded_base / 2);
uint16_t start_x = margin + 1;
uint16_t end_x = margin + base_side;
uint16_t base_y = bounds.size.h - 5; // small bottom margin
graphics_draw_line(ctx, GPoint(start_x, base_y), GPoint(end_x, base_y));
// determine height and apex coordinates
int32_t sin_left = sin_lookup(((int32_t)left_angle * TRIG_MAX_ANGLE) / 360);
int32_t cos_left = cos_lookup(((int32_t)left_angle * TRIG_MAX_ANGLE) / 360);
uint16_t height = (uint16_t)(((uint32_t)left_side * (uint32_t)sin_left) / TRIG_MAX_RATIO);
uint16_t apex_offset = (uint16_t)(((uint32_t)left_side * (uint32_t)cos_left) / TRIG_MAX_RATIO);
uint16_t apex_x = start_x + apex_offset;
uint16_t apex_y = base_y - height;
// draw the remaining sides
graphics_draw_line(ctx, GPoint(start_x, base_y), GPoint(apex_x, apex_y));
graphics_draw_line(ctx, GPoint(end_x, base_y), GPoint(apex_x, apex_y));
}
TriangleLayer *triangle_layer_create(GRect frame) {
TriangleLayer *tri = malloc(sizeof(TriangleLayer));
if (!tri)
return NULL;
// determine angles
uint8_t r1, r2;
do {
r1 = 1 + (rand() % 179); // 1178
r2 = 1 + (rand() % 179); // 1178
if (r1 > r2) {
uint8_t tmp = r1;
r1 = r2;
r2 = tmp;
}
} while (r1 == 60 && r2 == 120); // ensure never equilateral
tri->angle_A = r1;
tri->angle_B = r2 - r1;
tri->angle_C = 180 - r2;
// determine side lengths (law of sines)
int32_t sin_A = sin_lookup(((int32_t)tri->angle_A * TRIG_MAX_ANGLE) / 360);
int32_t sin_B = sin_lookup(((int32_t)tri->angle_B * TRIG_MAX_ANGLE) / 360);
int32_t sin_C = sin_lookup(((int32_t)tri->angle_C * TRIG_MAX_ANGLE) / 360);
int32_t max_sin = sin_A;
if (sin_B > max_sin)
max_sin = sin_B;
if (sin_C > max_sin)
max_sin = sin_C;
// longest side randomly chosen
#define MIN_SIDE 10
uint16_t max_side = (frame.size.w < frame.size.h) ? frame.size.w : frame.size.h;
max_side = max_side - 12; // basic margin
uint16_t largest_side = MIN_SIDE + (rand() % (max_side - MIN_SIDE + 1));
tri->side_a = (uint16_t)(((uint32_t)sin_A * largest_side) / (uint32_t)max_sin);
tri->side_b = (uint16_t)(((uint32_t)sin_B * largest_side) / (uint32_t)max_sin);
tri->side_c = (uint16_t)(((uint32_t)sin_C * largest_side) / (uint32_t)max_sin);
// create layer with room for a pointer-sized data slot & store the TriangleLayer* there
tri->layer = layer_create_with_data(frame, sizeof(TriangleLayer *));
*(TriangleLayer **)layer_get_data(tri->layer) = tri;
layer_set_update_proc(tri->layer, triangle_layer_update_proc);
return tri;
}
void triangle_layer_destroy(TriangleLayer *tri) {
if (!tri)
return;
layer_destroy(tri->layer);
free(tri);
}