Initial triangle generation
This commit is contained in:
+7
-1
@@ -1,4 +1,4 @@
|
||||
#include "src/resource_ids.auto.h"
|
||||
#include "triangles.h"
|
||||
#include <pebble.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -36,6 +36,7 @@ static TextLayer *s_drop_txt_under_layer;
|
||||
static Layer *s_division_layer;
|
||||
static Layer *s_alarm_highlight_layer;
|
||||
static MenuLayer *s_drop_menu_layer;
|
||||
static TriangleLayer *s_triangle_layer;
|
||||
|
||||
// fonts
|
||||
//// setter
|
||||
@@ -546,11 +547,16 @@ static void alarm_window_load() {
|
||||
layer_set_update_proc(s_alarm_highlight_layer, alarm_highlight_layer_update_proc);
|
||||
layer_add_child(window_layer, s_alarm_highlight_layer);
|
||||
|
||||
// triangle
|
||||
s_triangle_layer = triangle_layer_create(GRect(0, s_top_bar_grect.size.h + 1, PBL_DISPLAY_WIDTH, PBL_DISPLAY_HEIGHT - (s_top_bar_grect.size.h * 2)));
|
||||
layer_add_child(window_layer, s_triangle_layer->layer);
|
||||
|
||||
schedule_fallback_alarm();
|
||||
tick_timer_service_subscribe(SECOND_UNIT, alarm_seconds_handler);
|
||||
}
|
||||
|
||||
static void alarm_window_unload() {
|
||||
triangle_layer_destroy(s_triangle_layer);
|
||||
layer_destroy(s_alarm_highlight_layer);
|
||||
layer_destroy(s_division_layer);
|
||||
text_layer_destroy(s_parenthesis_txt_layer);
|
||||
|
||||
@@ -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); // 1–178
|
||||
r2 = 1 + (rand() % 179); // 1–178
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include <pebble.h>
|
||||
|
||||
typedef struct {
|
||||
Layer *layer;
|
||||
GColor color;
|
||||
|
||||
// angles; none of these are shown to the user, but they are needed to make the triangle
|
||||
uint8_t angle_A;
|
||||
uint8_t angle_B;
|
||||
uint8_t angle_C;
|
||||
|
||||
// side lengths; two of these are shown to the user (up to 3 digits)
|
||||
uint16_t side_a;
|
||||
uint16_t side_b;
|
||||
uint16_t side_c;
|
||||
} __attribute__((__packed__)) TriangleLayer;
|
||||
|
||||
TriangleLayer *triangle_layer_create(GRect frame);
|
||||
void triangle_layer_destroy(TriangleLayer *tri);
|
||||
Reference in New Issue
Block a user