aboutsummaryrefslogtreecommitdiff
path: root/src_c
diff options
context:
space:
mode:
authorbozo.kopic <bozo@kopic.xyz>2021-12-24 02:12:55 +0100
committerbozo.kopic <bozo@kopic.xyz>2021-12-24 02:12:55 +0100
commit2c3bacd1ed7f68e407766d96fa3da72b08674d21 (patch)
tree19808af52a1bdbc790c523fa5f878ffedcaab8c7 /src_c
parent1a19c238e3741931db9e61b6a0b79259b5ed0753 (diff)
WIP c implementation
Diffstat (limited to 'src_c')
-rw-r--r--src_c/common.c8
-rw-r--r--src_c/common.h13
-rw-r--r--src_c/csp.c109
3 files changed, 130 insertions, 0 deletions
diff --git a/src_c/common.c b/src_c/common.c
index 5aca7a8..271c2f9 100644
--- a/src_c/common.c
+++ b/src_c/common.c
@@ -277,6 +277,10 @@ static int read_panel(char *json, opcut_panel_t *panel, jsmntok_t *tokens,
}
}
+ if (panel->width <= 0 || panel->height <= 0)
+ return OPCUT_ERROR;
+ panel->area = panel->width * panel->height;
+
return OPCUT_SUCCESS;
}
@@ -315,6 +319,10 @@ static int read_item(char *json, opcut_item_t *item, jsmntok_t *tokens,
}
}
+ if (item->width <= 0 || item->height <= 0)
+ return OPCUT_ERROR;
+ item->area = item->width * item->height;
+
return OPCUT_SUCCESS;
}
diff --git a/src_c/common.h b/src_c/common.h
index 42fed63..660932f 100644
--- a/src_c/common.h
+++ b/src_c/common.h
@@ -36,6 +36,9 @@ typedef struct {
opcut_str_t id;
double width;
double height;
+
+ // internal
+ double area;
} opcut_panel_t;
typedef struct {
@@ -43,6 +46,9 @@ typedef struct {
double width;
double height;
bool can_rotate;
+
+ // internal
+ double area;
} opcut_item_t;
typedef struct {
@@ -68,6 +74,10 @@ typedef struct {
double height;
double x;
double y;
+
+ // internal
+ double area;
+ bool initial;
} opcut_unused_t;
typedef struct {
@@ -76,6 +86,9 @@ typedef struct {
size_t used_len;
opcut_unused_t *unused;
size_t unused_len;
+
+ // internal
+ double panels_area;
} opcut_result_t;
diff --git a/src_c/csp.c b/src_c/csp.c
index 1e555dc..4137955 100644
--- a/src_c/csp.c
+++ b/src_c/csp.c
@@ -1,6 +1,114 @@
#include "csp.h"
+#define FITNESS_K 0.03
+
+
+typedef struct {
+ size_t unused_initial_count;
+ double fitness;
+} fitness_t;
+
+
+static inline int compare_fitness(fitness_t *f1, fitness_t *f2) {
+ return (f1->unused_initial_count == f2->unused_initial_count
+ ? f1->fitness - f2->fitness
+ : f1->unused_initial_count - f2->unused_initial_count);
+}
+
+
+static void calculate_fitness(opcut_result_t *result, fitness_t *fitness) {
+ fitness->fitness = 0;
+
+ for (size_t i = 0; i < result->params->panels_len; ++i) {
+ opcut_panel_t *panel = result->params->panels + i;
+
+ double min_used_area = 0;
+ double used_areas = 0;
+ for (size_t j = 0; j < result->used_len; ++j) {
+ opcut_used_t *used = result->used + i;
+ if (used->panel != panel)
+ continue;
+ if (min_used_area == 0 || used->item->area < min_used_area)
+ min_used_area = used->item->area;
+ used_areas = used->item->area;
+ }
+
+ double max_unused_area = 0;
+ for (size_t j = 0; j < result->unused_len; ++j) {
+ opcut_unused_t *unused = result->unused + i;
+ if (unused->panel != panel)
+ continue;
+ if (max_unused_area == 0 || unused->area > max_unused_area)
+ max_unused_area = unused->area;
+ }
+
+ fitness->fitness += (panel->area - used_areas) / result->panels_area;
+ fitness->fitness -= FITNESS_K * min_used_area * max_unused_area /
+ (result->panels_area * result->panels_area);
+ }
+
+ fitness->unused_initial_count = 0;
+ if (result->params->min_initial_usage) {
+ for (size_t i = 0; i < result->unused_len; ++i) {
+ opcut_unused_t *unused = result->unused + i;
+ if (unused->initial)
+ fitness->unused_initial_count += 1;
+ }
+ }
+}
+
+
+static int cut_item_from_unused(opcut_item_t *item, opcut_unused_t *unused,
+ bool rotate, double cut_width, bool vertical,
+ opcut_used_t *new_used,
+ opcut_unused_t *new_unused,
+ size_t *new_unused_len) {
+ double item_width = (rotate ? item->height : item->width);
+ double item_height = (rotate ? item->width : item->height);
+ if (unused->height < item_height || unused->width < item_width)
+ return OPCUT_UNSOLVABLE;
+
+ new_used->panel = unused->panel;
+ new_used->item = item;
+ new_used->x = unused->x;
+ new_used->y = unused->y;
+ new_used->rotate = rotate;
+
+ double width;
+ double height;
+ *new_unused_len = 0;
+
+ width = unused->width - item_width - cut_width;
+ if (width > 0) {
+ height = (vertical ? unused->height : item_height);
+ new_unused[(*new_unused_len)++] =
+ (opcut_unused_t){.panel = unused->panel,
+ .width = width,
+ .height = height,
+ .x = unused->x + item_width + cut_width,
+ .y = unused->y,
+ .area = width * height,
+ .initial = false};
+ }
+
+ height = unused->height - item_height - cut_width;
+ if (height > 0) {
+ width = (vertical ? item_width : unused->width);
+ new_unused[(*new_unused_len)++] =
+ (opcut_unused_t){.panel = unused->panel,
+ .width = width,
+ .height = height,
+ .x = unused->x,
+ .y = unused->y + item_height + cut_width,
+ .area = width * height,
+ .initial = false};
+ }
+
+ return OPCUT_SUCCESS;
+}
+
+
int opcut_calculate(opcut_method_t method, opcut_params_t *params,
opcut_result_t *result) {
@@ -9,6 +117,7 @@ int opcut_calculate(opcut_method_t method, opcut_params_t *params,
result->used_len = 0;
result->unused = NULL;
result->unused_len = 0;
+ result->panels_area = 0;
return OPCUT_SUCCESS;
}