new geometry implementation + API update
This commit is contained in:
@@ -7,7 +7,9 @@ if(!LibXml2_FOUND)
|
|||||||
message(FATAL_ERROR "Cannot find libxml2 library")
|
message(FATAL_ERROR "Cannot find libxml2 library")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(cyberiadaml SHARED cyberiadaml.c utf8enc.c cyb_types.c cyb_string.c)
|
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D__DEBUG__")
|
||||||
|
|
||||||
|
add_library(cyberiadaml SHARED cyberiadaml.c utf8enc.c cyb_types.c cyb_string.c geometry.c)
|
||||||
target_include_directories(cyberiadaml PUBLIC
|
target_include_directories(cyberiadaml PUBLIC
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||||
$<INSTALL_INTERFACE:include/cyberiada>
|
$<INSTALL_INTERFACE:include/cyberiada>
|
||||||
|
|||||||
38
cyb_error.h
Normal file
38
cyb_error.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* The Cyberiada GraphML library implemention
|
||||||
|
*
|
||||||
|
* Error handling
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 Alexey Fedoseev <aleksey@fedoseev.net>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see https://www.gnu.org/licenses/
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifndef __CYBERIADA_ERROR_H
|
||||||
|
#define __CYBERIADA_ERROR_H
|
||||||
|
|
||||||
|
#ifdef __DEBUG__
|
||||||
|
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define DEBUG(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __SILENT__
|
||||||
|
#define ERROR(...) fprintf(stderr, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define ERROR(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
52
cyb_types.c
52
cyb_types.c
@@ -38,7 +38,7 @@ int cyberiada_stack_update_top_key(CyberiadaStack** stack, const char* new_key
|
|||||||
if (!stack || !*stack) {
|
if (!stack || !*stack) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
(*stack)->key = new_key;
|
(*stack)->key = (void*)new_key;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ int cyberiada_list_add(CyberiadaList** list, const char* key, void* data)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
new_item = (CyberiadaList*)malloc(sizeof(CyberiadaList));
|
new_item = (CyberiadaList*)malloc(sizeof(CyberiadaList));
|
||||||
new_item->key = key;
|
new_item->key = (void*)key;
|
||||||
new_item->data = data;
|
new_item->data = data;
|
||||||
new_item->next = NULL;
|
new_item->next = NULL;
|
||||||
if (!*list) {
|
if (!*list) {
|
||||||
@@ -119,7 +119,7 @@ void* cyberiada_list_find(CyberiadaList** list, const char* key)
|
|||||||
}
|
}
|
||||||
item = *list;
|
item = *list;
|
||||||
while (item) {
|
while (item) {
|
||||||
if (item->key && strcmp(item->key, key) == 0) {
|
if (item->key && strcmp((const char*)item->key, key) == 0) {
|
||||||
return item->data;
|
return item->data;
|
||||||
}
|
}
|
||||||
item = item->next;
|
item = item->next;
|
||||||
@@ -140,3 +140,49 @@ int cyberiada_list_free(CyberiadaList** list)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cyberiada_queue_add(CyberiadaQueue** queue, void* key, void* data)
|
||||||
|
{
|
||||||
|
CyberiadaQueue* new_item = (CyberiadaQueue*)malloc(sizeof(CyberiadaQueue));
|
||||||
|
memset(new_item, 0, sizeof(CyberiadaQueue));
|
||||||
|
new_item->key = key;
|
||||||
|
new_item->data = data;
|
||||||
|
new_item->next = (*queue);
|
||||||
|
*queue = new_item;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cyberiada_queue_get(CyberiadaQueue** queue, void** key, void** data)
|
||||||
|
{
|
||||||
|
CyberiadaQueue *q, *prev = NULL;
|
||||||
|
if (!queue || !key || !data) return 1;
|
||||||
|
q = *queue;
|
||||||
|
while (q->next) {
|
||||||
|
prev = q;
|
||||||
|
q = q->next;
|
||||||
|
}
|
||||||
|
*key = q->key;
|
||||||
|
*data = q->data;
|
||||||
|
free(q);
|
||||||
|
if (prev) {
|
||||||
|
prev->next = NULL;
|
||||||
|
} else {
|
||||||
|
*queue = NULL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cyberiada_queue_free(CyberiadaQueue** queue)
|
||||||
|
{
|
||||||
|
CyberiadaQueue* item;
|
||||||
|
if (!queue) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
while(*queue) {
|
||||||
|
item = *queue;
|
||||||
|
*queue = item->next;
|
||||||
|
free(item);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ extern "C" {
|
|||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
struct _CyberiadaStruct {
|
struct _CyberiadaStruct {
|
||||||
const char* key;
|
void* key;
|
||||||
void* data;
|
void* data;
|
||||||
struct _CyberiadaStruct* next;
|
struct _CyberiadaStruct* next;
|
||||||
};
|
};
|
||||||
@@ -52,6 +52,12 @@ extern "C" {
|
|||||||
int cyberiada_list_add(CyberiadaList** list, const char* key, void* data);
|
int cyberiada_list_add(CyberiadaList** list, const char* key, void* data);
|
||||||
void* cyberiada_list_find(CyberiadaList** list, const char* key);
|
void* cyberiada_list_find(CyberiadaList** list, const char* key);
|
||||||
int cyberiada_list_free(CyberiadaList** list);
|
int cyberiada_list_free(CyberiadaList** list);
|
||||||
|
|
||||||
|
typedef struct _CyberiadaStruct CyberiadaQueue;
|
||||||
|
|
||||||
|
int cyberiada_queue_add(CyberiadaQueue** queue, void* key, void* data);
|
||||||
|
int cyberiada_queue_get(CyberiadaQueue** queue, void** key, void**data);
|
||||||
|
int cyberiada_queue_free(CyberiadaQueue** queue);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
669
cyberiadaml.c
669
cyberiadaml.c
@@ -35,6 +35,8 @@
|
|||||||
#include "utf8enc.h"
|
#include "utf8enc.h"
|
||||||
#include "cyb_types.h"
|
#include "cyb_types.h"
|
||||||
#include "cyb_string.h"
|
#include "cyb_string.h"
|
||||||
|
#include "geometry.h"
|
||||||
|
#include "cyb_error.h"
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* Cyberiada parser constants
|
* Cyberiada parser constants
|
||||||
@@ -173,16 +175,9 @@
|
|||||||
/* Misc. constants */
|
/* Misc. constants */
|
||||||
|
|
||||||
#define PSEUDO_NODE_SIZE 20
|
#define PSEUDO_NODE_SIZE 20
|
||||||
|
#define DEFAULT_NODE_SIZE 100
|
||||||
#define EMPTY_TITLE ""
|
#define EMPTY_TITLE ""
|
||||||
|
|
||||||
#ifdef __DEBUG__
|
|
||||||
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
|
|
||||||
#else
|
|
||||||
#define DEBUG(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ERROR(...) fprintf(stderr, __VA_ARGS__)
|
|
||||||
|
|
||||||
/* Types & macros for XML/GraphML processing */
|
/* Types & macros for XML/GraphML processing */
|
||||||
|
|
||||||
#define INDENT_STR " "
|
#define INDENT_STR " "
|
||||||
@@ -231,6 +226,7 @@
|
|||||||
fprintf(stderr, "xml close element error %d at %s:%d", res, __FILE__, __LINE__); \
|
fprintf(stderr, "xml close element error %d at %s:%d", res, __FILE__, __LINE__); \
|
||||||
return CYBERIADA_XML_ERROR; \
|
return CYBERIADA_XML_ERROR; \
|
||||||
}
|
}
|
||||||
|
# define XML_READMEMORY_BASENAME "noname.xml"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char* attr_id;
|
char* attr_id;
|
||||||
@@ -438,97 +434,6 @@ static CyberiadaLink* cyberiada_copy_link(CyberiadaLink* src)
|
|||||||
return cyberiada_new_link(src->ref);
|
return cyberiada_new_link(src->ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
CyberiadaPoint* cyberiada_new_point(void)
|
|
||||||
{
|
|
||||||
CyberiadaPoint* p = (CyberiadaPoint*)malloc(sizeof(CyberiadaPoint));
|
|
||||||
memset(p, 0, sizeof(CyberiadaPoint));
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static CyberiadaPoint* cyberiada_copy_point(CyberiadaPoint* src)
|
|
||||||
{
|
|
||||||
CyberiadaPoint* dst;
|
|
||||||
if (!src) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
dst = cyberiada_new_point();
|
|
||||||
dst->x = src->x;
|
|
||||||
dst->y = src->y;
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cyberiada_update_point(CyberiadaPoint* p, float dx, float dy)
|
|
||||||
{
|
|
||||||
if (!p) return ;
|
|
||||||
p->x += dx;
|
|
||||||
p->y += dy;
|
|
||||||
}
|
|
||||||
|
|
||||||
CyberiadaRect* cyberiada_new_rect(void)
|
|
||||||
{
|
|
||||||
CyberiadaRect* r = (CyberiadaRect*)malloc(sizeof(CyberiadaRect));
|
|
||||||
memset(r, 0, sizeof(CyberiadaRect));
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static CyberiadaRect* cyberiada_copy_rect(CyberiadaRect* src)
|
|
||||||
{
|
|
||||||
CyberiadaRect* dst;
|
|
||||||
if (!src) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
dst = cyberiada_new_rect();
|
|
||||||
dst->x = src->x;
|
|
||||||
dst->y = src->y;
|
|
||||||
dst->width = src->width;
|
|
||||||
dst->height = src->height;
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cyberiada_update_rect(CyberiadaRect* r, float dx, float dy)
|
|
||||||
{
|
|
||||||
if (!r) return ;
|
|
||||||
r->x += dx;
|
|
||||||
r->y += dy;
|
|
||||||
}
|
|
||||||
|
|
||||||
CyberiadaPolyline* cyberiada_new_polyline(void)
|
|
||||||
{
|
|
||||||
CyberiadaPolyline* pl = (CyberiadaPolyline*)malloc(sizeof(CyberiadaPolyline));
|
|
||||||
memset(pl, 0, sizeof(CyberiadaPolyline));
|
|
||||||
return pl;
|
|
||||||
}
|
|
||||||
|
|
||||||
static CyberiadaPolyline* cyberiada_copy_polyline(CyberiadaPolyline* src)
|
|
||||||
{
|
|
||||||
CyberiadaPolyline *dst = NULL, *prev, *pl;
|
|
||||||
if (!src) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
pl = cyberiada_new_polyline();
|
|
||||||
pl->point.x = src->point.x;
|
|
||||||
pl->point.y = src->point.y;
|
|
||||||
if (dst) {
|
|
||||||
prev->next = pl;
|
|
||||||
} else {
|
|
||||||
dst = pl;
|
|
||||||
}
|
|
||||||
prev = pl;
|
|
||||||
src = src->next;
|
|
||||||
} while (src);
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*static void cyberiada_update_polyline(CyberiadaPolyline* pl, float dx, float dy)
|
|
||||||
{
|
|
||||||
if (!pl) return ;
|
|
||||||
do {
|
|
||||||
cyberiada_update_point(&(pl->point), dx, dy);
|
|
||||||
pl = pl->next;
|
|
||||||
} while (pl);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
CyberiadaAction* cyberiada_new_action(CyberiadaActionType type,
|
CyberiadaAction* cyberiada_new_action(CyberiadaActionType type,
|
||||||
const char* trigger,
|
const char* trigger,
|
||||||
const char* guard,
|
const char* guard,
|
||||||
@@ -545,21 +450,10 @@ CyberiadaAction* cyberiada_new_action(CyberiadaActionType type,
|
|||||||
|
|
||||||
static CyberiadaAction* cyberiada_copy_action(CyberiadaAction* src)
|
static CyberiadaAction* cyberiada_copy_action(CyberiadaAction* src)
|
||||||
{
|
{
|
||||||
CyberiadaAction *dst = NULL, *prev, *a;
|
|
||||||
if (!src) {
|
if (!src) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
do {
|
return cyberiada_new_action(src->type, src->trigger, src->guard, src->behavior);
|
||||||
a = cyberiada_new_action(src->type, src->trigger, src->guard, src->behavior);
|
|
||||||
if (dst) {
|
|
||||||
prev->next = a;
|
|
||||||
} else {
|
|
||||||
dst = a;
|
|
||||||
}
|
|
||||||
prev = a;
|
|
||||||
src = src->next;
|
|
||||||
} while (src);
|
|
||||||
return dst;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CyberiadaNode* cyberiada_new_node(const char* id)
|
CyberiadaNode* cyberiada_new_node(const char* id)
|
||||||
@@ -1256,7 +1150,6 @@ static CyberiadaEdge* cyberiada_graph_find_last_edge(CyberiadaSM* sm)
|
|||||||
|
|
||||||
static int cyberiada_destroy_edge(CyberiadaEdge* e)
|
static int cyberiada_destroy_edge(CyberiadaEdge* e)
|
||||||
{
|
{
|
||||||
CyberiadaPolyline *polyline, *pl;
|
|
||||||
if (e->id) free(e->id);
|
if (e->id) free(e->id);
|
||||||
if (e->source_id) free(e->source_id);
|
if (e->source_id) free(e->source_id);
|
||||||
if (e->target_id) free(e->target_id);
|
if (e->target_id) free(e->target_id);
|
||||||
@@ -1266,12 +1159,7 @@ static int cyberiada_destroy_edge(CyberiadaEdge* e)
|
|||||||
free(e->comment_subject);
|
free(e->comment_subject);
|
||||||
}
|
}
|
||||||
if (e->geometry_polyline) {
|
if (e->geometry_polyline) {
|
||||||
polyline = e->geometry_polyline;
|
cyberiada_destroy_polyline(e->geometry_polyline);
|
||||||
do {
|
|
||||||
pl = polyline;
|
|
||||||
polyline = polyline->next;
|
|
||||||
free(pl);
|
|
||||||
} while (polyline);
|
|
||||||
}
|
}
|
||||||
if (e->geometry_source_point) free(e->geometry_source_point);
|
if (e->geometry_source_point) free(e->geometry_source_point);
|
||||||
if (e->geometry_target_point) free(e->geometry_target_point);
|
if (e->geometry_target_point) free(e->geometry_target_point);
|
||||||
@@ -1311,7 +1199,7 @@ static void cyberiada_free_name_list(NamesList** nl)
|
|||||||
cyberiada_list_free(nl);
|
cyberiada_list_free(nl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cyberiada_graphs_reconstruct_nodes(CyberiadaNode* root, NamesList** nl)
|
static int cyberiada_graphs_reconstruct_node_identifiers(CyberiadaNode* root, NamesList** nl)
|
||||||
{
|
{
|
||||||
char buffer[MAX_STR_LEN];
|
char buffer[MAX_STR_LEN];
|
||||||
size_t buffer_len = sizeof(buffer) - 1;
|
size_t buffer_len = sizeof(buffer) - 1;
|
||||||
@@ -1340,14 +1228,14 @@ static int cyberiada_graphs_reconstruct_nodes(CyberiadaNode* root, NamesList** n
|
|||||||
cyberiada_add_name_to_list(nl, "", node->id);
|
cyberiada_add_name_to_list(nl, "", node->id);
|
||||||
}
|
}
|
||||||
if (node->children) {
|
if (node->children) {
|
||||||
cyberiada_graphs_reconstruct_nodes(node->children, nl);
|
cyberiada_graphs_reconstruct_node_identifiers(node->children, nl);
|
||||||
}
|
}
|
||||||
node = node->next;
|
node = node->next;
|
||||||
}
|
}
|
||||||
return CYBERIADA_NO_ERROR;
|
return CYBERIADA_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cyberiada_graphs_reconstruct_edges(CyberiadaDocument* doc, NamesList** nl)
|
static int cyberiada_graphs_reconstruct_edge_identifiers(CyberiadaDocument* doc, NamesList** nl)
|
||||||
{
|
{
|
||||||
char buffer[MAX_STR_LEN];
|
char buffer[MAX_STR_LEN];
|
||||||
size_t buffer_len = sizeof(buffer) - 1;
|
size_t buffer_len = sizeof(buffer) - 1;
|
||||||
@@ -1410,249 +1298,6 @@ static int cyberiada_graphs_reconstruct_edges(CyberiadaDocument* doc, NamesList*
|
|||||||
return CYBERIADA_NO_ERROR;
|
return CYBERIADA_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cyberiada_graphs_reconstruct_node_geometry_from_yed(CyberiadaNode* node, float parent_x, float parent_y)
|
|
||||||
{
|
|
||||||
float new_root_x;
|
|
||||||
float new_root_y;
|
|
||||||
|
|
||||||
while (node) {
|
|
||||||
if (node->geometry_point) {
|
|
||||||
cyberiada_update_point(node->geometry_point, -parent_x, -parent_y);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->geometry_rect) {
|
|
||||||
new_root_x = node->geometry_rect->x;
|
|
||||||
new_root_y = node->geometry_rect->y;
|
|
||||||
|
|
||||||
cyberiada_update_rect(node->geometry_rect, -parent_x, -parent_y);
|
|
||||||
} else {
|
|
||||||
new_root_x = parent_x;
|
|
||||||
new_root_y = parent_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->children) {
|
|
||||||
cyberiada_graphs_reconstruct_node_geometry_from_yed(node->children, new_root_x, new_root_y);
|
|
||||||
}
|
|
||||||
node = node->next;
|
|
||||||
}
|
|
||||||
return CYBERIADA_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cyberiada_graphs_reconstruct_geometry_from_yed(CyberiadaDocument* doc)
|
|
||||||
{
|
|
||||||
CyberiadaSM* sm;
|
|
||||||
CyberiadaNode* node;
|
|
||||||
CyberiadaEdge* edge;
|
|
||||||
CyberiadaPolyline* pl;
|
|
||||||
float from_x, from_y, to_x, to_y;
|
|
||||||
float src_from_x, src_from_y, src_to_x, src_to_y, tgt_from_x, tgt_from_y, tgt_to_x, tgt_to_y;
|
|
||||||
|
|
||||||
for (sm = doc->state_machines; sm; sm = sm->next) {
|
|
||||||
|
|
||||||
for (edge = sm->edges; edge; edge = edge->next) {
|
|
||||||
if (edge->source && (edge->source->geometry_rect || edge->source->geometry_point) &&
|
|
||||||
edge->target && (edge->target->geometry_rect || edge->target->geometry_point) &&
|
|
||||||
(edge->geometry_source_point ||
|
|
||||||
edge->geometry_target_point ||
|
|
||||||
edge->geometry_polyline ||
|
|
||||||
edge->geometry_label_point)) {
|
|
||||||
|
|
||||||
from_x = from_y = to_x = to_y = 0.0f;
|
|
||||||
if (edge->source->geometry_point) {
|
|
||||||
from_x += edge->source->geometry_point->x;
|
|
||||||
from_y += edge->source->geometry_point->y;
|
|
||||||
} else {
|
|
||||||
from_x += edge->source->geometry_rect->x + edge->source->geometry_rect->width / 2.0f;
|
|
||||||
from_y += edge->source->geometry_rect->y + edge->source->geometry_rect->height / 2.0f;
|
|
||||||
if (edge->geometry_source_point) {
|
|
||||||
from_x += edge->geometry_source_point->x;
|
|
||||||
from_y += edge->geometry_source_point->y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (edge->target->geometry_point) {
|
|
||||||
to_x += edge->target->geometry_point->x;
|
|
||||||
to_y += edge->target->geometry_point->y;
|
|
||||||
} else {
|
|
||||||
to_x += edge->target->geometry_rect->x + edge->target->geometry_rect->width / 2.0f;
|
|
||||||
to_y += edge->target->geometry_rect->y + edge->target->geometry_rect->height / 2.0f;
|
|
||||||
if (edge->geometry_target_point) {
|
|
||||||
to_x += edge->geometry_target_point->x;
|
|
||||||
to_y += edge->geometry_target_point->y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (edge->geometry_polyline) {
|
|
||||||
float first_p_x = edge->geometry_polyline->point.x;
|
|
||||||
float first_p_y = edge->geometry_polyline->point.y;
|
|
||||||
float last_p_x;
|
|
||||||
float last_p_y;
|
|
||||||
|
|
||||||
pl = edge->geometry_polyline;
|
|
||||||
while (pl->next) pl = pl->next;
|
|
||||||
last_p_x = pl->point.x;
|
|
||||||
last_p_y = pl->point.y;
|
|
||||||
|
|
||||||
src_from_x = from_x;
|
|
||||||
src_from_y = from_y;
|
|
||||||
src_to_x = first_p_x;
|
|
||||||
src_to_y = first_p_y;
|
|
||||||
tgt_from_x = last_p_x;
|
|
||||||
tgt_from_y = last_p_y;
|
|
||||||
tgt_to_x = to_x;
|
|
||||||
tgt_to_y = to_y;
|
|
||||||
} else {
|
|
||||||
src_from_x = tgt_from_x = from_x;
|
|
||||||
src_from_y = tgt_from_y = from_y;
|
|
||||||
src_to_x = tgt_to_x = to_x;
|
|
||||||
src_to_y = tgt_to_y = to_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* DEBUG("edge (%f; %f) -> (%f; %f) and (%f; %f) -> (%f; %f)\n", */
|
|
||||||
/* src_from_x, src_from_y, src_to_x, src_to_y, */
|
|
||||||
/* tgt_from_x, tgt_from_y, tgt_to_x, tgt_to_y); */
|
|
||||||
|
|
||||||
if (edge->geometry_source_point) {
|
|
||||||
if (edge->source->geometry_point) {
|
|
||||||
if (src_from_x == src_to_x) {
|
|
||||||
edge->geometry_source_point->x = 0.0f;
|
|
||||||
if (src_from_y >= src_to_y) {
|
|
||||||
edge->geometry_source_point->y = -PSEUDO_NODE_SIZE / 2.0f;
|
|
||||||
} else {
|
|
||||||
edge->geometry_source_point->y = PSEUDO_NODE_SIZE / 2.0f;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
float alpha = (float)atan((src_from_y - src_to_y) / (src_to_x - src_from_x));
|
|
||||||
edge->geometry_source_point->x = (float)cos(alpha) * PSEUDO_NODE_SIZE / 2.0f;
|
|
||||||
edge->geometry_source_point->y = -(float)sin(alpha) * PSEUDO_NODE_SIZE / 2.0f;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (src_from_x == src_to_x) {
|
|
||||||
edge->geometry_source_point->x = edge->source->geometry_rect->width / 2.0f;
|
|
||||||
if (src_from_y >= src_to_y) {
|
|
||||||
edge->geometry_source_point->y = 0.0f;
|
|
||||||
} else {
|
|
||||||
edge->geometry_source_point->y = edge->source->geometry_rect->height;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
float alpha = (float)atan((src_from_y - src_to_y) / (src_to_x - src_from_x));
|
|
||||||
if (src_to_x < src_from_x) alpha += (float)M_PI;
|
|
||||||
float alpha_g = 180.0f * alpha / (float)M_PI;
|
|
||||||
/* DEBUG("src alpha %f\n", alpha_g);*/
|
|
||||||
if (alpha_g < 0.0f) alpha_g += 360.0f;
|
|
||||||
if (alpha_g <= 45.0f || alpha_g > 315.0f) {
|
|
||||||
edge->geometry_source_point->x = edge->source->geometry_rect->width;
|
|
||||||
edge->geometry_source_point->y += (-(float)tan(alpha) * edge->source->geometry_rect->width +
|
|
||||||
edge->source->geometry_rect->height) / 2.0f;
|
|
||||||
} else if (alpha_g > 45.0f && alpha_g <= 135.0f) {
|
|
||||||
edge->geometry_source_point->x += ((float)tan(alpha) * edge->source->geometry_rect->height +
|
|
||||||
edge->source->geometry_rect->width) / 2.0f;
|
|
||||||
edge->geometry_source_point->y = 0.0f;
|
|
||||||
} else if (alpha_g > 135.0f && alpha_g <= 225.0f) {
|
|
||||||
edge->geometry_source_point->x = 0.0f;
|
|
||||||
edge->geometry_source_point->y += (-(float)tan(alpha) * edge->source->geometry_rect->width +
|
|
||||||
edge->source->geometry_rect->height) / 2.0f;
|
|
||||||
} else {
|
|
||||||
edge->geometry_source_point->x += (-(float)tan(alpha) * edge->source->geometry_rect->height +
|
|
||||||
edge->source->geometry_rect->width) / 2.0f;
|
|
||||||
edge->geometry_source_point->y = edge->source->geometry_rect->height;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (edge->geometry_source_point->x < 0) {
|
|
||||||
edge->geometry_source_point->x = 0.0f;
|
|
||||||
}
|
|
||||||
if (edge->geometry_source_point->x > edge->source->geometry_rect->width) {
|
|
||||||
edge->geometry_source_point->x = edge->source->geometry_rect->width;
|
|
||||||
}
|
|
||||||
if (edge->geometry_source_point->y < 0) {
|
|
||||||
edge->geometry_source_point->y = 0.0f;
|
|
||||||
}
|
|
||||||
if (edge->geometry_source_point->y > edge->source->geometry_rect->height) {
|
|
||||||
edge->geometry_source_point->y = edge->source->geometry_rect->height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* DEBUG("sp: (%f; %f)\n", edge->geometry_source_point->x, edge->geometry_source_point->y); */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (edge->geometry_target_point) {
|
|
||||||
if (edge->target->geometry_point) {
|
|
||||||
if (tgt_from_x == tgt_to_x) {
|
|
||||||
edge->geometry_target_point->x = 0.0f;
|
|
||||||
if (tgt_from_y >= tgt_to_y) {
|
|
||||||
edge->geometry_target_point->y = PSEUDO_NODE_SIZE / 2.0f;
|
|
||||||
} else {
|
|
||||||
edge->geometry_target_point->y = -PSEUDO_NODE_SIZE / 2.0f;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
float alpha = (float)atan((tgt_from_y - tgt_to_y) / (tgt_to_x - tgt_from_x));
|
|
||||||
edge->geometry_target_point->x = (float)cos(alpha) * PSEUDO_NODE_SIZE / 2.0f;
|
|
||||||
edge->geometry_target_point->y = -(float)sin(alpha) * PSEUDO_NODE_SIZE / 2.0f;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (tgt_from_x == tgt_to_x) {
|
|
||||||
edge->geometry_target_point->x = edge->target->geometry_rect->width / 2.0f;
|
|
||||||
if (tgt_from_y >= tgt_to_y) {
|
|
||||||
edge->geometry_target_point->y = edge->target->geometry_rect->height;
|
|
||||||
} else {
|
|
||||||
edge->geometry_target_point->y = 0.0f;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
float alpha = (float)atan((tgt_from_y - tgt_to_y) / (tgt_to_x - tgt_from_x));
|
|
||||||
if (tgt_to_x < tgt_from_x) alpha += (float)M_PI;
|
|
||||||
alpha += (float)M_PI; /* target = incoming edge */
|
|
||||||
float alpha_g = 180.0f * alpha / (float)M_PI;
|
|
||||||
/* DEBUG("tgt alpha %f\n", alpha_g);*/
|
|
||||||
if (alpha_g < 0.0f) alpha_g += 360.0f;
|
|
||||||
if (alpha_g <= 45.0f || alpha_g > 315.0f) {
|
|
||||||
edge->geometry_target_point->x = edge->target->geometry_rect->width;
|
|
||||||
edge->geometry_target_point->y += (-(float)tan(alpha) * edge->target->geometry_rect->width +
|
|
||||||
edge->target->geometry_rect->height) / 2.0f;
|
|
||||||
} else if (alpha_g > 45.0f && alpha_g <= 135.0f) {
|
|
||||||
edge->geometry_target_point->x += ((float)tan(alpha) * edge->target->geometry_rect->height +
|
|
||||||
edge->target->geometry_rect->width) / 2.0f;
|
|
||||||
edge->geometry_target_point->y = 0.0f;
|
|
||||||
} else if (alpha_g > 135.0f && alpha_g <= 225.0f) {
|
|
||||||
edge->geometry_target_point->x = 0.0f;
|
|
||||||
edge->geometry_target_point->y += (-(float)tan(alpha) * edge->target->geometry_rect->width +
|
|
||||||
edge->target->geometry_rect->height) / 2.0f;
|
|
||||||
} else {
|
|
||||||
edge->geometry_target_point->x += (-(float)tan(alpha) * edge->target->geometry_rect->height +
|
|
||||||
edge->target->geometry_rect->width) / 2.0f;
|
|
||||||
edge->geometry_target_point->y = edge->target->geometry_rect->height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (edge->geometry_target_point->x < 0) {
|
|
||||||
edge->geometry_target_point->x = 0.0f;
|
|
||||||
}
|
|
||||||
if (edge->geometry_target_point->x > edge->target->geometry_rect->width) {
|
|
||||||
edge->geometry_target_point->x = edge->target->geometry_rect->width;
|
|
||||||
}
|
|
||||||
if (edge->geometry_target_point->y < 0) {
|
|
||||||
edge->geometry_target_point->y = 0.0f;
|
|
||||||
}
|
|
||||||
if (edge->geometry_target_point->y > edge->target->geometry_rect->height) {
|
|
||||||
edge->geometry_target_point->y = edge->target->geometry_rect->height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* DEBUG("tp: (%f; %f)\n", edge->geometry_target_point->x, edge->geometry_target_point->y); */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (node = sm->nodes; node; node = node->next) {
|
|
||||||
cyberiada_graphs_reconstruct_node_geometry_from_yed(node, 0.0f, 0.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return CYBERIADA_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cyberiada_graphs_reconstruct_geometry_to_yed(CyberiadaDocument* doc)
|
|
||||||
{
|
|
||||||
return CYBERIADA_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char* name;
|
const char* name;
|
||||||
size_t value_offset;
|
size_t value_offset;
|
||||||
@@ -1961,20 +1606,10 @@ static int cyberiada_decode_meta(CyberiadaDocument* doc, char* metadata)
|
|||||||
return CYBERIADA_NO_ERROR;
|
return CYBERIADA_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cyberiada_init_sm(CyberiadaSM* sm)
|
|
||||||
{
|
|
||||||
if (sm) {
|
|
||||||
sm->nodes = NULL;
|
|
||||||
sm->edges = NULL;
|
|
||||||
sm->next = NULL;
|
|
||||||
}
|
|
||||||
return CYBERIADA_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
CyberiadaSM* cyberiada_new_sm(void)
|
CyberiadaSM* cyberiada_new_sm(void)
|
||||||
{
|
{
|
||||||
CyberiadaSM* sm = (CyberiadaSM*)malloc(sizeof(CyberiadaSM));
|
CyberiadaSM* sm = (CyberiadaSM*)malloc(sizeof(CyberiadaSM));
|
||||||
cyberiada_init_sm(sm);
|
memset(sm, 0, sizeof(CyberiadaSM));
|
||||||
return sm;
|
return sm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1982,6 +1617,9 @@ static int cyberiada_destroy_sm(CyberiadaSM* sm)
|
|||||||
{
|
{
|
||||||
CyberiadaEdge *edge, *e;
|
CyberiadaEdge *edge, *e;
|
||||||
if (sm) {
|
if (sm) {
|
||||||
|
if (sm->bounding_rect) {
|
||||||
|
free(sm->bounding_rect);
|
||||||
|
}
|
||||||
if (sm->nodes) {
|
if (sm->nodes) {
|
||||||
cyberiada_destroy_all_nodes(sm->nodes);
|
cyberiada_destroy_all_nodes(sm->nodes);
|
||||||
}
|
}
|
||||||
@@ -2266,7 +1904,7 @@ static int cyberiada_get_element_text(char* buffer, size_t buffer_len,
|
|||||||
|
|
||||||
static int cyberiada_xml_read_coord(xmlNode* xml_node,
|
static int cyberiada_xml_read_coord(xmlNode* xml_node,
|
||||||
const char* attr_name,
|
const char* attr_name,
|
||||||
float* result)
|
double* result)
|
||||||
{
|
{
|
||||||
char buffer[MAX_STR_LEN];
|
char buffer[MAX_STR_LEN];
|
||||||
size_t buffer_len = sizeof(buffer) - 1;
|
size_t buffer_len = sizeof(buffer) - 1;
|
||||||
@@ -2275,7 +1913,7 @@ static int cyberiada_xml_read_coord(xmlNode* xml_node,
|
|||||||
attr_name) != CYBERIADA_NO_ERROR) {
|
attr_name) != CYBERIADA_NO_ERROR) {
|
||||||
return CYBERIADA_BAD_PARAMETER;
|
return CYBERIADA_BAD_PARAMETER;
|
||||||
}
|
}
|
||||||
*result = (float)atof(buffer);
|
*result = (double)atof(buffer);
|
||||||
return CYBERIADA_NO_ERROR;
|
return CYBERIADA_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2528,8 +2166,8 @@ static GraphProcessorState handle_node_geometry(xmlNode* xml_node,
|
|||||||
}
|
}
|
||||||
if (type == cybNodeInitial) {
|
if (type == cybNodeInitial) {
|
||||||
current->geometry_point = cyberiada_new_point();
|
current->geometry_point = cyberiada_new_point();
|
||||||
current->geometry_point->x = rect->x + rect->width / 2.0f;
|
current->geometry_point->x = rect->x + rect->width / 2.0;
|
||||||
current->geometry_point->y = rect->y + rect->height / 2.0f;
|
current->geometry_point->y = rect->y + rect->height / 2.0;
|
||||||
free(rect);
|
free(rect);
|
||||||
return gpsNodeStart;
|
return gpsNodeStart;
|
||||||
} else if (type == cybNodeComment) {
|
} else if (type == cybNodeComment) {
|
||||||
@@ -2574,8 +2212,10 @@ static GraphProcessorState handle_node_title(xmlNode* xml_node,
|
|||||||
return gpsInvalid;
|
return gpsInvalid;
|
||||||
}
|
}
|
||||||
cyberiada_get_element_text(buffer, buffer_len, xml_node);
|
cyberiada_get_element_text(buffer, buffer_len, xml_node);
|
||||||
/* DEBUG("Set node %s title %s\n", current->id, buffer); */
|
DEBUG("Set node %s title '%s'\n", current->id, buffer);
|
||||||
cyberiada_copy_string(&(current->title), &(current->title_len), buffer);
|
cyberiada_copy_string(&(current->title), &(current->title_len), buffer);
|
||||||
|
cyberiada_string_trim(current->title);
|
||||||
|
DEBUG("After trim: '%s'\n", current->title);
|
||||||
return gpsNodeAction;
|
return gpsNodeAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2658,7 +2298,7 @@ static GraphProcessorState handle_edge_label(xmlNode* xml_node,
|
|||||||
{
|
{
|
||||||
char buffer[MAX_STR_LEN];
|
char buffer[MAX_STR_LEN];
|
||||||
size_t buffer_len = sizeof(buffer) - 1;
|
size_t buffer_len = sizeof(buffer) - 1;
|
||||||
float x = 0.0, y = 0.0;
|
double x = 0.0, y = 0.0;
|
||||||
CyberiadaEdge *current;
|
CyberiadaEdge *current;
|
||||||
CyberiadaSM* sm = doc->state_machines;
|
CyberiadaSM* sm = doc->state_machines;
|
||||||
while (sm->next) sm = sm->next;
|
while (sm->next) sm = sm->next;
|
||||||
@@ -2870,6 +2510,7 @@ static GraphProcessorState handle_node_data(xmlNode* xml_node,
|
|||||||
}
|
}
|
||||||
/* DEBUG("Set node %s title %s\n", current->id, buffer); */
|
/* DEBUG("Set node %s title %s\n", current->id, buffer); */
|
||||||
cyberiada_copy_string(&(current->title), &(current->title_len), buffer);
|
cyberiada_copy_string(&(current->title), &(current->title_len), buffer);
|
||||||
|
cyberiada_string_trim(current->title);
|
||||||
} else if (strcmp(key_name, GRAPHML_CYB_KEY_STATE_MACHINE_NAME) == 0) {
|
} else if (strcmp(key_name, GRAPHML_CYB_KEY_STATE_MACHINE_NAME) == 0) {
|
||||||
if (current->type != cybNodeSM) {
|
if (current->type != cybNodeSM) {
|
||||||
ERROR("Using state machine key outside the graph element in %s\n", current->id);
|
ERROR("Using state machine key outside the graph element in %s\n", current->id);
|
||||||
@@ -3466,40 +3107,74 @@ static int cyberiada_check_graphml_ns(xmlNode* root, CyberiadaXMLFormat* format)
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* GraphML reader interface
|
* GraphML reader interface
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
static int cyberiada_process_decode_sm_document(CyberiadaDocument* cyb_doc, xmlDoc* doc, CyberiadaXMLFormat format, int flags)
|
||||||
int cyberiada_read_sm_document(CyberiadaDocument* cyb_doc, const char* filename, CyberiadaXMLFormat format)
|
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
xmlDoc* doc = NULL;
|
|
||||||
xmlNode* root = NULL;
|
xmlNode* root = NULL;
|
||||||
CyberiadaSM* sm;
|
CyberiadaSM* sm;
|
||||||
NamesList* nl = NULL;
|
NamesList* nl = NULL;
|
||||||
|
int geom_flags;
|
||||||
|
|
||||||
|
if (flags & CYBERIADA_FLAG_ROUND_GEOMETRY) {
|
||||||
|
ERROR("Round geometry flag is not supported on import\n");
|
||||||
|
return CYBERIADA_BAD_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & CYBERIADA_FLAG_SKIP_GEOMETRY &&
|
||||||
|
flags != CYBERIADA_FLAG_SKIP_GEOMETRY) {
|
||||||
|
ERROR("The skip geometry flag is not compatible with other flags\n");
|
||||||
|
return CYBERIADA_BAD_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
geom_flags = flags & (CYBERIADA_FLAG_ABSOLUTE_GEOMETRY |
|
||||||
|
CYBERIADA_FLAG_LEFTTOP_LOCAL_GEOMETRY |
|
||||||
|
CYBERIADA_FLAG_CENTER_LOCAL_GEOMETRY);
|
||||||
|
if (geom_flags &&
|
||||||
|
geom_flags != CYBERIADA_FLAG_ABSOLUTE_GEOMETRY &&
|
||||||
|
geom_flags != CYBERIADA_FLAG_LEFTTOP_LOCAL_GEOMETRY &&
|
||||||
|
geom_flags != CYBERIADA_FLAG_CENTER_LOCAL_GEOMETRY) {
|
||||||
|
ERROR("Single geometry flag (abs, left-top, center) can be used at the same time\n");
|
||||||
|
return CYBERIADA_BAD_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(flags & CYBERIADA_FLAG_SKIP_GEOMETRY) && !geom_flags) {
|
||||||
|
/* set default geometry flag */
|
||||||
|
flags |= CYBERIADA_FLAG_CENTER_LOCAL_GEOMETRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
geom_flags = flags & (CYBERIADA_FLAG_CENTER_EDGE_GEOMETRY |
|
||||||
|
CYBERIADA_FLAG_LEFTTOP_BORDER_EDGE_GEOMETRY |
|
||||||
|
CYBERIADA_FLAG_CENTER_BORDER_EDGE_GEOMETRY);
|
||||||
|
if (geom_flags &&
|
||||||
|
geom_flags != CYBERIADA_FLAG_CENTER_EDGE_GEOMETRY &&
|
||||||
|
geom_flags != CYBERIADA_FLAG_LEFTTOP_BORDER_EDGE_GEOMETRY &&
|
||||||
|
geom_flags != CYBERIADA_FLAG_CENTER_BORDER_EDGE_GEOMETRY) {
|
||||||
|
ERROR("Single geometry edge flag (border, center) can be used at the same time\n");
|
||||||
|
return CYBERIADA_BAD_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(flags & CYBERIADA_FLAG_SKIP_GEOMETRY) && !geom_flags) {
|
||||||
|
/* set default edge geometry flag */
|
||||||
|
flags |= CYBERIADA_FLAG_CENTER_BORDER_EDGE_GEOMETRY;
|
||||||
|
}
|
||||||
|
|
||||||
cyberiada_init_sm_document(cyb_doc);
|
cyberiada_init_sm_document(cyb_doc);
|
||||||
cyberiada_init_action_regexps();
|
cyberiada_init_action_regexps();
|
||||||
xmlInitParser();
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
/* parse the file and get the DOM */
|
|
||||||
if ((doc = xmlReadFile(filename, NULL, 0)) == NULL) {
|
|
||||||
ERROR("error: could not parse file %s\n", filename);
|
|
||||||
res = CYBERIADA_XML_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the root element node */
|
/* get the root element node */
|
||||||
root = xmlDocGetRootElement(doc);
|
root = xmlDocGetRootElement(doc);
|
||||||
|
|
||||||
if (strcmp((const char*)root->name, GRAPHML_GRAPHML_ELEMENT) != 0) {
|
if (strcmp((const char*)root->name, GRAPHML_GRAPHML_ELEMENT) != 0) {
|
||||||
ERROR("error: could not find GraphML root node %s\n", filename);
|
ERROR("error: could not find GraphML root node\n");
|
||||||
res = CYBERIADA_XML_ERROR;
|
res = CYBERIADA_XML_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check whether the xml is graphml */
|
/* check whether the xml is graphml */
|
||||||
if (cyberiada_check_graphml_ns(root, &format)) {
|
if (cyberiada_check_graphml_ns(root, &format)) {
|
||||||
ERROR("error: no valid graphml namespace in %s\n", filename);
|
ERROR("error: no valid graphml namespace\n");
|
||||||
res = CYBERIADA_XML_ERROR;
|
res = CYBERIADA_XML_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -3512,8 +3187,7 @@ int cyberiada_read_sm_document(CyberiadaDocument* cyb_doc, const char* filename,
|
|||||||
} else if (format == cybxmlCyberiada10) {
|
} else if (format == cybxmlCyberiada10) {
|
||||||
res = cyberiada_decode_cyberiada_xml(root, cyb_doc);
|
res = cyberiada_decode_cyberiada_xml(root, cyb_doc);
|
||||||
} else {
|
} else {
|
||||||
ERROR("error: unsupported GraphML format of file %s\n",
|
ERROR("error: unsupported GraphML format of file\n");
|
||||||
filename);
|
|
||||||
res = CYBERIADA_XML_ERROR;
|
res = CYBERIADA_XML_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -3523,31 +3197,77 @@ int cyberiada_read_sm_document(CyberiadaDocument* cyb_doc, const char* filename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (sm = cyb_doc->state_machines; sm; sm = sm->next) {
|
for (sm = cyb_doc->state_machines; sm; sm = sm->next) {
|
||||||
if ((res = cyberiada_graphs_reconstruct_nodes(sm->nodes, &nl)) != CYBERIADA_NO_ERROR) {
|
if ((res = cyberiada_graphs_reconstruct_node_identifiers(sm->nodes, &nl)) != CYBERIADA_NO_ERROR) {
|
||||||
ERROR("error: cannot reconstruct graph nodes file %s\n",
|
ERROR("error: cannot reconstruct graph nodes' indentifiers\n");
|
||||||
filename);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((res = cyberiada_graphs_reconstruct_edges(cyb_doc, &nl)) != CYBERIADA_NO_ERROR) {
|
if ((res = cyberiada_graphs_reconstruct_edge_identifiers(cyb_doc, &nl)) != CYBERIADA_NO_ERROR) {
|
||||||
ERROR("error: cannot reconstruct graph edges from file %s\n",
|
ERROR("error: cannot reconstruct graph edges' identifier\n");
|
||||||
filename);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format == cybxmlYED && res == CYBERIADA_NO_ERROR) {
|
if (res == CYBERIADA_NO_ERROR) {
|
||||||
cyberiada_graphs_reconstruct_geometry_from_yed(cyb_doc);
|
if (flags & CYBERIADA_FLAG_SKIP_GEOMETRY) {
|
||||||
|
cyberiada_clean_document_geometry(cyb_doc);
|
||||||
|
} else {
|
||||||
|
cyberiada_import_document_geometry(cyb_doc, flags, format);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
cyberiada_free_name_list(&nl);
|
cyberiada_free_name_list(&nl);
|
||||||
cyberiada_free_action_regexps();
|
cyberiada_free_action_regexps();
|
||||||
xmlFreeDoc(doc);
|
|
||||||
xmlCleanupParser();
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cyberiada_read_sm_document(CyberiadaDocument* cyb_doc, const char* filename,
|
||||||
|
CyberiadaXMLFormat format, int flags)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
xmlDoc* doc = NULL;
|
||||||
|
xmlInitParser();
|
||||||
|
|
||||||
|
/* parse the file and get the DOM */
|
||||||
|
if ((doc = xmlReadFile(filename, NULL, 0)) == NULL) {
|
||||||
|
ERROR("error: could not parse file %s\n", filename);
|
||||||
|
xmlCleanupParser();
|
||||||
|
return CYBERIADA_XML_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = cyberiada_process_decode_sm_document(cyb_doc, doc, format, flags);
|
||||||
|
|
||||||
|
if (doc) {
|
||||||
|
xmlFreeDoc(doc);
|
||||||
|
}
|
||||||
|
xmlCleanupParser();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cyberiada_decode_sm_document(CyberiadaDocument* cyb_doc, const char* buffer, size_t buffer_size,
|
||||||
|
CyberiadaXMLFormat format, int flags)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
xmlDoc* doc = NULL;
|
||||||
|
xmlInitParser();
|
||||||
|
|
||||||
|
/* parse the file and get the DOM */
|
||||||
|
if ((doc = xmlReadMemory(buffer, buffer_size, XML_READMEMORY_BASENAME, NULL, 0)) == NULL) {
|
||||||
|
ERROR("error: could not read buffer\n");
|
||||||
|
xmlCleanupParser();
|
||||||
|
return CYBERIADA_XML_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = cyberiada_process_decode_sm_document(cyb_doc, doc, format, flags);
|
||||||
|
|
||||||
|
if (doc) {
|
||||||
|
xmlFreeDoc(doc);
|
||||||
|
}
|
||||||
|
xmlCleanupParser();
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
@@ -4695,11 +4415,38 @@ static int cyberiada_write_sm_document_yed(CyberiadaDocument* doc, xmlTextWriter
|
|||||||
* GraphML writer interface
|
* GraphML writer interface
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
int cyberiada_write_sm_document(CyberiadaDocument* doc, const char* filename, CyberiadaXMLFormat format)
|
static int cyberiada_process_encode_sm_document(CyberiadaDocument* doc, xmlTextWriterPtr writer,
|
||||||
|
CyberiadaXMLFormat format, int flags)
|
||||||
{
|
{
|
||||||
CyberiadaDocument* copy_doc = NULL;
|
CyberiadaDocument* copy_doc = NULL;
|
||||||
xmlTextWriterPtr writer;
|
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
if (flags & CYBERIADA_FLAG_RECONSTRUCT_GEOMETRY) {
|
||||||
|
ERROR("Geometry reconstructioin flag is not supported on export\n");
|
||||||
|
return CYBERIADA_BAD_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & CYBERIADA_FLAG_SKIP_GEOMETRY) {
|
||||||
|
if (flags != CYBERIADA_FLAG_SKIP_GEOMETRY) {
|
||||||
|
ERROR("The skip geometry flag is not compatible with other flags\n");
|
||||||
|
return CYBERIADA_BAD_PARAMETER;
|
||||||
|
}
|
||||||
|
if (format == cybxmlYED) {
|
||||||
|
ERROR("Skip geometry flag is not allowed for YED export\n");
|
||||||
|
return CYBERIADA_BAD_PARAMETER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CYBERIADA_FLAG_ABSOLUTE_GEOMETRY |
|
||||||
|
CYBERIADA_FLAG_LEFTTOP_LOCAL_GEOMETRY |
|
||||||
|
CYBERIADA_FLAG_CENTER_LOCAL_GEOMETRY |
|
||||||
|
CYBERIADA_FLAG_LEFTTOP_BORDER_EDGE_GEOMETRY |
|
||||||
|
CYBERIADA_FLAG_CENTER_BORDER_EDGE_GEOMETRY |
|
||||||
|
CYBERIADA_FLAG_CENTER_EDGE_GEOMETRY) {
|
||||||
|
|
||||||
|
ERROR("Geometry flags (abs, left-top, center) & edge geometry flags are not allowed for export\n");
|
||||||
|
return CYBERIADA_BAD_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
if (format != cybxmlCyberiada10 && format != cybxmlYED) {
|
if (format != cybxmlCyberiada10 && format != cybxmlYED) {
|
||||||
ERROR("unsupported SM format for write: %d\n", format);
|
ERROR("unsupported SM format for write: %d\n", format);
|
||||||
@@ -4711,16 +4458,12 @@ int cyberiada_write_sm_document(CyberiadaDocument* doc, const char* filename, Cy
|
|||||||
return CYBERIADA_BAD_PARAMETER;
|
return CYBERIADA_BAD_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlInitParser();
|
if (format == cybxmlYED && (!doc->state_machines ||doc->state_machines->next)) {
|
||||||
|
ERROR("YED format supports only single SM documents\n");
|
||||||
|
return CYBERIADA_BAD_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
writer = xmlNewTextWriterFilename(filename, 0);
|
|
||||||
if (!writer) {
|
|
||||||
ERROR("cannot open xml writter for file %s\n", filename);
|
|
||||||
res = CYBERIADA_XML_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = xmlTextWriterStartDocument(writer, NULL, GRAPHML_XML_ENCODING, NULL);
|
res = xmlTextWriterStartDocument(writer, NULL, GRAPHML_XML_ENCODING, NULL);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
ERROR("error writing xml start document: %d\n", res);
|
ERROR("error writing xml start document: %d\n", res);
|
||||||
@@ -4728,22 +4471,20 @@ int cyberiada_write_sm_document(CyberiadaDocument* doc, const char* filename, Cy
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
copy_doc = cyberiada_copy_sm_document(doc);
|
||||||
|
|
||||||
|
if (flags & CYBERIADA_FLAG_SKIP_GEOMETRY) {
|
||||||
|
cyberiada_clean_document_geometry(copy_doc);
|
||||||
|
} else {
|
||||||
|
cyberiada_export_document_geometry(copy_doc, flags, format);
|
||||||
|
}
|
||||||
if (format == cybxmlYED) {
|
if (format == cybxmlYED) {
|
||||||
if (!doc->state_machines || doc->state_machines->next) {
|
|
||||||
ERROR("YED format supports only single SM documents\n");
|
|
||||||
res = CYBERIADA_BAD_PARAMETER;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
copy_doc = cyberiada_copy_sm_document(doc);
|
|
||||||
cyberiada_graphs_reconstruct_geometry_to_yed(copy_doc);
|
|
||||||
|
|
||||||
res = cyberiada_write_sm_document_yed(copy_doc, writer);
|
res = cyberiada_write_sm_document_yed(copy_doc, writer);
|
||||||
|
|
||||||
cyberiada_destroy_sm_document(copy_doc);
|
|
||||||
} else if (format == cybxmlCyberiada10) {
|
} else if (format == cybxmlCyberiada10) {
|
||||||
res = cyberiada_write_sm_document_cyberiada(doc, writer);
|
res = cyberiada_write_sm_document_cyberiada(copy_doc, writer);
|
||||||
}
|
}
|
||||||
|
cyberiada_destroy_sm_document(copy_doc);
|
||||||
|
|
||||||
if (res != CYBERIADA_NO_ERROR) {
|
if (res != CYBERIADA_NO_ERROR) {
|
||||||
ERROR("error writing xml %d\n", res);
|
ERROR("error writing xml %d\n", res);
|
||||||
res = CYBERIADA_XML_ERROR;
|
res = CYBERIADA_XML_ERROR;
|
||||||
@@ -4760,12 +4501,72 @@ int cyberiada_write_sm_document(CyberiadaDocument* doc, const char* filename, Cy
|
|||||||
res = CYBERIADA_NO_ERROR;
|
res = CYBERIADA_NO_ERROR;
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
xmlFreeTextWriter(writer);
|
|
||||||
xmlCleanupParser();
|
|
||||||
|
|
||||||
if (res != CYBERIADA_NO_ERROR) {
|
if (res != CYBERIADA_NO_ERROR) {
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
return CYBERIADA_NO_ERROR;
|
return CYBERIADA_NO_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cyberiada_write_sm_document(CyberiadaDocument* doc, const char* filename,
|
||||||
|
CyberiadaXMLFormat format, int flags)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
xmlTextWriterPtr writer = NULL;
|
||||||
|
xmlInitParser();
|
||||||
|
writer = xmlNewTextWriterFilename(filename, 0);
|
||||||
|
if (!writer) {
|
||||||
|
ERROR("cannot open xml writter for file %s\n", filename);
|
||||||
|
xmlCleanupParser();
|
||||||
|
return CYBERIADA_XML_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = cyberiada_process_encode_sm_document(doc, writer, format, flags);
|
||||||
|
|
||||||
|
xmlFreeTextWriter(writer);
|
||||||
|
xmlCleanupParser();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cyberiada_encode_sm_document(CyberiadaDocument* doc, char** buffer, size_t* buffer_size,
|
||||||
|
CyberiadaXMLFormat format, int flags)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
xmlBufferPtr xml_buffer;
|
||||||
|
xmlTextWriterPtr writer = NULL;
|
||||||
|
|
||||||
|
xmlInitParser();
|
||||||
|
xml_buffer = xmlBufferCreate();
|
||||||
|
if (!xml_buffer) {
|
||||||
|
ERROR("cannot create xml buffer\n");
|
||||||
|
xmlCleanupParser();
|
||||||
|
return CYBERIADA_XML_ERROR;
|
||||||
|
}
|
||||||
|
writer = xmlNewTextWriterMemory(xml_buffer, 0);
|
||||||
|
if (!writer) {
|
||||||
|
ERROR("cannot create buffer writter\n");
|
||||||
|
xmlBufferFree(xml_buffer);
|
||||||
|
xmlCleanupParser();
|
||||||
|
return CYBERIADA_XML_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = cyberiada_process_encode_sm_document(doc, writer, format, flags);
|
||||||
|
|
||||||
|
if (res == CYBERIADA_NO_ERROR) {
|
||||||
|
size_t size = xml_buffer->use;
|
||||||
|
*buffer = (char*)malloc(size + 1);
|
||||||
|
memcpy(*buffer, xml_buffer->content, size);
|
||||||
|
(*buffer)[size] = 0;
|
||||||
|
*buffer_size = size;
|
||||||
|
} else {
|
||||||
|
*buffer = NULL;
|
||||||
|
*buffer_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlBufferFree(xml_buffer);
|
||||||
|
xmlFreeTextWriter(writer);
|
||||||
|
xmlCleanupParser();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|||||||
106
cyberiadaml.h
106
cyberiadaml.h
@@ -70,11 +70,11 @@ typedef enum {
|
|||||||
/* SM node & transitions geometry */
|
/* SM node & transitions geometry */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float x, y;
|
double x, y;
|
||||||
} CyberiadaPoint;
|
} CyberiadaPoint;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float x, y, width, height;
|
double x, y, width, height;
|
||||||
} CyberiadaRect;
|
} CyberiadaRect;
|
||||||
|
|
||||||
typedef struct _CyberiadaPolyline {
|
typedef struct _CyberiadaPolyline {
|
||||||
@@ -108,14 +108,26 @@ typedef struct _CyberiadaLink {
|
|||||||
size_t ref_len;
|
size_t ref_len;
|
||||||
} CyberiadaLink;
|
} CyberiadaLink;
|
||||||
|
|
||||||
/* SM node (state) */
|
/* SM node (state)
|
||||||
|
*
|
||||||
|
* Comment on the node geometry:
|
||||||
|
* - if the top-level node (state machine) has geometry, it is calculated in
|
||||||
|
* absolute coordinates (x: left-to-right, y: top-to-bottom);
|
||||||
|
* - if the state machine has no geometry, the first level nodes (comporite states, initial
|
||||||
|
* vertexes, etc.) are calculated in absolute coordinates;
|
||||||
|
* - the child nodes are calculated in local coordinates relative to the _center_ of the
|
||||||
|
* parent node.
|
||||||
|
*
|
||||||
|
* NOTE: this geomerty is different from the Cyberiada GraphML 1.0 / YED formats geometry
|
||||||
|
* and is being converted during the document import/export.
|
||||||
|
*/
|
||||||
typedef struct _CyberiadaNode {
|
typedef struct _CyberiadaNode {
|
||||||
CyberiadaNodeType type;
|
CyberiadaNodeType type;
|
||||||
char* id;
|
char* id;
|
||||||
size_t id_len;
|
size_t id_len;
|
||||||
char* title;
|
char* title;
|
||||||
size_t title_len;
|
size_t title_len;
|
||||||
CyberiadaAction* actions; /* for simple & composite nodes */
|
CyberiadaAction* actions; /* for simple & composite state nodes */
|
||||||
CyberiadaCommentData* comment_data; /* for comments */
|
CyberiadaCommentData* comment_data; /* for comments */
|
||||||
CyberiadaLink* link; /* for submachine states */
|
CyberiadaLink* link; /* for submachine states */
|
||||||
CyberiadaPoint* geometry_point; /* for some pseudostates & final state */
|
CyberiadaPoint* geometry_point; /* for some pseudostates & final state */
|
||||||
@@ -139,7 +151,19 @@ typedef struct _CyberiadaCommentSubject {
|
|||||||
size_t fragment_len;
|
size_t fragment_len;
|
||||||
} CyberiadaCommentSubject;
|
} CyberiadaCommentSubject;
|
||||||
|
|
||||||
/* SM edge (transition) */
|
/* SM edge (transition)
|
||||||
|
*
|
||||||
|
* Comment on the edge geometry:
|
||||||
|
* - the source and target points are calculated in local coordinates relative
|
||||||
|
* to the center of the corresponding source/target node;
|
||||||
|
* - the label point is calculated in local coordinates relative to the geometrical
|
||||||
|
* center of the edge (based on the bounding rectangle);
|
||||||
|
* - the polyline points are calculated in local coordinated relative to the center of
|
||||||
|
* the source node.
|
||||||
|
*
|
||||||
|
* NOTE: this geomerty is different from the Cyberiada GraphML 1.0 / YED formats geometry
|
||||||
|
* and is being converted during the document import/export.
|
||||||
|
*/
|
||||||
typedef struct _CyberiadaEdge {
|
typedef struct _CyberiadaEdge {
|
||||||
CyberiadaEdgeType type;
|
CyberiadaEdgeType type;
|
||||||
char* id;
|
char* id;
|
||||||
@@ -165,6 +189,7 @@ typedef struct _CyberiadaEdge {
|
|||||||
typedef struct _CyberiadaSM {
|
typedef struct _CyberiadaSM {
|
||||||
CyberiadaNode* nodes;
|
CyberiadaNode* nodes;
|
||||||
CyberiadaEdge* edges;
|
CyberiadaEdge* edges;
|
||||||
|
CyberiadaRect* bounding_rect;
|
||||||
struct _CyberiadaSM* next;
|
struct _CyberiadaSM* next;
|
||||||
} CyberiadaSM;
|
} CyberiadaSM;
|
||||||
|
|
||||||
@@ -211,22 +236,52 @@ typedef struct {
|
|||||||
char* markup_language;
|
char* markup_language;
|
||||||
size_t markup_language_len;
|
size_t markup_language_len;
|
||||||
} CyberiadaMetainformation;
|
} CyberiadaMetainformation;
|
||||||
|
|
||||||
|
/* SM document node coordinates format */
|
||||||
|
typedef enum {
|
||||||
|
cybCoordNone = 0, /* no geometry information */
|
||||||
|
cybCoordAbsolute = 1, /* absolute coordinates (used in YED) */
|
||||||
|
cybCoordLeftTop = 2, /* left-top-oriented local coordinates (used in Cyberiada10) */
|
||||||
|
cybCoordLocalCenter = 4, /* center-oriented local coordinates (used by default) */
|
||||||
|
} CyberiadaGeometryCoordFormat;
|
||||||
|
|
||||||
|
/* SM document edges source/target point placement & coordinates format */
|
||||||
|
typedef enum {
|
||||||
|
cybEdgeNone = 0,
|
||||||
|
cybEdgeLocalCenter = 1, /* source & target points are bind to a node's center */
|
||||||
|
cybEdgeLeftTopBorder = 2, /* source & target points are placed on a node's border with left-top coordinates */
|
||||||
|
cybEdgeCenterBorder = 4, /* source & target points are placed on a node's border with center coordinates */
|
||||||
|
} CyberiadaGeometryEdgeFormat;
|
||||||
|
|
||||||
/* SM document */
|
/* SM document */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char* format; /* SM document format string */
|
char* format; /* SM document format string (additional info) */
|
||||||
size_t format_len; /* SM document format string length */
|
size_t format_len; /* SM document format string length */
|
||||||
CyberiadaMetainformation* meta_info; /* SM document metainformation */
|
CyberiadaMetainformation* meta_info; /* SM document metainformation */
|
||||||
CyberiadaSM* state_machines; /* State machines */
|
CyberiadaGeometryCoordFormat geometry_format; /* SM document geometry coordinates format */
|
||||||
|
CyberiadaGeometryEdgeFormat edge_geom_format; /* SM document edges geometry format */
|
||||||
|
CyberiadaSM* state_machines; /* State machines */
|
||||||
} CyberiadaDocument;
|
} CyberiadaDocument;
|
||||||
|
|
||||||
/* Cyberiada GraphML Library supported formats */
|
/* Cyberiada GraphML Library supported formats */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
cybxmlCyberiada10 = 0, /* Cyberiada 1.0 format */
|
cybxmlCyberiada10 = 0, /* Cyberiada 1.0 format */
|
||||||
cybxmlYED = 1, /* Old YED-based Berloga/Ostranna format */
|
cybxmlYED = 1, /* Old YED-based Berloga/Ostranna format */
|
||||||
cybxmlUnknown = 99 /* Format is not specified */
|
cybxmlUnknown = 99 /* Format is not specified */
|
||||||
} CyberiadaXMLFormat;
|
} CyberiadaXMLFormat;
|
||||||
|
|
||||||
|
/* Cyberiada GraphML Library import/export flags */
|
||||||
|
#define CYBERIADA_FLAG_NO 0
|
||||||
|
#define CYBERIADA_FLAG_ABSOLUTE_GEOMETRY 1 /* convert imported geometry to absolute coordinates */
|
||||||
|
#define CYBERIADA_FLAG_LEFTTOP_LOCAL_GEOMETRY 2 /* convert imported geometry to left-top-oriented local coordinates */
|
||||||
|
#define CYBERIADA_FLAG_CENTER_LOCAL_GEOMETRY 4 /* convert imported geometry to center-oriented local coordinates */
|
||||||
|
#define CYBERIADA_FLAG_CENTER_EDGE_GEOMETRY 8 /* convert imported geometry to center edge coordinates */
|
||||||
|
#define CYBERIADA_FLAG_LEFTTOP_BORDER_EDGE_GEOMETRY 16 /* convert imported geometry to border edge coordinates (left-top) */
|
||||||
|
#define CYBERIADA_FLAG_CENTER_BORDER_EDGE_GEOMETRY 32 /* convert imported geometry to border edge coordinates (center) */
|
||||||
|
#define CYBERIADA_FLAG_RECONSTRUCT_GEOMETRY 64 /* reconstruct absent node/edge geometry on import */
|
||||||
|
#define CYBERIADA_FLAG_SKIP_GEOMETRY 128 /* skip geometry node/edge during import/export */
|
||||||
|
#define CYBERIADA_FLAG_ROUND_GEOMETRY 256 /* export geometry with round coordinates to 0.001 */
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* The Cyberiada GraphML error codes
|
* The Cyberiada GraphML error codes
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
@@ -263,10 +318,19 @@ typedef enum {
|
|||||||
|
|
||||||
/* Read an XML file and decode the SM structure */
|
/* Read an XML file and decode the SM structure */
|
||||||
/* Allocate the SM document structure first */
|
/* Allocate the SM document structure first */
|
||||||
int cyberiada_read_sm_document(CyberiadaDocument* doc, const char* filename, CyberiadaXMLFormat format);
|
int cyberiada_read_sm_document(CyberiadaDocument* doc, const char* filename, CyberiadaXMLFormat format, int flags);
|
||||||
|
|
||||||
/* Encode the SM document structure and write the data to an XML file */
|
/* Encode the SM document structure and write the data to an XML file */
|
||||||
int cyberiada_write_sm_document(CyberiadaDocument* doc, const char* filename, CyberiadaXMLFormat format);
|
int cyberiada_write_sm_document(CyberiadaDocument* doc, const char* filename, CyberiadaXMLFormat format, int flags);
|
||||||
|
|
||||||
|
/* Decode the SM structure */
|
||||||
|
/* Allocate the SM document structure first */
|
||||||
|
int cyberiada_decode_sm_document(CyberiadaDocument* doc, const char* buffer, size_t buffer_size,
|
||||||
|
CyberiadaXMLFormat format, int flags);
|
||||||
|
|
||||||
|
/* Encode the SM document structure */
|
||||||
|
int cyberiada_encode_sm_document(CyberiadaDocument* doc, char** buffer, size_t* buffer_size,
|
||||||
|
CyberiadaXMLFormat format, int flags);
|
||||||
|
|
||||||
/* Print the SM structure to stdout */
|
/* Print the SM structure to stdout */
|
||||||
int cyberiada_print_sm_document(CyberiadaDocument* doc);
|
int cyberiada_print_sm_document(CyberiadaDocument* doc);
|
||||||
@@ -301,7 +365,15 @@ typedef enum {
|
|||||||
/* Allocate and initialize the SM polyline structure in memory */
|
/* Allocate and initialize the SM polyline structure in memory */
|
||||||
CyberiadaPolyline* cyberiada_new_polyline(void);
|
CyberiadaPolyline* cyberiada_new_polyline(void);
|
||||||
|
|
||||||
/* Allocate and initialize the SM metainformation structure in memory */
|
/* Free the SM polyline structure in memory */
|
||||||
|
int cyberiada_destroy_polyline(CyberiadaPolyline* polyline);
|
||||||
|
|
||||||
|
/* Change the SM document geometry format and convert the SMs geometry data */
|
||||||
|
int cyberiada_convert_document_geometry(CyberiadaDocument* doc,
|
||||||
|
CyberiadaGeometryCoordFormat new_format,
|
||||||
|
CyberiadaGeometryEdgeFormat new_edge_format);
|
||||||
|
|
||||||
|
/* Allocate and initialize the SM metainformation structure in memory */
|
||||||
CyberiadaMetainformation* cyberiada_new_meta(void);
|
CyberiadaMetainformation* cyberiada_new_meta(void);
|
||||||
|
|
||||||
/* Initialize and copy string. Use this function to initialize strings in Cyberiada structures */
|
/* Initialize and copy string. Use this function to initialize strings in Cyberiada structures */
|
||||||
|
|||||||
1209
geometry.c
Normal file
1209
geometry.c
Normal file
File diff suppressed because it is too large
Load Diff
59
geometry.h
Normal file
59
geometry.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* The Cyberiada GraphML library implemention
|
||||||
|
*
|
||||||
|
* The geometry utilities
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 Alexey Fedoseev <aleksey@fedoseev.net>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see https://www.gnu.org/licenses/
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifndef __CYBERIADA_GEOMETRY_H
|
||||||
|
#define __CYBERIADA_GEOMRTRY_H
|
||||||
|
|
||||||
|
#include "cyberiadaml.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* The Cyberiada GraphML geometry utilities
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
CyberiadaPoint* cyberiada_new_point(void);
|
||||||
|
CyberiadaPoint* cyberiada_copy_point(CyberiadaPoint* src);
|
||||||
|
|
||||||
|
CyberiadaRect* cyberiada_new_rect(void);
|
||||||
|
CyberiadaRect* cyberiada_copy_rect(CyberiadaRect* src);
|
||||||
|
|
||||||
|
CyberiadaPolyline* cyberiada_new_polyline(void);
|
||||||
|
CyberiadaPolyline* cyberiada_copy_polyline(CyberiadaPolyline* src);
|
||||||
|
int cyberiada_destroy_polyline(CyberiadaPolyline* polyline);
|
||||||
|
|
||||||
|
int cyberiada_clean_document_geometry(CyberiadaDocument* doc);
|
||||||
|
int cyberiada_convert_document_geometry(CyberiadaDocument* doc,
|
||||||
|
CyberiadaGeometryCoordFormat new_format,
|
||||||
|
CyberiadaGeometryEdgeFormat new_edge_format);
|
||||||
|
int cyberiada_import_document_geometry(CyberiadaDocument* doc,
|
||||||
|
int flags, CyberiadaXMLFormat file_format);
|
||||||
|
int cyberiada_export_document_geometry(CyberiadaDocument* doc,
|
||||||
|
int flags, CyberiadaXMLFormat file_format);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user