diff --git a/Test/FMI3/fmi3_import_terminals_and_icons_test.cpp b/Test/FMI3/fmi3_import_terminals_and_icons_test.cpp index 20e7ec59..f3827ce5 100644 --- a/Test/FMI3/fmi3_import_terminals_and_icons_test.cpp +++ b/Test/FMI3/fmi3_import_terminals_and_icons_test.cpp @@ -28,6 +28,20 @@ TEST_CASE("Test parse terminals and icons") { REQUIRE(xml != nullptr); REQUIRE(fmi3_import_get_has_terminals_and_icons(xml) != 0); + SECTION("Testing graphicalRepresentation") { + // TODO: FMI2 + // TODO + ; + SECTION("Testing coordinateSystem") { + // TODO: + ; + } + SECTION("Testing Icon") { + // TODO: + ; + } + } + SECTION("Testing getting terminal by name") { fmi_import_terminal_t* term; @@ -148,3 +162,67 @@ TEST_CASE("Test clearing of attribute buffer with invalid elements") { REQUIRE(fmi3_testutil_get_num_problems(tfmu) == 3); fmi3_testutil_import_free(tfmu); } + +TEST_CASE("Empty graphical representation: Takes default") { + const char* xmldir = FMI3_TEST_XML_DIR "/terminals_and_icons/valid/empty_graphicalRepresentation"; + fmi3_testutil_import_t* tfmu = fmi3_testutil_parse_xml_with_log(xmldir); + fmi3_import_t* fmu = tfmu->fmu; + REQUIRE(fmu != nullptr); // successful parse of modelDescription + REQUIRE(fmi3_import_get_has_terminals_and_icons(fmu) == 1); + + // TODO: Verify default coordinate system + scaling + no icon + + REQUIRE(fmi3_testutil_get_num_problems(tfmu) == 0); + fmi3_testutil_import_free(tfmu); +} + +TEST_CASE("Incomplete graphicaRepresentation->coordinateSystem: Takes default") { + const char* xmldir = FMI3_TEST_XML_DIR "/terminals_and_icons/invalid/incomplete_coordinateSystem"; + fmi3_testutil_import_t* tfmu = fmi3_testutil_parse_xml_with_log(xmldir); + fmi3_import_t* fmu = tfmu->fmu; + REQUIRE(fmu != nullptr); // successful parse of modelDescription + REQUIRE(fmi3_import_get_has_terminals_and_icons(fmu) == 1); + + REQUIRE(fmi3_testutil_log_contains(tfmu, "Parsing XML element 'CoordinateSystem': required attribute 'x2' not found")); + REQUIRE(fmi3_testutil_log_contains(tfmu, "Parsing XML element 'CoordinateSystem': required attribute 'y2' not found")); + + REQUIRE(fmi3_testutil_log_contains(tfmu, "Failed to parse complete CoordinateSystem, using default system (-100, -100), (100, 100).")); + + // TODO: Verify default coordinate system + no icon + + REQUIRE(fmi3_testutil_get_num_problems(tfmu) == 3); + fmi3_testutil_import_free(tfmu); +} + +TEST_CASE("Not well-defined graphicaRepresentation->coordinateSystem") { + const char* xmldir = FMI3_TEST_XML_DIR "/terminals_and_icons/invalid/flipped_coordinateSystem"; + fmi3_testutil_import_t* tfmu = fmi3_testutil_parse_xml_with_log(xmldir); + fmi3_import_t* fmu = tfmu->fmu; + REQUIRE(fmu != nullptr); // successful parse of modelDescription + REQUIRE(fmi3_import_get_has_terminals_and_icons(fmu) == 1); + + REQUIRE(fmi3_testutil_log_contains(tfmu, "'CoordinateSystem' not well-defined, requires x1 = 100.000000 < x2 = -100.000000.")); + REQUIRE(fmi3_testutil_log_contains(tfmu, "'CoordinateSystem' not well-defined, requires y1 = 100.000000 < y2 = -100.000000.")); + + // TODO: Verify coordinates are stored anyways + + REQUIRE(fmi3_testutil_get_num_problems(tfmu) == 2); + fmi3_testutil_import_free(tfmu); +} + +TEST_CASE("Incomplete graphicalRepresentation->Icon") { + const char* xmldir = FMI3_TEST_XML_DIR "/terminals_and_icons/invalid/incomplete_icon"; + fmi3_testutil_import_t* tfmu = fmi3_testutil_parse_xml_with_log(xmldir); + fmi3_import_t* fmu = tfmu->fmu; + REQUIRE(fmu != nullptr); // successful parse of modelDescription + REQUIRE(fmi3_import_get_has_terminals_and_icons(fmu) == 1); + + REQUIRE(fmi3_testutil_log_contains(tfmu, "Parsing XML element 'Icon': required attribute 'x2' not found")); + REQUIRE(fmi3_testutil_log_contains(tfmu, "Parsing XML element 'Icon': required attribute 'y2' not found")); + REQUIRE(fmi3_testutil_log_contains(tfmu, "Failed to parse complete Icon.")); + + // TODO: Verify there is no icon + + REQUIRE(fmi3_testutil_get_num_problems(tfmu) == 3); + fmi3_testutil_import_free(tfmu); +} diff --git a/Test/FMI3/parser_test_xmls/terminals_and_icons/invalid/flipped_coordinateSystem/modelDescription.xml b/Test/FMI3/parser_test_xmls/terminals_and_icons/invalid/flipped_coordinateSystem/modelDescription.xml new file mode 100644 index 00000000..4e24d976 --- /dev/null +++ b/Test/FMI3/parser_test_xmls/terminals_and_icons/invalid/flipped_coordinateSystem/modelDescription.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Test/FMI3/parser_test_xmls/terminals_and_icons/invalid/flipped_coordinateSystem/terminalsAndIcons/terminalsAndIcons.xml b/Test/FMI3/parser_test_xmls/terminals_and_icons/invalid/flipped_coordinateSystem/terminalsAndIcons/terminalsAndIcons.xml new file mode 100644 index 00000000..d58d0580 --- /dev/null +++ b/Test/FMI3/parser_test_xmls/terminals_and_icons/invalid/flipped_coordinateSystem/terminalsAndIcons/terminalsAndIcons.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Test/FMI3/parser_test_xmls/terminals_and_icons/invalid/incomplete_coordinateSystem/modelDescription.xml b/Test/FMI3/parser_test_xmls/terminals_and_icons/invalid/incomplete_coordinateSystem/modelDescription.xml new file mode 100644 index 00000000..4e24d976 --- /dev/null +++ b/Test/FMI3/parser_test_xmls/terminals_and_icons/invalid/incomplete_coordinateSystem/modelDescription.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Test/FMI3/parser_test_xmls/terminals_and_icons/invalid/incomplete_coordinateSystem/terminalsAndIcons/terminalsAndIcons.xml b/Test/FMI3/parser_test_xmls/terminals_and_icons/invalid/incomplete_coordinateSystem/terminalsAndIcons/terminalsAndIcons.xml new file mode 100644 index 00000000..55ca3a4e --- /dev/null +++ b/Test/FMI3/parser_test_xmls/terminals_and_icons/invalid/incomplete_coordinateSystem/terminalsAndIcons/terminalsAndIcons.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/Test/FMI3/parser_test_xmls/terminals_and_icons/invalid/incomplete_icon/modelDescription.xml b/Test/FMI3/parser_test_xmls/terminals_and_icons/invalid/incomplete_icon/modelDescription.xml new file mode 100644 index 00000000..4e24d976 --- /dev/null +++ b/Test/FMI3/parser_test_xmls/terminals_and_icons/invalid/incomplete_icon/modelDescription.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Test/FMI3/parser_test_xmls/terminals_and_icons/invalid/incomplete_icon/terminalsAndIcons/terminalsAndIcons.xml b/Test/FMI3/parser_test_xmls/terminals_and_icons/invalid/incomplete_icon/terminalsAndIcons/terminalsAndIcons.xml new file mode 100644 index 00000000..072bef7c --- /dev/null +++ b/Test/FMI3/parser_test_xmls/terminals_and_icons/invalid/incomplete_icon/terminalsAndIcons/terminalsAndIcons.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Test/FMI3/parser_test_xmls/terminals_and_icons/valid/basic/terminalsAndIcons/terminalsAndIcons.xml b/Test/FMI3/parser_test_xmls/terminals_and_icons/valid/basic/terminalsAndIcons/terminalsAndIcons.xml index f14a6f37..1551ffeb 100644 --- a/Test/FMI3/parser_test_xmls/terminals_and_icons/valid/basic/terminalsAndIcons/terminalsAndIcons.xml +++ b/Test/FMI3/parser_test_xmls/terminals_and_icons/valid/basic/terminalsAndIcons/terminalsAndIcons.xml @@ -2,7 +2,7 @@ - + diff --git a/Test/FMI3/parser_test_xmls/terminals_and_icons/valid/empty_graphicalRepresentation/modelDescription.xml b/Test/FMI3/parser_test_xmls/terminals_and_icons/valid/empty_graphicalRepresentation/modelDescription.xml new file mode 100644 index 00000000..4e24d976 --- /dev/null +++ b/Test/FMI3/parser_test_xmls/terminals_and_icons/valid/empty_graphicalRepresentation/modelDescription.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Test/FMI3/parser_test_xmls/terminals_and_icons/valid/empty_graphicalRepresentation/terminalsAndIcons/terminalsAndIcons.xml b/Test/FMI3/parser_test_xmls/terminals_and_icons/valid/empty_graphicalRepresentation/terminalsAndIcons/terminalsAndIcons.xml new file mode 100644 index 00000000..6ad178b9 --- /dev/null +++ b/Test/FMI3/parser_test_xmls/terminals_and_icons/valid/empty_graphicalRepresentation/terminalsAndIcons/terminalsAndIcons.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/XML/include/FMI/fmi_xml_terminals_and_icons.h b/src/XML/include/FMI/fmi_xml_terminals_and_icons.h index 3d1f5ee7..99176e77 100644 --- a/src/XML/include/FMI/fmi_xml_terminals_and_icons.h +++ b/src/XML/include/FMI/fmi_xml_terminals_and_icons.h @@ -68,7 +68,22 @@ int fmi2_xml_terminals_and_icons_set_model_description(fmi_xml_terminals_and_ico int fmi3_xml_terminals_and_icons_set_model_description(fmi_xml_terminals_and_icons_t* termIcon, fmi3_xml_model_description_t* md); +/* Top level */ int fmi_xml_get_has_terminals_and_icons(fmi_xml_terminals_and_icons_t* termIcon); + +/* Graphical Representation */ +int fmi_xml_get_has_graphical_representation(fmi_xml_terminals_and_icons_t* termIcon); +/* coordinateSystem*/ +int fmi_xml_get_graphical_representation_system_coordinates(fmi_xml_graphicalRepresentation_t* graphRepr, + double* x1, double* y1, double* x2, double* y2); +int fmi_xml_get_graphical_representation_suggested_scaling(fmi_xml_graphicalRepresentation_t* graphRepr, + double* suggested_scaling); +/* icon */ +int fmi_xml_get_graphical_representation_has_icon(fmi_xml_graphicalRepresentation_t* graphRepr); +int fmi_xml_get_graphical_representation_icon_coordinates(fmi_xml_graphicalRepresentation_t* graphRepr, + double* x1, double* y1, double* x2, double* y2); + +/* Terminals */ fmi_xml_terminal_t* fmi_xml_get_terminal_by_name(fmi_xml_terminals_and_icons_t* termIcon, const char* name); const char* fmi_xml_get_terminal_name(fmi_xml_terminal_t* term); diff --git a/src/XML/src/FMI/fmi_xml_terminals_and_icons.c b/src/XML/src/FMI/fmi_xml_terminals_and_icons.c index f910538f..959311e1 100644 --- a/src/XML/src/FMI/fmi_xml_terminals_and_icons.c +++ b/src/XML/src/FMI/fmi_xml_terminals_and_icons.c @@ -189,13 +189,26 @@ int fmi_xml_handle_CoordinateSystem(fmi3_xml_parser_context_t* context, const ch ret |= fmi3_xml_parse_attr_as_float64(context, FMI_ELM_TERMICON(fmi_xml_elmID_termIcon_CoordinateSystem), FMI_ATTR_TERMICON(fmi_termIcon_attr_id_y2), 1, &(coordSys->y2), 100); ret |= fmi3_xml_parse_attr_as_float64(context, FMI_ELM_TERMICON(fmi_xml_elmID_termIcon_CoordinateSystem), - FMI_ATTR_TERMICON(fmi_termIcon_attr_id_suggestedScalingFactorTo_mm), 1, &(coordSys->suggestedScalingFactorTo_mm), 100); + FMI_ATTR_TERMICON(fmi_termIcon_attr_id_suggestedScalingFactorTo_mm), 1, &(coordSys->suggestedScalingFactorTo_mm), 0.1); if (ret) { - // TODO: Log; clearly state that full coordinate system is discarded and default is taken instead? + fmi3_xml_parse_error(context, "Failed to parse complete CoordinateSystem, using default system (-100, -100), (100, 100)."); + coordSys->x1 = -100; + coordSys->y1 = -100; + coordSys->x2 = 100; + coordSys->y2 = 100; + coordSys->suggestedScalingFactorTo_mm = 0.1; return 1; } } else { - // TODO: Error check; warning is + /* SPEC: [...] where the coordinates of the first point shall be less than the coordinates of the second point. */ + if (coordSys->x1 >= coordSys->x2) { + fmi3_xml_parse_warning(context, "'CoordinateSystem' not well-defined, requires x1 = %f < x2 = %f.", + coordSys->x1, coordSys->x2); + } + if (coordSys->y1 >= coordSys->y2) { + fmi3_xml_parse_warning(context, "'CoordinateSystem' not well-defined, requires y1 = %f < y2 = %f.", + coordSys->y1, coordSys->y2); + } } return 0; } @@ -205,24 +218,26 @@ int fmi_xml_handle_Icon(fmi3_xml_parser_context_t* context, const char* data) { fmi_xml_graphicalRepresentation_t* graphRepr = termIcon->graphicalRepresentation; if (!data) { int ret; - graphRepr->icon = (fmi_xml_icon_t*)context->callbacks->calloc(1, sizeof(fmi_xml_icon_t)); - if (!(graphRepr->icon)) { + fmi_xml_icon_t* icon = (fmi_xml_icon_t*)context->callbacks->calloc(1, sizeof(fmi_xml_icon_t)); + if (!icon) { fmi3_xml_parse_fatal(context, "Could not allocate memory"); return 1; } ret = 0; ret |= fmi3_xml_parse_attr_as_float64(context, FMI_ELM_TERMICON(fmi_xml_elmID_termIcon_Icon), - FMI_ATTR_TERMICON(fmi_termIcon_attr_id_x1), 1, &(graphRepr->icon->x1), 0); + FMI_ATTR_TERMICON(fmi_termIcon_attr_id_x1), 1, &(icon->x1), 0); ret |= fmi3_xml_parse_attr_as_float64(context, FMI_ELM_TERMICON(fmi_xml_elmID_termIcon_Icon), - FMI_ATTR_TERMICON(fmi_termIcon_attr_id_y1), 1, &(graphRepr->icon->y1), 0); + FMI_ATTR_TERMICON(fmi_termIcon_attr_id_y1), 1, &(icon->y1), 0); ret |= fmi3_xml_parse_attr_as_float64(context, FMI_ELM_TERMICON(fmi_xml_elmID_termIcon_Icon), - FMI_ATTR_TERMICON(fmi_termIcon_attr_id_x2), 1, &(graphRepr->icon->x2), 0); + FMI_ATTR_TERMICON(fmi_termIcon_attr_id_x2), 1, &(icon->x2), 0); ret |= fmi3_xml_parse_attr_as_float64(context, FMI_ELM_TERMICON(fmi_xml_elmID_termIcon_Icon), - FMI_ATTR_TERMICON(fmi_termIcon_attr_id_y2), 1, &(graphRepr->icon->y2), 0); + FMI_ATTR_TERMICON(fmi_termIcon_attr_id_y2), 1, &(icon->y2), 0); if (ret) { - // TODO: Error message? + fmi3_xml_parse_error(context, "Failed to parse complete Icon."); + context->callbacks->free(icon); // Discard element return 1; } + graphRepr->icon = icon; } else { ; } @@ -327,17 +342,69 @@ int fmi_xml_handle_TerminalGraphicalRepresentation(fmi3_xml_parser_context_t* co return 0; } + +/* Top level*/ int fmi_xml_get_has_terminals_and_icons(fmi_xml_terminals_and_icons_t* termIcon) { return termIcon ? 1 : 0; } -fmi_xml_terminal_t* fmi_xml_get_terminal_by_name(fmi_xml_terminals_and_icons_t* termIcon, const char* name){ - if (!name) return NULL; +/* Graphical Representation */ +int fmi_xml_get_has_graphical_representation(fmi_xml_terminals_and_icons_t* termIcon) { + if (!termIcon) { + return 0; + } + return termIcon->graphicalRepresentation ? 1 : 0; +} + +int fmi_xml_get_graphical_representation_system_coordinates(fmi_xml_graphicalRepresentation_t* graphRepr, + double* x1, double* y1, double* x2, double* y2) { + if (!graphRepr || (!graphRepr->coordinateSystem)) { + return 1; + } + *x1 = graphRepr->coordinateSystem->x1; + *y1 = graphRepr->coordinateSystem->y1; + *x2 = graphRepr->coordinateSystem->x2; + *y2 = graphRepr->coordinateSystem->y2; + return 0; +} + +int fmi_xml_get_graphical_representation_suggested_scaling(fmi_xml_graphicalRepresentation_t* graphRepr, + double* suggested_scaling) { + if (!graphRepr || (!graphRepr->coordinateSystem)) { + return 1; + } + *suggested_scaling = graphRepr->coordinateSystem->suggestedScalingFactorTo_mm; + return 0; +} + +int fmi_xml_get_graphical_representation_has_icon(fmi_xml_graphicalRepresentation_t* graphRepr) { + if (!graphRepr) { + return 0; + } + return graphRepr->icon ? 1 : 0; +} + +int fmi_xml_get_graphical_representation_icon_coordinates(fmi_xml_graphicalRepresentation_t* graphRepr, + double* x1, double* y1, double* x2, double* y2) { + if (!graphRepr || (!graphRepr->icon)) { + return 1; + } + *x1 = graphRepr->icon->x1; + *y1 = graphRepr->icon->y1; + *x2 = graphRepr->icon->x2; + *y2 = graphRepr->icon->y2; + return 0; +} + +/* Terminals*/ +fmi_xml_terminal_t* fmi_xml_get_terminal_by_name(fmi_xml_terminals_and_icons_t* termIcon, const char* name) { + if (!name) { + return NULL; + } jm_named_ptr key, *found; key.name = name; found = jm_vector_bsearch(jm_named_ptr)(&termIcon->terminalsByName, &key, jm_compare_named); - if (!found) return NULL; - return found->ptr; + return found ? found->ptr : NULL; } const char* fmi_xml_get_terminal_name(fmi_xml_terminal_t* term) { diff --git a/src/XML/src/FMI/fmi_xml_terminals_and_icons_impl.h b/src/XML/src/FMI/fmi_xml_terminals_and_icons_impl.h index c06bd58a..53de2482 100644 --- a/src/XML/src/FMI/fmi_xml_terminals_and_icons_impl.h +++ b/src/XML/src/FMI/fmi_xml_terminals_and_icons_impl.h @@ -48,18 +48,12 @@ struct fmi_xml_graphicalRepresentation_t { }; struct fmi_xml_coordinateSystem_t { - double x1; - double y1; - double x2; - double y2; + double x1, y1, x2, y2; double suggestedScalingFactorTo_mm; }; struct fmi_xml_icon_t { - double x1; - double y1; - double x2; - double y2; + double x1, y1, x2, y2; }; struct fmi_xml_terminal_t {