576 double date_value = floor(date.
year * 366.25) + date.
JulianDay();
577 date_value += double(time.
hour) / 24. + double(time.
minute) / 1440. + double(time.
second) / 86400.;
580 if (timeseries_data.find(label) == timeseries_data.end()) {
581 timeseries_data[label].push_back(value);
582 timeseries_datevalue[label].push_back(date_value);
588 auto it_data = timeseries_data[label].begin();
589 auto it_datevalue = timeseries_datevalue[label].begin();
592 if (date_value < timeseries_datevalue[label].front()) {
593 timeseries_data[label].insert(it_data, value);
594 timeseries_datevalue[label].insert(it_datevalue, date_value);
597 timeseries_data[label].insert(it_data + 1, value);
598 timeseries_datevalue[label].insert(it_datevalue + 1, date_value);
602 if (date_value < timeseries_datevalue[label].front()) {
603 timeseries_data[label].insert(it_data, value);
604 timeseries_datevalue[label].insert(it_datevalue, date_value);
606 }
else if (date_value > timeseries_datevalue[label].back()) {
607 timeseries_data[label].push_back(value);
608 timeseries_datevalue[label].push_back(date_value);
613 for (
uint t = 0; t < N - 1; t++) {
614 if (date_value == timeseries_datevalue[label].at(t)) {
615 std::cerr <<
"WARNING (Context::addTimeseriesData): Skipping duplicate timeseries date/time." << std::endl;
618 if (date_value > timeseries_datevalue[label].at(t) && date_value < timeseries_datevalue[label].at(t + 1)) {
619 timeseries_data[label].insert(it_data + t + 1, value);
620 timeseries_datevalue[label].insert(it_datevalue + t + 1, date_value);
627 helios_runtime_error(
"ERROR (Context::addTimeseriesData): Failed to insert timeseries data for unknown reason.");
639 if (timeseries_data.find(label) == timeseries_data.end()) {
640 helios_runtime_error(
"ERROR (setCurrentTimeseriesData): Timeseries variable `" + std::string(label) +
"' does not exist.");
643 double date_value = floor(date.
year * 366.25) + date.
JulianDay();
644 date_value += double(time.
hour) / 24. + double(time.
minute) / 1440. + double(time.
second) / 86400.;
646 double tmin = timeseries_datevalue.at(label).front();
647 double tmax = timeseries_datevalue.at(label).back();
649 if (date_value < tmin) {
650 std::cerr <<
"WARNING (queryTimeseriesData): Timeseries date and time is outside of the range of the data. Using the earliest data point in the timeseries." << std::endl;
651 return timeseries_data.at(label).front();
652 }
else if (date_value > tmax) {
653 std::cerr <<
"WARNING (queryTimeseriesData): Timeseries date and time is outside of the range of the data. Using the latest data point in the timeseries." << std::endl;
654 return timeseries_data.at(label).back();
657 if (timeseries_datevalue.at(label).empty()) {
658 std::cerr <<
"WARNING (queryTimeseriesData): timeseries " << label <<
" does not contain any data." << std::endl;
660 }
else if (timeseries_datevalue.at(label).size() == 1) {
661 return timeseries_data.at(label).front();
664 bool success =
false;
665 for (i = 0; i < timeseries_data.at(label).size() - 1; i++) {
666 if (date_value >= timeseries_datevalue.at(label).at(i) && date_value <= timeseries_datevalue.at(label).at(i + 1)) {
673 helios_runtime_error(
"ERROR (queryTimeseriesData): Failed to query timeseries data for unknown reason.");
676 double xminus = timeseries_data.at(label).at(i);
677 double xplus = timeseries_data.at(label).at(i + 1);
679 double tminus = timeseries_datevalue.at(label).at(i);
680 double tplus = timeseries_datevalue.at(label).at(i + 1);
682 return float(xminus + (xplus - xminus) * (date_value - tminus) / (tplus - tminus));
795 float local_xmin = 1e8, local_xmax = -1e8;
796 float local_ymin = 1e8, local_ymax = -1e8;
797 float local_zmin = 1e8, local_zmax = -1e8;
800#pragma omp for nowait
801 for (
int i = 0; i < (int) UUIDs.size(); i++) {
803 const std::vector<vec3> &verts = getPrimitivePointer_private(UUIDs[i])->getVertices();
805 for (
const auto &vert: verts) {
806 local_xmin = std::min(local_xmin, vert.x);
807 local_xmax = std::max(local_xmax, vert.x);
808 local_ymin = std::min(local_ymin, vert.y);
809 local_ymax = std::max(local_ymax, vert.y);
810 local_zmin = std::min(local_zmin, vert.z);
811 local_zmax = std::max(local_zmax, vert.z);
818 xbounds.
x = std::min(xbounds.
x, local_xmin);
819 xbounds.
y = std::max(xbounds.
y, local_xmax);
820 ybounds.
x = std::min(ybounds.
x, local_ymin);
821 ybounds.
y = std::max(ybounds.
y, local_ymax);
822 zbounds.
x = std::min(zbounds.
x, local_zmin);
823 zbounds.
y = std::max(zbounds.
y, local_zmax);
829 for (
uint UUID: UUIDs) {
830 const std::vector<vec3> &verts = getPrimitivePointer_private(UUID)->getVertices();
832 for (
auto &vert: verts) {
833 if (vert.x < xbounds.
x) {
835 }
else if (vert.x > xbounds.
y) {
838 if (vert.y < ybounds.
x) {
840 }
else if (vert.y > ybounds.
y) {
843 if (vert.z < zbounds.
x) {
845 }
else if (vert.z > zbounds.
y) {
1074 if (objects.find(ObjID) == objects.end()) {
1075 helios_runtime_error(
"ERROR (Context::copyObject): Object ID of " + std::to_string(ObjID) +
" not found in the context.");
1078 ObjectType type = objects.at(ObjID)->getObjectType();
1083 for (
uint p: UUIDs_copy) {
1084 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
1087 const std::string &texturefile = objects.at(ObjID)->getTextureFile();
1094 auto *tile_new = (
new Tile(currentObjectID, UUIDs_copy, subdiv, texturefile.c_str(),
this));
1096 objects[currentObjectID] = tile_new;
1102 auto *sphere_new = (
new Sphere(currentObjectID, UUIDs_copy, subdiv, texturefile.c_str(),
this));
1104 objects[currentObjectID] = sphere_new;
1108 const std::vector<vec3> &nodes = o->
getNodes();
1114 auto *tube_new = (
new Tube(currentObjectID, UUIDs_copy, nodes, radius, colors, triangle_vertices, subdiv, texturefile.c_str(),
this));
1116 objects[currentObjectID] = tube_new;
1122 auto *box_new = (
new Box(currentObjectID, UUIDs_copy, subdiv, texturefile.c_str(),
this));
1124 objects[currentObjectID] = box_new;
1130 auto *disk_new = (
new Disk(currentObjectID, UUIDs_copy, subdiv, texturefile.c_str(),
this));
1132 objects[currentObjectID] = disk_new;
1134 auto *polymesh_new = (
new Polymesh(currentObjectID, UUIDs_copy, texturefile.c_str(),
this));
1136 objects[currentObjectID] = polymesh_new;
1144 auto *cone_new = (
new Cone(currentObjectID, UUIDs_copy, nodes.at(0), nodes.at(1), radius.at(0), radius.at(1), subdiv, texturefile.c_str(),
this));
1146 objects[currentObjectID] = cone_new;
1157 return currentObjectID - 1;
1161 std::vector<uint> output_object_IDs;
1162 output_object_IDs.resize(IDs.size());
1163 uint passed_count = 0;
1165 for (
uint i = 0; i < IDs.size(); i++) {
1171 if (strcmp(comparator,
"<") == 0) {
1172 if (
float(
R) < threshold) {
1173 output_object_IDs.at(passed_count) = IDs.at(i);
1176 }
else if (strcmp(comparator,
">") == 0) {
1177 if (
float(
R) > threshold) {
1178 output_object_IDs.at(passed_count) = IDs.at(i);
1181 }
else if (strcmp(comparator,
"=") == 0) {
1182 if (
float(
R) == threshold) {
1183 output_object_IDs.at(passed_count) = IDs.at(i);
1191 if (strcmp(comparator,
"<") == 0) {
1192 if (
R < threshold) {
1193 output_object_IDs.at(passed_count) = IDs.at(i);
1196 }
else if (strcmp(comparator,
">") == 0) {
1197 if (
R > threshold) {
1198 output_object_IDs.at(passed_count) = IDs.at(i);
1201 }
else if (strcmp(comparator,
"=") == 0) {
1202 if (
R == threshold) {
1203 output_object_IDs.at(passed_count) = IDs.at(i);
1211 if (strcmp(comparator,
"<") == 0) {
1212 if (
float(
R) < threshold) {
1213 output_object_IDs.at(passed_count) = IDs.at(i);
1216 }
else if (strcmp(comparator,
">") == 0) {
1217 if (
float(
R) > threshold) {
1218 output_object_IDs.at(passed_count) = IDs.at(i);
1221 }
else if (strcmp(comparator,
"=") == 0) {
1222 if (
float(
R) == threshold) {
1223 output_object_IDs.at(passed_count) = IDs.at(i);
1228 std::cerr <<
"WARNING: Object data not of type UINT, INT, or FLOAT. Filtering for other types not yet supported." << std::endl;
1233 output_object_IDs.resize(passed_count);
1235 return output_object_IDs;
1478 std::vector<uint> tile_ObjectIDs;
1479 std::vector<uint> textured_tile_ObjectIDs;
1482 std::vector<std::string> tex;
1484 for (
uint ObjID: ObjIDs) {
1487 helios_runtime_error(
"ERROR (Context::setTileObjectSubdivisionCount): Object ID of " + std::to_string(ObjID) +
" not found in the context.");
1493 std::cerr <<
"WARNING (Context::setTileObjectSubdivisionCount): ObjectID " << ObjID <<
" is not a tile object. Skipping..." << std::endl;
1495 std::cerr <<
"WARNING (Context::setTileObjectSubdivisionCount): ObjectID " << ObjID <<
" is missing primitives. Skipping..." << std::endl;
1498 Patch *p = getPatchPointer_private(
getObjectPointer(ObjID)->getPrimitiveUUIDs().at(0));
1499 if (!p->hasTexture()) {
1500 tile_ObjectIDs.push_back(ObjID);
1502 textured_tile_ObjectIDs.push_back(ObjID);
1503 tex.push_back(p->getTextureFile());
1509 for (
unsigned int tile_ObjectID: tile_ObjectIDs) {
1511 const std::vector<uint> &UUIDs_old = current_object_pointer->
getPrimitiveUUIDs();
1519 std::vector<uint> UUIDs_new =
addTile(center, size, rotation, new_subdiv, color);
1521 for (
uint UUID: UUIDs_new) {
1522 getPrimitivePointer_private(UUID)->setParentObjectID(tile_ObjectID);
1531 sort(tex.begin(), tex.end());
1532 std::vector<std::string>::iterator it;
1533 it = std::unique(tex.begin(), tex.end());
1534 tex.resize(std::distance(tex.begin(), it));
1537 std::vector<uint> object_templates;
1538 std::vector<std::vector<uint>> template_primitives;
1539 for (
uint j = 0; j < tex.size(); j++) {
1542 object_templates.emplace_back(object_template);
1544 template_primitives.emplace_back(object_primitives);
1549 for (
uint i = 0; i < textured_tile_ObjectIDs.size(); i++) {
1552 std::string current_texture_file = current_object_pointer->
getTextureFile();
1562 for (
uint j = 0; j < tex.size(); j++) {
1564 if (current_texture_file == tex.at(j)) {
1566 std::vector<uint> new_primitives =
copyPrimitive(template_primitives.at(j));
1589 current_object_pointer->
translate(center);
1601 std::vector<uint> tile_ObjectIDs;
1602 std::vector<uint> textured_tile_ObjectIDs;
1604 std::vector<std::string> tex;
1606 for (
uint ObjID: ObjIDs) {
1609 helios_runtime_error(
"ERROR (Context::setTileObjectSubdivisionCount): Object ID of " + std::to_string(ObjID) +
" not found in the context.");
1615 std::cerr <<
"WARNING (Context::setTileObjectSubdivisionCount): ObjectID " << ObjID <<
" is not a tile object. Skipping..." << std::endl;
1617 std::cerr <<
"WARNING (Context::setTileObjectSubdivisionCount): ObjectID " << ObjID <<
" is missing primitives. Skipping..." << std::endl;
1620 Patch *p = getPatchPointer_private(
getObjectPointer(ObjID)->getPrimitiveUUIDs().at(0));
1621 if (!p->hasTexture()) {
1622 tile_ObjectIDs.push_back(ObjID);
1624 textured_tile_ObjectIDs.push_back(ObjID);
1625 tex.push_back(p->getTextureFile());
1631 for (
uint i = 0; i < tile_ObjectIDs.size(); i++) {
1641 float tile_area = current_object_pointer->
getArea();
1644 float subpatch_dimension = sqrtf(tile_area / area_ratio);
1645 float subpatch_per_x = size.
x / subpatch_dimension;
1646 float subpatch_per_y = size.
y / subpatch_dimension;
1648 float option_1_AR = (tile_area / (size.
x / ceil(subpatch_per_x) * size.
y / floor(subpatch_per_y))) - area_ratio;
1649 float option_2_AR = (tile_area / (size.
x / floor(subpatch_per_x) * size.
y / ceil(subpatch_per_y))) - area_ratio;
1652 if ((
int) area_ratio == 1) {
1654 }
else if (option_1_AR >= option_2_AR) {
1655 new_subdiv =
make_int2(ceil(subpatch_per_x), floor(subpatch_per_y));
1657 new_subdiv =
make_int2(floor(subpatch_per_x), ceil(subpatch_per_y));
1661 std::vector<uint> UUIDs_new =
addTile(center, size, rotation, new_subdiv, color);
1663 for (
uint UUID: UUIDs_new) {
1664 getPrimitivePointer_private(UUID)->setParentObjectID(tile_ObjectIDs.at(i));
1673 sort(tex.begin(), tex.end());
1674 std::vector<std::string>::iterator it;
1675 it = std::unique(tex.begin(), tex.end());
1676 tex.resize(std::distance(tex.begin(), it));
1682 std::vector<uint> object_templates;
1683 std::vector<std::vector<uint>> template_primitives;
1684 for (
uint j = 0; j < tex.size(); j++) {
1687 for (
uint i = 0; i < textured_tile_ObjectIDs.size(); i++) {
1690 std::string current_texture_file_b = current_object_pointer_b->
getTextureFile();
1692 if (current_texture_file_b == tex.at(j)) {
1700 vec2 tile_size = current_object_pointer->
getSize();
1701 float tile_area = current_object_pointer->
getArea();
1704 float subpatch_dimension = sqrtf(tile_area / area_ratio);
1705 float subpatch_per_x = tile_size.
x / subpatch_dimension;
1706 float subpatch_per_y = tile_size.
y / subpatch_dimension;
1708 float option_1_AR = (tile_area / (tile_size.
x / ceil(subpatch_per_x) * tile_size.
y / floor(subpatch_per_y))) - area_ratio;
1709 float option_2_AR = (tile_area / (tile_size.
x / floor(subpatch_per_x) * tile_size.
y / ceil(subpatch_per_y))) - area_ratio;
1712 if ((
int) area_ratio == 1) {
1714 }
else if (option_1_AR >= option_2_AR) {
1715 new_subdiv =
make_int2(ceil(subpatch_per_x), floor(subpatch_per_y));
1717 new_subdiv =
make_int2(floor(subpatch_per_x), ceil(subpatch_per_y));
1722 object_templates.emplace_back(object_template);
1724 template_primitives.emplace_back(object_primitives);
1729 for (
uint i = 0; i < textured_tile_ObjectIDs.size(); i++) {
1733 std::string current_texture_file = current_object_pointer->
getTextureFile();
1743 for (
uint j = 0; j < tex.size(); j++) {
1745 if (current_texture_file == tex.at(j)) {
1747 std::vector<uint> new_primitives =
copyPrimitive(template_primitives.at(j));
1771 current_object_pointer->
translate(center);
1828 if (!validateTextureFileExtenstion(texturefile)) {
1829 helios_runtime_error(
"ERROR (Context::addSphere): Texture file " + std::string(texturefile) +
" is not PNG or JPEG format.");
1830 }
else if (!doesTextureFileExist(texturefile)) {
1831 helios_runtime_error(
"ERROR (Context::addSphere): Texture file " + std::string(texturefile) +
" does not exist.");
1834 std::vector<uint> UUID;
1836 float dtheta =
PI_F / float(Ndivs);
1837 float dphi = 2.0f *
PI_F / float(Ndivs);
1840 for (
int j = 0; j < Ndivs; j++) {
1845 vec3 n0 = v0 - center;
1847 vec3 n1 = v1 - center;
1849 vec3 n2 = v2 - center;
1852 vec2 uv0 =
make_vec2(1.f - atan2f(sin((
float(j) + 0.5f) * dphi), -cos((
float(j) + 0.5f) * dphi)) / (2.f *
PI_F) - 0.5f, 1.f - n0.
z * 0.5f - 0.5f);
1853 vec2 uv1 =
make_vec2(1.f - atan2f(n1.
x, -n1.
y) / (2.f *
PI_F) - 0.5f, 1.f - n1.
z * 0.5f - 0.5f);
1854 vec2 uv2 =
make_vec2(1.f - atan2f(n2.
x, -n2.
y) / (2.f *
PI_F) - 0.5f, 1.f - n2.
z * 0.5f - 0.5f);
1856 if (j == Ndivs - 1) {
1860 uint triangle_uuid =
addTriangle(v0, v1, v2, texturefile, uv0, uv1, uv2);
1862 UUID.push_back(triangle_uuid);
1869 for (
int j = 0; j < Ndivs; j++) {
1874 vec3 n0 = v0 - center;
1876 vec3 n1 = v1 - center;
1878 vec3 n2 = v2 - center;
1881 vec2 uv0 =
make_vec2(1.f - atan2f(sinf((
float(j) + 0.5f) * dphi), -cosf((
float(j) + 0.5f) * dphi)) / (2.f *
PI_F) - 0.5f, 1.f - n0.
z * 0.5f - 0.5f);
1882 vec2 uv1 =
make_vec2(1.f - atan2f(n1.
x, -n1.
y) / (2.f *
PI_F) - 0.5f, 1.f - n1.
z * 0.5f - 0.5f);
1883 vec2 uv2 =
make_vec2(1.f - atan2f(n2.
x, -n2.
y) / (2.f *
PI_F) - 0.5f, 1.f - n2.
z * 0.5f - 0.5f);
1885 if (j == Ndivs - 1) {
1889 uint triangle_uuid =
addTriangle(v0, v1, v2, texturefile, uv0, uv1, uv2);
1891 UUID.push_back(triangle_uuid);
1898 for (
int j = 0; j < Ndivs; j++) {
1899 for (
int i = 1; i < Ndivs - 1; i++) {
1905 vec3 n0 = v0 - center;
1907 vec3 n1 = v1 - center;
1909 vec3 n2 = v2 - center;
1911 vec3 n3 = v3 - center;
1914 vec2 uv0 =
make_vec2(1.f - atan2f(n0.
x, -n0.
y) / (2.f *
PI_F) - 0.5f, 1.f - n0.
z * 0.5f - 0.5f);
1915 vec2 uv1 =
make_vec2(1.f - atan2f(n1.
x, -n1.
y) / (2.f *
PI_F) - 0.5f, 1.f - n1.
z * 0.5f - 0.5f);
1916 vec2 uv2 =
make_vec2(1.f - atan2f(n2.
x, -n2.
y) / (2.f *
PI_F) - 0.5f, 1.f - n2.
z * 0.5f - 0.5f);
1917 vec2 uv3 =
make_vec2(1.f - atan2f(n3.
x, -n3.
y) / (2.f *
PI_F) - 0.5f, 1.f - n3.
z * 0.5f - 0.5f);
1919 if (j == Ndivs - 1) {
1924 uint triangle_uuid1 =
addTriangle(v0, v1, v2, texturefile, uv0, uv1, uv2);
1926 UUID.push_back(triangle_uuid1);
1930 uint triangle_uuid2 =
addTriangle(v0, v2, v3, texturefile, uv0, uv2, uv3);
1932 UUID.push_back(triangle_uuid2);
1982 if (!validateTextureFileExtenstion(texturefile)) {
1983 helios_runtime_error(
"ERROR (Context::addTile): Texture file " + std::string(texturefile) +
" is not PNG or JPEG format.");
1984 }
else if (!doesTextureFileExist(texturefile)) {
1985 helios_runtime_error(
"ERROR (Context::addTile): Texture file " + std::string(texturefile) +
" does not exist.");
1986 }
else if (texture_repeat.
x < 1 || texture_repeat.
y < 1) {
1987 helios_runtime_error(
"ERROR (Context::addTile): Number of texture repeats must be greater than 0.");
1991 int2 repeat = texture_repeat;
1992 repeat.
x = std::min(subdiv.
x, repeat.
x);
1993 repeat.
y = std::min(subdiv.
y, repeat.
y);
1994 while (subdiv.
x % repeat.
x != 0) {
1997 while (subdiv.
y % repeat.
y != 0) {
2001 std::vector<uint> UUID;
2004 subsize.
x = size.
x / float(subdiv.
x);
2005 subsize.
y = size.
y / float(subdiv.
y);
2007 std::vector<helios::vec2> uv(4);
2008 int2 sub_per_repeat;
2009 sub_per_repeat.
x = subdiv.
x / repeat.
x;
2010 sub_per_repeat.
y = subdiv.
y / repeat.
y;
2012 uv_sub.
x = 1.f / float(sub_per_repeat.
x);
2013 uv_sub.
y = 1.f / float(sub_per_repeat.
y);
2015 addTexture(texturefile);
2017 const int2 &sz = textures.at(texturefile).getImageResolution();
2018 if (subdiv.
x >= repeat.
x * sz.
x || subdiv.
y >= repeat.
y * sz.
y) {
2019 helios_runtime_error(
"ERROR (Context::addTile): The resolution of the texture image '" + std::string(texturefile) +
"' is lower than the number of tile subdivisions. Increase resolution of the texture image.");
2022 for (
uint j = 0; j < subdiv.
y; j++) {
2023 for (
uint i = 0; i < subdiv.
x; i++) {
2024 vec3 subcenter =
make_vec3(-0.5f * size.
x + (
float(i) + 0.5f) * subsize.
x, -0.5f * size.
y + (
float(j) + 0.5f) * subsize.
y, 0.f);
2026 uint i_local = i % sub_per_repeat.
x;
2027 uint j_local = j % sub_per_repeat.
y;
2028 uv.at(0) =
make_vec2(
float(i_local) * uv_sub.
x,
float(j_local) * uv_sub.
y);
2029 uv.at(1) =
make_vec2(
float(i_local + 1) * uv_sub.
x,
float(j_local) * uv_sub.
y);
2030 uv.at(2) =
make_vec2(
float(i_local + 1) * uv_sub.
x,
float(j_local + 1) * uv_sub.
y);
2031 uv.at(3) =
make_vec2(
float(i_local) * uv_sub.
x,
float(j_local + 1) * uv_sub.
y);
2033 auto *patch_new = (
new Patch(texturefile, uv, textures, 0, currentUUID));
2035 if (patch_new->getSolidFraction() == 0) {
2040 assert(size.
x > 0.f && size.
y > 0.f);
2041 patch_new->scale(
make_vec3(subsize.
x, subsize.
y, 1));
2043 patch_new->translate(subcenter);
2046 patch_new->rotate(-rotation.
elevation,
"x");
2049 patch_new->rotate(-rotation.
azimuth,
"z");
2052 patch_new->translate(center);
2054 primitives[currentUUID] = patch_new;
2056 UUID.push_back(currentUUID - 1);
2069std::vector<uint>
Context::addTube(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius,
const std::vector<RGBcolor> &color) {
2070 const uint node_count = nodes.size();
2072 if (node_count == 0) {
2074 }
else if (node_count != radius.size()) {
2075 helios_runtime_error(
"ERROR (Context::addTube): Size of `nodes' and `radius' arguments must agree.");
2076 }
else if (node_count != color.size()) {
2077 helios_runtime_error(
"ERROR (Context::addTube): Size of `nodes' and `color' arguments must agree.");
2081 std::vector<float> cfact(radial_subdivisions + 1);
2082 std::vector<float> sfact(radial_subdivisions + 1);
2083 std::vector<std::vector<vec3>> xyz;
2086 vec3 nvec(0.1817f, 0.6198f, 0.7634f);
2088 for (
int j = 0; j < radial_subdivisions + 1; j++) {
2089 cfact[j] = cosf(2.f *
PI_F *
float(j) /
float(radial_subdivisions));
2090 sfact[j] = sinf(2.f *
PI_F *
float(j) /
float(radial_subdivisions));
2093 for (
int i = 0; i < node_count; i++) {
2095 if (radius.at(i) < 0) {
2100 vec.
x = nodes[i + 1].x - nodes[i].x;
2101 vec.
y = nodes[i + 1].y - nodes[i].y;
2102 vec.
z = nodes[i + 1].z - nodes[i].z;
2103 }
else if (i == node_count - 1) {
2104 vec.
x = nodes[i].x - nodes[i - 1].x;
2105 vec.
y = nodes[i].y - nodes[i - 1].y;
2106 vec.
z = nodes[i].z - nodes[i - 1].z;
2108 vec.
x = 0.5f * ((nodes[i].x - nodes[i - 1].x) + (nodes[i + 1].x - nodes[i].x));
2109 vec.
y = 0.5f * ((nodes[i].y - nodes[i - 1].y) + (nodes[i + 1].y - nodes[i].y));
2110 vec.
z = 0.5f * ((nodes[i].z - nodes[i - 1].z) + (nodes[i + 1].z - nodes[i].z));
2115 if (fabs(nvec * vec) > 0.95f) {
2116 nvec =
vec3(0.1817f, 0.6198f, 0.7634f);
2117 if (fabs(nvec * vec) > 0.95f) {
2118 nvec =
vec3(1.0f, 0.0f, 0.0f);
2122 if (fabs(vec.z) > 0.95f) {
2123 nvec =
vec3(1.0f, 0.0f, 0.0f);
2126 convec =
cross(nvec, vec);
2128 nvec =
cross(vec, convec);
2131 for (
int j = 0; j < radial_subdivisions + 1; j++) {
2133 normal.
x = cfact[j] * radius[i] * nvec.
x + sfact[j] * radius[i] * convec.
x;
2134 normal.
y = cfact[j] * radius[i] * nvec.
y + sfact[j] * radius[i] * convec.
y;
2135 normal.
z = cfact[j] * radius[i] * nvec.
z + sfact[j] * radius[i] * convec.
z;
2137 xyz[j][i].x = nodes[i].x + normal.
x;
2138 xyz[j][i].y = nodes[i].y + normal.
y;
2139 xyz[j][i].z = nodes[i].z + normal.
z;
2144 std::vector<uint> UUIDs(2 * (node_count - 1) * radial_subdivisions);
2147 for (
int i = 0; i < node_count - 1; i++) {
2148 for (
int j = 0; j < radial_subdivisions; j++) {
2150 v1 = xyz[j + 1][i + 1];
2153 UUIDs.at(ii) =
addTriangle(v0, v1, v2, color.at(i));
2157 v2 = xyz[j + 1][i + 1];
2159 UUIDs.at(ii + 1) =
addTriangle(v0, v1, v2, color.at(i));
2168std::vector<uint>
Context::addTube(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius,
const char *texturefile) {
2169 if (!validateTextureFileExtenstion(texturefile)) {
2170 helios_runtime_error(
"ERROR (Context::addTube): Texture file " + std::string(texturefile) +
" is not PNG or JPEG format.");
2171 }
else if (!doesTextureFileExist(texturefile)) {
2172 helios_runtime_error(
"ERROR (Context::addTube): Texture file " + std::string(texturefile) +
" does not exist.");
2175 const uint node_count = nodes.size();
2177 if (node_count == 0) {
2179 }
else if (node_count != radius.size()) {
2180 helios_runtime_error(
"ERROR (Context::addTube): Size of `nodes' and `radius' arguments must agree.");
2184 std::vector<float> cfact(radial_subdivisions + 1);
2185 std::vector<float> sfact(radial_subdivisions + 1);
2186 std::vector<std::vector<vec3>> xyz, normal;
2187 std::vector<std::vector<vec2>> uv;
2192 vec3 nvec(0.1817f, 0.6198f, 0.7634f);
2194 for (
int j = 0; j < radial_subdivisions + 1; j++) {
2195 cfact[j] = cosf(2.f *
PI_F *
float(j) /
float(radial_subdivisions));
2196 sfact[j] = sinf(2.f *
PI_F *
float(j) /
float(radial_subdivisions));
2199 for (
int i = 0; i < node_count; i++) {
2201 if (radius.at(i) < 0) {
2206 vec.
x = nodes[i + 1].x - nodes[i].x;
2207 vec.
y = nodes[i + 1].y - nodes[i].y;
2208 vec.
z = nodes[i + 1].z - nodes[i].z;
2209 }
else if (i == node_count - 1) {
2210 vec.
x = nodes[i].x - nodes[i - 1].x;
2211 vec.
y = nodes[i].y - nodes[i - 1].y;
2212 vec.
z = nodes[i].z - nodes[i - 1].z;
2214 vec.
x = 0.5f * ((nodes[i].x - nodes[i - 1].x) + (nodes[i + 1].x - nodes[i].x));
2215 vec.
y = 0.5f * ((nodes[i].y - nodes[i - 1].y) + (nodes[i + 1].y - nodes[i].y));
2216 vec.
z = 0.5f * ((nodes[i].z - nodes[i - 1].z) + (nodes[i + 1].z - nodes[i].z));
2221 if (fabs(nvec * vec) > 0.95f) {
2222 nvec =
vec3(0.1817f, 0.6198f, 0.7634f);
2223 if (fabs(nvec * vec) > 0.95f) {
2224 nvec =
vec3(1.0f, 0.0f, 0.0f);
2228 if (fabs(vec.z) > 0.95f) {
2229 nvec =
vec3(1.0f, 0.0f, 0.0f);
2232 convec =
cross(nvec, vec);
2234 nvec =
cross(vec, convec);
2237 for (
int j = 0; j < radial_subdivisions + 1; j++) {
2238 normal[j][i].
x = cfact[j] * radius[i] * nvec.
x + sfact[j] * radius[i] * convec.
x;
2239 normal[j][i].y = cfact[j] * radius[i] * nvec.
y + sfact[j] * radius[i] * convec.
y;
2240 normal[j][i].z = cfact[j] * radius[i] * nvec.
z + sfact[j] * radius[i] * convec.
z;
2242 xyz[j][i].x = nodes[i].x + normal[j][i].x;
2243 xyz[j][i].y = nodes[i].y + normal[j][i].y;
2244 xyz[j][i].z = nodes[i].z + normal[j][i].z;
2246 uv[j][i].x = float(i) / float(node_count - 1);
2247 uv[j][i].y = float(j) / float(radial_subdivisions);
2249 normal[j][i] = normal[j][i] / radius[i];
2255 std::vector<uint> UUIDs(2 * (node_count - 1) * radial_subdivisions);
2258 for (
int i = 0; i < node_count - 1; i++) {
2259 for (
int j = 0; j < radial_subdivisions; j++) {
2261 v1 = xyz[j + 1][i + 1];
2265 uv1 = uv[j + 1][i + 1];
2268 uint triangle_uuid =
addTriangle(v0, v1, v2, texturefile, uv0, uv1, uv2);
2270 UUIDs.at(ii) = triangle_uuid;
2278 v2 = xyz[j + 1][i + 1];
2282 uv2 = uv[j + 1][i + 1];
2284 uint triangle_uuid2 =
addTriangle(v0, v1, v2, texturefile, uv0, uv1, uv2);
2286 UUIDs.at(ii + 1) = triangle_uuid2;
2289 UUIDs.at(ii + 1) = 0;
2297 UUIDs.erase(std::remove(UUIDs.begin(), UUIDs.end(), 0), UUIDs.end());
2317 std::vector<uint> UUID;
2320 subsize.
x = size.
x / float(subdiv.
x);
2321 subsize.
y = size.
y / float(subdiv.
y);
2322 subsize.
z = size.
z / float(subdiv.
z);
2325 std::vector<uint> U;
2327 if (reverse_normals) {
2332 subcenter = center +
make_vec3(0, 0.5f * size.
y, 0);
2334 UUID.insert(UUID.end(), U.begin(), U.end());
2337 subcenter = center -
make_vec3(0, 0.5f * size.
y, 0);
2339 UUID.insert(UUID.end(), U.begin(), U.end());
2344 subcenter = center +
make_vec3(0.5f * size.
x, 0, 0);
2346 UUID.insert(UUID.end(), U.begin(), U.end());
2349 subcenter = center -
make_vec3(0.5f * size.
x, 0, 0);
2351 UUID.insert(UUID.end(), U.begin(), U.end());
2356 subcenter = center +
make_vec3(0, 0, 0.5f * size.
z);
2358 UUID.insert(UUID.end(), U.begin(), U.end());
2361 subcenter = center -
make_vec3(0, 0, 0.5f * size.
z);
2363 UUID.insert(UUID.end(), U.begin(), U.end());
2369 subcenter = center +
make_vec3(0, 0.5f * size.
y, 0);
2371 UUID.insert(UUID.end(), U.begin(), U.end());
2374 subcenter = center -
make_vec3(0, 0.5f * size.
y, 0);
2376 UUID.insert(UUID.end(), U.begin(), U.end());
2381 subcenter = center +
make_vec3(0.5f * size.
x, 0, 0);
2383 UUID.insert(UUID.end(), U.begin(), U.end());
2386 subcenter = center -
make_vec3(0.5f * size.
x, 0, 0);
2388 UUID.insert(UUID.end(), U.begin(), U.end());
2393 subcenter = center +
make_vec3(0, 0, 0.5f * size.
z);
2395 UUID.insert(UUID.end(), U.begin(), U.end());
2398 subcenter = center -
make_vec3(0, 0, 0.5f * size.
z);
2400 UUID.insert(UUID.end(), U.begin(), U.end());
2407 if (!validateTextureFileExtenstion(texturefile)) {
2408 helios_runtime_error(
"ERROR (Context::addBox): Texture file " + std::string(texturefile) +
" is not PNG or JPEG format.");
2409 }
else if (!doesTextureFileExist(texturefile)) {
2410 helios_runtime_error(
"ERROR (Context::addBox): Texture file " + std::string(texturefile) +
" does not exist.");
2413 std::vector<uint> UUID;
2416 subsize.
x = size.
x / float(subdiv.
x);
2417 subsize.
y = size.
y / float(subdiv.
y);
2418 subsize.
z = size.
z / float(subdiv.
z);
2421 std::vector<uint> U;
2423 if (reverse_normals) {
2428 subcenter = center +
make_vec3(0, 0.5f * size.
y, 0);
2430 UUID.insert(UUID.end(), U.begin(), U.end());
2433 subcenter = center -
make_vec3(0, 0.5f * size.
y, 0);
2435 UUID.insert(UUID.end(), U.begin(), U.end());
2440 subcenter = center +
make_vec3(0.5f * size.
x, 0, 0);
2442 UUID.insert(UUID.end(), U.begin(), U.end());
2445 subcenter = center -
make_vec3(0.5f * size.
x, 0, 0);
2447 UUID.insert(UUID.end(), U.begin(), U.end());
2452 subcenter = center +
make_vec3(0, 0, 0.5f * size.
z);
2454 UUID.insert(UUID.end(), U.begin(), U.end());
2457 subcenter = center -
make_vec3(0, 0, 0.5f * size.
z);
2459 UUID.insert(UUID.end(), U.begin(), U.end());
2465 subcenter = center +
make_vec3(0, 0.5f * size.
y, 0);
2467 UUID.insert(UUID.end(), U.begin(), U.end());
2470 subcenter = center -
make_vec3(0, 0.5f * size.
y, 0);
2472 UUID.insert(UUID.end(), U.begin(), U.end());
2477 subcenter = center +
make_vec3(0.5f * size.
x, 0, 0);
2479 UUID.insert(UUID.end(), U.begin(), U.end());
2482 subcenter = center -
make_vec3(0.5f * size.
x, 0, 0);
2484 UUID.insert(UUID.end(), U.begin(), U.end());
2489 subcenter = center +
make_vec3(0, 0, 0.5f * size.
z);
2491 UUID.insert(UUID.end(), U.begin(), U.end());
2494 subcenter = center -
make_vec3(0, 0, 0.5f * size.
z);
2496 UUID.insert(UUID.end(), U.begin(), U.end());
2527 std::vector<uint> UUID(Ndivs.
x + Ndivs.
x * (Ndivs.
y - 1) * 2);
2529 for (
int r = 0; r < Ndivs.
y; r++) {
2530 for (
int t = 0; t < Ndivs.
x; t++) {
2531 float dtheta = 2.f *
PI_F / float(Ndivs.
x);
2532 float theta = dtheta * float(t);
2533 float theta_plus = dtheta * float(t + 1);
2535 float rx = size.
x / float(Ndivs.
y) * float(r);
2536 float ry = size.
y / float(Ndivs.
y) * float(r);
2538 float rx_plus = size.
x / float(Ndivs.
y) * float(r + 1);
2539 float ry_plus = size.
y / float(Ndivs.
y) * float(r + 1);
2544 UUID.at(i) =
addTriangle(
make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0),
make_vec3(rx * cosf(theta), ry * sinf(theta), 0),
make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0), color);
2546 UUID.at(i) =
addTriangle(
make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0),
make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0),
make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), color);
2548 getPrimitivePointer_private(UUID.at(i))->rotate(rotation.
elevation,
"y");
2549 getPrimitivePointer_private(UUID.at(i))->rotate(rotation.
azimuth,
"z");
2550 getPrimitivePointer_private(UUID.at(i))->translate(center);
2560 if (!validateTextureFileExtenstion(texturefile)) {
2561 helios_runtime_error(
"ERROR (Context::addDisk): Texture file " + std::string(texturefile) +
" is not PNG or JPEG format.");
2562 }
else if (!doesTextureFileExist(texturefile)) {
2563 helios_runtime_error(
"ERROR (Context::addDisk): Texture file " + std::string(texturefile) +
" does not exist.");
2566 std::vector<uint> UUID;
2567 UUID.reserve(Ndivs.
x + Ndivs.
x * (Ndivs.
y - 1) * 2);
2568 for (
int r = 0; r < Ndivs.
y; r++) {
2569 for (
int t = 0; t < Ndivs.
x; t++) {
2570 float dtheta = 2.f *
PI_F / float(Ndivs.
x);
2571 float theta = dtheta * float(t);
2572 float theta_plus = dtheta * float(t + 1);
2574 float rx = size.
x / float(Ndivs.
y) * float(r);
2575 float ry = size.
y / float(Ndivs.
y) * float(r);
2576 float rx_plus = size.
x / float(Ndivs.
y) * float(r + 1);
2577 float ry_plus = size.
y / float(Ndivs.
y) * float(r + 1);
2580 uint triangle_uuid =
addTriangle(
make_vec3(0, 0, 0),
make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0),
make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), texturefile,
make_vec2(0.5, 0.5),
2581 make_vec2(0.5f * (1.f + cosf(theta) * rx_plus / size.
x), 0.5f * (1.f + sinf(theta) * ry_plus / size.
y)),
2582 make_vec2(0.5f * (1.f + cosf(theta_plus) * rx_plus / size.
x), 0.5f * (1.f + sinf(theta_plus) * ry_plus / size.
y)));
2584 UUID.push_back(triangle_uuid);
2590 uint triangle_uuid1 =
addTriangle(
make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0),
make_vec3(rx * cosf(theta), ry * sinf(theta), 0),
make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0), texturefile,
2591 make_vec2(0.5f * (1.f + cosf(theta_plus) * rx / size.
x), 0.5f * (1.f + sinf(theta_plus) * ry / size.
y)),
make_vec2(0.5f * (1.f + cosf(theta) * rx / size.
x), 0.5f * (1.f + sinf(theta) * ry / size.
y)),
2592 make_vec2(0.5f * (1.f + cosf(theta) * rx_plus / size.
x), 0.5f * (1.f + sinf(theta) * ry_plus / size.
y)));
2594 UUID.push_back(triangle_uuid1);
2599 uint triangle_uuid2 =
2600 addTriangle(
make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0),
make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0),
make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), texturefile,
2601 make_vec2(0.5f * (1.f + cosf(theta_plus) * rx / size.
x), 0.5f * (1.f + sinf(theta_plus) * ry / size.
y)),
make_vec2(0.5f * (1.f + cosf(theta) * rx_plus / size.
x), 0.5f * (1.f + sinf(theta) * ry_plus / size.
y)),
2602 make_vec2(0.5f * (1.f + cosf(theta_plus) * rx_plus / size.
x), 0.5f * (1.f + sinf(theta_plus) * ry_plus / size.
y)));
2604 UUID.push_back(triangle_uuid2);
2611 size_t start_idx = UUID.size() - (r == 0 ? 1 : 2);
2612 for (
size_t uuid_idx = start_idx; uuid_idx < UUID.size(); uuid_idx++) {
2613 getPrimitivePointer_private(UUID.at(uuid_idx))->rotate(rotation.
elevation,
"y");
2614 getPrimitivePointer_private(UUID.at(uuid_idx))->rotate(rotation.
azimuth,
"z");
2615 getPrimitivePointer_private(UUID.at(uuid_idx))->translate(center);
2631 std::vector<helios::vec3> nodes{node0, node1};
2632 std::vector<float> radii{radius0, radius1};
2635 std::vector<float> cfact(Ndivs + 1);
2636 std::vector<float> sfact(Ndivs + 1);
2637 std::vector<std::vector<vec3>> xyz, normal;
2638 xyz.resize(Ndivs + 1);
2639 normal.resize(Ndivs + 1);
2640 for (
uint j = 0; j < Ndivs + 1; j++) {
2641 xyz.at(j).resize(2);
2642 normal.at(j).resize(2);
2644 vec3 nvec(0.1817f, 0.6198f, 0.7634f);
2646 for (
int j = 0; j < Ndivs + 1; j++) {
2647 cfact[j] = cosf(2.f *
PI_F *
float(j) /
float(Ndivs));
2648 sfact[j] = sinf(2.f *
PI_F *
float(j) /
float(Ndivs));
2651 for (
int i = 0; i < 2; i++) {
2654 vec.
x = nodes[i + 1].x - nodes[i].x;
2655 vec.
y = nodes[i + 1].y - nodes[i].y;
2656 vec.
z = nodes[i + 1].z - nodes[i].z;
2657 }
else if (i == 1) {
2658 vec.
x = nodes[i].x - nodes[i - 1].x;
2659 vec.
y = nodes[i].y - nodes[i - 1].y;
2660 vec.
z = nodes[i].z - nodes[i - 1].z;
2664 convec =
cross(nvec, vec);
2666 convec.
x = convec.
x / norm;
2667 convec.
y = convec.
y / norm;
2668 convec.
z = convec.
z / norm;
2669 nvec =
cross(vec, convec);
2671 nvec.
x = nvec.
x / norm;
2672 nvec.
y = nvec.
y / norm;
2673 nvec.
z = nvec.
z / norm;
2676 for (
int j = 0; j < Ndivs + 1; j++) {
2677 normal[j][i].x = cfact[j] * radii[i] * nvec.
x + sfact[j] * radii[i] * convec.
x;
2678 normal[j][i].y = cfact[j] * radii[i] * nvec.
y + sfact[j] * radii[i] * convec.
y;
2679 normal[j][i].z = cfact[j] * radii[i] * nvec.
z + sfact[j] * radii[i] * convec.
z;
2681 xyz[j][i].x = nodes[i].x + normal[j][i].x;
2682 xyz[j][i].y = nodes[i].y + normal[j][i].y;
2683 xyz[j][i].z = nodes[i].z + normal[j][i].z;
2685 normal[j][i] = normal[j][i] / radii[i];
2690 std::vector<uint> UUID;
2692 for (
int i = 0; i < 2 - 1; i++) {
2693 for (
int j = 0; j < Ndivs; j++) {
2695 v1 = xyz[j + 1][i + 1];
2702 v2 = xyz[j + 1][i + 1];
2712 if (!validateTextureFileExtenstion(texturefile)) {
2713 helios_runtime_error(
"ERROR (Context::addCone): Texture file " + std::string(texturefile) +
" is not PNG or JPEG format.");
2714 }
else if (!doesTextureFileExist(texturefile)) {
2715 helios_runtime_error(
"ERROR (Context::addCone): Texture file " + std::string(texturefile) +
" does not exist.");
2718 std::vector<helios::vec3> nodes{node0, node1};
2719 std::vector<float> radii{radius0, radius1};
2722 std::vector<float> cfact(Ndivs + 1);
2723 std::vector<float> sfact(Ndivs + 1);
2724 std::vector<std::vector<vec3>> xyz, normal;
2725 std::vector<std::vector<vec2>> uv;
2726 xyz.resize(Ndivs + 1);
2727 normal.resize(Ndivs + 1);
2728 uv.resize(Ndivs + 1);
2729 for (
uint j = 0; j < Ndivs + 1; j++) {
2730 xyz.at(j).resize(2);
2731 normal.at(j).resize(2);
2734 vec3 nvec(0.f, 1.f, 0.f);
2736 for (
int j = 0; j < Ndivs + 1; j++) {
2737 cfact[j] = cosf(2.f *
PI_F *
float(j) /
float(Ndivs));
2738 sfact[j] = sinf(2.f *
PI_F *
float(j) /
float(Ndivs));
2741 for (
int i = 0; i < 2; i++) {
2744 vec.
x = nodes[i + 1].x - nodes[i].x;
2745 vec.
y = nodes[i + 1].y - nodes[i].y;
2746 vec.
z = nodes[i + 1].z - nodes[i].z;
2747 }
else if (i == 1) {
2748 vec.
x = nodes[i].x - nodes[i - 1].x;
2749 vec.
y = nodes[i].y - nodes[i - 1].y;
2750 vec.
z = nodes[i].z - nodes[i - 1].z;
2754 convec =
cross(nvec, vec);
2756 convec.
x = convec.
x / norm;
2757 convec.
y = convec.
y / norm;
2758 convec.
z = convec.
z / norm;
2759 nvec =
cross(vec, convec);
2761 nvec.
x = nvec.
x / norm;
2762 nvec.
y = nvec.
y / norm;
2763 nvec.
z = nvec.
z / norm;
2765 for (
int j = 0; j < Ndivs + 1; j++) {
2766 normal[j][i].x = cfact[j] * radii[i] * nvec.
x + sfact[j] * radii[i] * convec.
x;
2767 normal[j][i].y = cfact[j] * radii[i] * nvec.
y + sfact[j] * radii[i] * convec.
y;
2768 normal[j][i].z = cfact[j] * radii[i] * nvec.
z + sfact[j] * radii[i] * convec.
z;
2770 xyz[j][i].x = nodes[i].x + normal[j][i].x;
2771 xyz[j][i].y = nodes[i].y + normal[j][i].y;
2772 xyz[j][i].z = nodes[i].z + normal[j][i].z;
2774 uv[j][i].x = float(i) / float(2 - 1);
2775 uv[j][i].y = float(j) / float(Ndivs);
2777 normal[j][i] = normal[j][i] / radii[i];
2783 std::vector<uint> UUID;
2785 for (
int i = 0; i < 2 - 1; i++) {
2786 for (
int j = 0; j < Ndivs; j++) {
2788 v1 = xyz[j + 1][i + 1];
2792 uv1 = uv[j + 1][i + 1];
2795 if ((v1 - v0).magnitude() > 1e-6 && (v2 - v0).magnitude() > 1e-6 && (v2 - v1).magnitude() > 1e-6) {
2796 uint triangle_uuid =
addTriangle(v0, v1, v2, texturefile, uv0, uv1, uv2);
2798 UUID.push_back(triangle_uuid);
2806 v2 = xyz[j + 1][i + 1];
2810 uv2 = uv[j + 1][i + 1];
2812 if ((v1 - v0).magnitude() > 1e-6 && (v2 - v0).magnitude() > 1e-6 && (v2 - v1).magnitude() > 1e-6) {
2813 uint triangle_uuid =
addTriangle(v0, v1, v2, texturefile, uv0, uv1, uv2);
2815 UUID.push_back(triangle_uuid);
2831 std::map<uint, float> pcolor_data;
2833 float data_min_new = 9999999;
2834 float data_max_new = -9999999;
2835 for (
uint UUID: UUIDs) {
2837 std::cerr <<
"WARNING (Context::colorPrimitiveDataPseudocolor): primitive for UUID " << std::to_string(UUID) <<
" does not exist. Skipping this primitive." << std::endl;
2845 std::cerr <<
"WARNING (Context::colorPrimitiveDataPseudocolor): Only primitive data types of int, uint, float, and double are supported for this function. Skipping this primitive." << std::endl;
2856 dataf = float(data);
2860 dataf = float(data);
2864 dataf = float(data);
2868 if (data_min == 9999999 && data_max == -9999999) {
2869 if (dataf < data_min_new) {
2870 data_min_new = dataf;
2872 if (dataf > data_max_new) {
2873 data_max_new = dataf;
2877 pcolor_data[UUID] = dataf;
2880 if (data_min == 9999999 && data_max == -9999999) {
2881 data_min = data_min_new;
2882 data_max = data_max_new;
2887 std::map<std::string, std::vector<std::string>> cmap_texture_filenames;
2889 for (
auto &[UUID, pdata]: pcolor_data) {
2892 int cmap_ind = std::round((pdata - data_min) / (data_max - data_min) *
float(Ncolors - 1));
2896 }
else if (cmap_ind >= Ncolors) {
2897 cmap_ind = Ncolors - 1;
2916 if (Ncolors > 9999) {
2917 std::cerr <<
"WARNING (Context::generateColormap): Truncating number of color map textures to maximum value of 9999." << std::endl;
2920 if (ctable.size() != cfrac.size()) {
2921 helios_runtime_error(
"ERROR (Context::generateColormap): The length of arguments 'ctable' and 'cfrac' must match.");
2923 if (ctable.empty()) {
2924 helios_runtime_error(
"ERROR (Context::generateColormap): 'ctable' and 'cfrac' arguments contain empty vectors.");
2927 std::vector<RGBcolor> color_table(Ncolors);
2929 for (
int i = 0; i < Ncolors; i++) {
2930 float frac = float(i) / float(Ncolors - 1) * cfrac.back();
2933 for (j = 0; j < cfrac.size() - 1; j++) {
2934 if (frac >= cfrac.at(j) && frac <= cfrac.at(j + 1)) {
2939 float cminus = std::fmaxf(0.f, cfrac.at(j));
2940 float cplus = std::fminf(1.f, cfrac.at(j + 1));
2942 float jfrac = (frac - cminus) / (cplus - cminus);
2945 color.
r = ctable.at(j).r + jfrac * (ctable.at(j + 1).r - ctable.at(j).r);
2946 color.
g = ctable.at(j).g + jfrac * (ctable.at(j + 1).g - ctable.at(j).g);
2947 color.
b = ctable.at(j).b + jfrac * (ctable.at(j + 1).b - ctable.at(j).b);
2949 color_table.at(i) = color;
2956 std::vector<RGBcolor> ctable_c;
2957 std::vector<float> clocs_c;
2959 if (colormap ==
"hot") {
2968 clocs_c.at(0) = 0.f;
2969 clocs_c.at(1) = 0.25f;
2970 clocs_c.at(2) = 0.5f;
2971 clocs_c.at(3) = 0.75f;
2972 clocs_c.at(4) = 1.f;
2973 }
else if (colormap ==
"cool") {
2975 ctable_c.at(0) = RGB::cyan;
2976 ctable_c.at(1) = RGB::magenta;
2979 clocs_c.at(0) = 0.f;
2980 clocs_c.at(1) = 1.f;
2981 }
else if (colormap ==
"lava") {
2990 clocs_c.at(0) = 0.f;
2991 clocs_c.at(1) = 0.4f;
2992 clocs_c.at(2) = 0.5f;
2993 clocs_c.at(3) = 0.6f;
2994 clocs_c.at(4) = 1.f;
2995 }
else if (colormap ==
"rainbow") {
2997 ctable_c.at(0) = RGB::navy;
2998 ctable_c.at(1) = RGB::cyan;
2999 ctable_c.at(2) = RGB::yellow;
3003 clocs_c.at(0) = 0.f;
3004 clocs_c.at(1) = 0.3f;
3005 clocs_c.at(2) = 0.7f;
3006 clocs_c.at(3) = 1.f;
3007 }
else if (colormap ==
"parula") {
3009 ctable_c.at(0) = RGB::navy;
3011 ctable_c.at(2) = RGB::goldenrod;
3012 ctable_c.at(3) = RGB::yellow;
3015 clocs_c.at(0) = 0.f;
3016 clocs_c.at(1) = 0.4f;
3017 clocs_c.at(2) = 0.7f;
3018 clocs_c.at(3) = 1.f;
3019 }
else if (colormap ==
"gray") {
3021 ctable_c.at(0) = RGB::black;
3022 ctable_c.at(1) = RGB::white;
3025 clocs_c.at(0) = 0.f;
3026 clocs_c.at(1) = 1.f;
3027 }
else if (colormap ==
"green") {
3029 ctable_c.at(0) = RGB::black;
3030 ctable_c.at(1) = RGB::green;
3033 clocs_c.at(0) = 0.f;
3034 clocs_c.at(1) = 1.f;
3036 helios_runtime_error(
"ERROR (Context::generateColormapTextures): Unknown colormap " + colormap +
".");
3043 uint Ncolors = colormap_data.size();
3046 std::ifstream tfile(texturefile);
3048 helios_runtime_error(
"ERROR (Context::generateTexturesFromColormap): Texture file " + texturefile +
" does not exist, or you do not have permission to read it.");
3058 std::vector<RGBcolor> color_table(Ncolors);
3060 std::vector<std::string> texture_filenames(Ncolors);
3062 if (file_ext ==
"png" || file_ext ==
"PNG") {
3063 std::vector<RGBAcolor> pixel_data;
3065 readPNG(texturefile, width, height, pixel_data);
3067 for (
int i = 0; i < Ncolors; i++) {
3068 std::ostringstream filename;
3069 filename <<
"lib/images/colormap_" << file_base <<
"_" << std::setw(4) << std::setfill(
'0') << std::to_string(i) <<
".png";
3071 texture_filenames.at(i) = filename.str();
3073 RGBcolor color = colormap_data.at(i);
3075 for (
int row = 0; row < height; row++) {
3076 for (
int col = 0; col < width; col++) {
3077 pixel_data.at(row * width + col) =
make_RGBAcolor(color, pixel_data.at(row * width + col).a);
3081 writePNG(filename.str(), width, height, pixel_data);
3085 return texture_filenames;
3379 std::cout <<
"-------------------------------------------" << std::endl;
3380 std::cout <<
"Info for UUID " << UUID << std::endl;
3381 std::cout <<
"-------------------------------------------" << std::endl;
3386 stype =
"PRIMITIVE_TYPE_PATCH";
3387 }
else if (type == 1) {
3388 stype =
"PRIMITIVE_TYPE_TRIANGLE";
3389 }
else if (type == 2) {
3390 stype =
"PRIMITIVE_TYPE_VOXEL";
3393 std::cout <<
"Type: " << stype << std::endl;
3399 std::cout <<
"Patch Center: " <<
getPatchCenter(UUID) << std::endl;
3400 std::cout <<
"Patch Size: " <<
getPatchSize(UUID) << std::endl;
3402 std::cout <<
"Voxel Center: " <<
getVoxelCenter(UUID) << std::endl;
3403 std::cout <<
"Voxel Size: " <<
getVoxelSize(UUID) << std::endl;
3407 std::cout <<
"Vertices: " << std::endl;
3408 for (
uint i = 0; i < primitive_vertices.size(); i++) {
3409 std::cout <<
" " << primitive_vertices.at(i) << std::endl;
3414 std::cout <<
"Transform: " << std::endl;
3415 std::cout <<
" " << T[0] <<
" " << T[1] <<
" " << T[2] <<
" " << T[3] << std::endl;
3416 std::cout <<
" " << T[4] <<
" " << T[5] <<
" " << T[6] <<
" " << T[7] << std::endl;
3417 std::cout <<
" " << T[8] <<
" " << T[9] <<
" " << T[10] <<
" " << T[11] << std::endl;
3418 std::cout <<
" " << T[12] <<
" " << T[13] <<
" " << T[14] <<
" " << T[15] << std::endl;
3423 std::cout <<
"Texture UV: " << std::endl;
3425 for (
uint i = 0; i < uv.size(); i++) {
3426 std::cout <<
" " << uv.at(i) << std::endl;
3434 std::cout <<
"Primitive Data: " << std::endl;
3437 for (
uint i = 0; i < pd.size(); i++) {
3443 dstype =
"HELIOS_TYPE_INT";
3445 dstype =
"HELIOS_TYPE_UINT";
3447 dstype =
"HELIOS_TYPE_FLOAT";
3449 dstype =
"HELIOS_TYPE_DOUBLE";
3451 dstype =
"HELIOS_TYPE_VEC2";
3453 dstype =
"HELIOS_TYPE_VEC3";
3455 dstype =
"HELIOS_TYPE_VEC4";
3457 dstype =
"HELIOS_TYPE_INT2";
3459 dstype =
"HELIOS_TYPE_INT3";
3461 dstype =
"HELIOS_TYPE_INT4";
3463 dstype =
"HELIOS_TYPE_STRING";
3469 std::cout <<
" " <<
"[name: " << pd.at(i) <<
", type: " << dstype <<
", size: " << dsize <<
"]:" << std::endl;
3473 std::vector<int> pdata;
3475 for (
uint j = 0; j < dsize; j++) {
3477 std::cout <<
" " << pdata.at(j) << std::endl;
3479 std::cout <<
" ..." << std::endl;
3480 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3481 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3486 std::vector<uint> pdata;
3488 for (
uint j = 0; j < dsize; j++) {
3490 std::cout <<
" " << pdata.at(j) << std::endl;
3492 std::cout <<
" ..." << std::endl;
3493 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3494 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3499 std::vector<float> pdata;
3501 for (
uint j = 0; j < dsize; j++) {
3503 std::cout <<
" " << pdata.at(j) << std::endl;
3505 std::cout <<
" ..." << std::endl;
3506 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3507 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3512 std::vector<double> pdata;
3514 for (
uint j = 0; j < dsize; j++) {
3516 std::cout <<
" " << pdata.at(j) << std::endl;
3518 std::cout <<
" ..." << std::endl;
3519 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3520 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3525 std::vector<vec2> pdata;
3527 for (
uint j = 0; j < dsize; j++) {
3529 std::cout <<
" " << pdata.at(j) << std::endl;
3531 std::cout <<
" ..." << std::endl;
3532 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3533 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3538 std::vector<vec3> pdata;
3540 for (
uint j = 0; j < dsize; j++) {
3542 std::cout <<
" " << pdata.at(j) << std::endl;
3544 std::cout <<
" ..." << std::endl;
3545 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3546 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3551 std::vector<vec4> pdata;
3553 for (
uint j = 0; j < dsize; j++) {
3555 std::cout <<
" " << pdata.at(j) << std::endl;
3557 std::cout <<
" ..." << std::endl;
3558 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3559 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3564 std::vector<int2> pdata;
3566 for (
uint j = 0; j < dsize; j++) {
3568 std::cout <<
" " << pdata.at(j) << std::endl;
3570 std::cout <<
" ..." << std::endl;
3571 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3572 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3577 std::vector<int3> pdata;
3579 for (
uint j = 0; j < dsize; j++) {
3581 std::cout <<
" " << pdata.at(j) << std::endl;
3583 std::cout <<
" ..." << std::endl;
3584 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3585 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3590 std::vector<int4> pdata;
3592 for (
uint j = 0; j < dsize; j++) {
3594 std::cout <<
" " << pdata.at(j) << std::endl;
3596 std::cout <<
" ..." << std::endl;
3597 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3598 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3603 std::vector<std::string> pdata;
3605 for (
uint j = 0; j < dsize; j++) {
3607 std::cout <<
" " << pdata.at(j) << std::endl;
3609 std::cout <<
" ..." << std::endl;
3610 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3611 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3619 std::cout <<
"-------------------------------------------" << std::endl;
3623 std::cout <<
"-------------------------------------------" << std::endl;
3624 std::cout <<
"Info for ObjID " << ObjID << std::endl;
3625 std::cout <<
"-------------------------------------------" << std::endl;
3630 ostype =
"OBJECT_TYPE_TILE";
3631 }
else if (otype == 1) {
3632 ostype =
"OBJECT_TYPE_SPHERE";
3633 }
else if (otype == 2) {
3634 ostype =
"OBJECT_TYPE_TUBE";
3635 }
else if (otype == 3) {
3636 ostype =
"OBJECT_TYPE_BOX";
3637 }
else if (otype == 4) {
3638 ostype =
"OBJECT_TYPE_DISK";
3639 }
else if (otype == 5) {
3640 ostype =
"OBJECT_TYPE_POLYMESH";
3641 }
else if (otype == 6) {
3642 ostype =
"OBJECT_TYPE_CONE";
3645 std::cout <<
"Type: " << ostype << std::endl;
3646 std::cout <<
"Object Bounding Box Center: " <<
getObjectCenter(ObjID) << std::endl;
3647 std::cout <<
"One-sided Surface Area: " <<
getObjectArea(ObjID) << std::endl;
3652 std::cout <<
"Object Primitives Complete" << std::endl;
3654 std::cout <<
"Object Primitives Incomplete" << std::endl;
3657 std::cout <<
"Primitive UUIDs: " << std::endl;
3659 for (
uint i = 0; i < primitive_UUIDs.size(); i++) {
3664 pstype =
"PRIMITIVE_TYPE_PATCH";
3665 }
else if (ptype == 1) {
3666 pstype =
"PRIMITIVE_TYPE_TRIANGLE";
3668 std::cout <<
" " << primitive_UUIDs.at(i) <<
" (" << pstype <<
")" << std::endl;
3670 std::cout <<
" ..." << std::endl;
3674 pstype =
"PRIMITIVE_TYPE_PATCH";
3675 }
else if (ptype == 1) {
3676 pstype =
"PRIMITIVE_TYPE_TRIANGLE";
3678 std::cout <<
" " << primitive_UUIDs.at(primitive_UUIDs.size() - 2) <<
" (" << pstype <<
")" << std::endl;
3681 pstype =
"PRIMITIVE_TYPE_PATCH";
3682 }
else if (ptype == 1) {
3683 pstype =
"PRIMITIVE_TYPE_TRIANGLE";
3685 std::cout <<
" " << primitive_UUIDs.at(primitive_UUIDs.size() - 1) <<
" (" << pstype <<
")" << std::endl;
3696 std::cout <<
"Tile Texture UV: " << std::endl;
3698 for (
uint i = 0; i < uv.size(); i++) {
3699 std::cout <<
" " << uv.at(i) << std::endl;
3702 std::cout <<
"Tile Vertices: " << std::endl;
3704 for (
uint i = 0; i < primitive_vertices.size(); i++) {
3705 std::cout <<
" " << primitive_vertices.at(i) << std::endl;
3713 std::cout <<
"Tube Nodes: " << std::endl;
3715 for (
uint i = 0; i < nodes.size(); i++) {
3717 std::cout <<
" " << nodes.at(i) << std::endl;
3719 std::cout <<
" ..." << std::endl;
3720 std::cout <<
" " << nodes.at(nodes.size() - 2) << std::endl;
3721 std::cout <<
" " << nodes.at(nodes.size() - 1) << std::endl;
3725 std::cout <<
"Tube Node Radii: " << std::endl;
3727 for (
uint i = 0; i < noderadii.size(); i++) {
3729 std::cout <<
" " << noderadii.at(i) << std::endl;
3731 std::cout <<
" ..." << std::endl;
3732 std::cout <<
" " << noderadii.at(noderadii.size() - 2) << std::endl;
3733 std::cout <<
" " << noderadii.at(noderadii.size() - 1) << std::endl;
3737 std::cout <<
"Tube Node Colors: " << std::endl;
3739 for (
uint i = 0; i < nodecolors.size(); i++) {
3741 std::cout <<
" " << nodecolors.at(i) << std::endl;
3743 std::cout <<
" ..." << std::endl;
3744 std::cout <<
" " << nodecolors.at(nodecolors.size() - 2) << std::endl;
3745 std::cout <<
" " << nodecolors.at(nodecolors.size() - 1) << std::endl;
3764 std::cout <<
"Cone Nodes: " << std::endl;
3766 for (
uint i = 0; i < nodes.size(); i++) {
3767 std::cout <<
" " << nodes.at(i) << std::endl;
3769 std::cout <<
"Cone Node Radii: " << std::endl;
3771 for (
uint i = 0; i < noderadii.size(); i++) {
3772 std::cout <<
" " << noderadii.at(i) << std::endl;
3779 std::cout <<
"Transform: " << std::endl;
3780 std::cout <<
" " << T[0] <<
" " << T[1] <<
" " << T[2] <<
" " << T[3] << std::endl;
3781 std::cout <<
" " << T[4] <<
" " << T[5] <<
" " << T[6] <<
" " << T[7] << std::endl;
3782 std::cout <<
" " << T[8] <<
" " << T[9] <<
" " << T[10] <<
" " << T[11] << std::endl;
3783 std::cout <<
" " << T[12] <<
" " << T[13] <<
" " << T[14] <<
" " << T[15] << std::endl;
3787 std::cout <<
"Object Data: " << std::endl;
3790 for (
uint i = 0; i < pd.size(); i++) {
3796 dstype =
"HELIOS_TYPE_INT";
3798 dstype =
"HELIOS_TYPE_UINT";
3800 dstype =
"HELIOS_TYPE_FLOAT";
3802 dstype =
"HELIOS_TYPE_DOUBLE";
3804 dstype =
"HELIOS_TYPE_VEC2";
3806 dstype =
"HELIOS_TYPE_VEC3";
3808 dstype =
"HELIOS_TYPE_VEC4";
3810 dstype =
"HELIOS_TYPE_INT2";
3812 dstype =
"HELIOS_TYPE_INT3";
3814 dstype =
"HELIOS_TYPE_INT4";
3816 dstype =
"HELIOS_TYPE_STRING";
3822 std::cout <<
" " <<
"[name: " << pd.at(i) <<
", type: " << dstype <<
", size: " << dsize <<
"]:" << std::endl;
3826 std::vector<int> pdata;
3828 for (
uint j = 0; j < dsize; j++) {
3830 std::cout <<
" " << pdata.at(j) << std::endl;
3832 std::cout <<
" ..." << std::endl;
3833 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3834 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3839 std::vector<uint> pdata;
3841 for (
uint j = 0; j < dsize; j++) {
3843 std::cout <<
" " << pdata.at(j) << std::endl;
3845 std::cout <<
" ..." << std::endl;
3846 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3847 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3852 std::vector<float> pdata;
3854 for (
uint j = 0; j < dsize; j++) {
3856 std::cout <<
" " << pdata.at(j) << std::endl;
3858 std::cout <<
" ..." << std::endl;
3859 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3860 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3865 std::vector<double> pdata;
3867 for (
uint j = 0; j < dsize; j++) {
3869 std::cout <<
" " << pdata.at(j) << std::endl;
3871 std::cout <<
" ..." << std::endl;
3872 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3873 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3878 std::vector<vec2> pdata;
3880 for (
uint j = 0; j < dsize; j++) {
3882 std::cout <<
" " << pdata.at(j) << std::endl;
3884 std::cout <<
" ..." << std::endl;
3885 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3886 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3891 std::vector<vec3> pdata;
3893 for (
uint j = 0; j < dsize; j++) {
3895 std::cout <<
" " << pdata.at(j) << std::endl;
3897 std::cout <<
" ..." << std::endl;
3898 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3899 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3904 std::vector<vec4> pdata;
3906 for (
uint j = 0; j < dsize; j++) {
3908 std::cout <<
" " << pdata.at(j) << std::endl;
3910 std::cout <<
" ..." << std::endl;
3911 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3912 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3917 std::vector<int2> pdata;
3919 for (
uint j = 0; j < dsize; j++) {
3921 std::cout <<
" " << pdata.at(j) << std::endl;
3923 std::cout <<
" ..." << std::endl;
3924 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3925 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3930 std::vector<int3> pdata;
3932 for (
uint j = 0; j < dsize; j++) {
3934 std::cout <<
" " << pdata.at(j) << std::endl;
3936 std::cout <<
" ..." << std::endl;
3937 std::cout <<
" " << pdata.at(dsize - 2) << std::endl;
3938 std::cout <<
" " << pdata.at(dsize - 1) << std::endl;
3943 std::vector<int4> pdata;
3945 for (
uint j = 0; j < dsize; j++) {
3947 std::cout <<
" " << pdata.at(j) << std::endl;
3949 std::cout <<
" ..." << std::endl;
3954 std::vector<std::string> pdata;
3956 for (
uint j = 0; j < dsize; j++) {
3958 std::cout <<
" " << pdata.at(j) << std::endl;
3960 std::cout <<
" ..." << std::endl;
3968 std::cout <<
"-------------------------------------------" << std::endl;