391 float new_leaf_width =
XMLloadfloat(canopy_node,
"leaf_width");
392 if (new_leaf_width != nullvalue_f) {
396 float new_leaf_width_spread =
XMLloadfloat(canopy_node,
"leaf_width_spread");
397 if (new_leaf_width_spread != nullvalue_f) {
401 int2 new_leaf_subdivisions =
XMLloadint2(canopy_node,
"leaf_subdivisions");
402 if (new_leaf_subdivisions.
x != nullvalue_i && new_leaf_subdivisions.
y != nullvalue_i) {
406 std::string new_leaf_texture_file =
XMLloadstring(canopy_node,
"leaf_texture_file");
407 if (new_leaf_texture_file != nullvalue_s) {
411 std::string new_wood_texture_file =
XMLloadstring(canopy_node,
"wood_texture_file");
412 if (new_wood_texture_file != nullvalue_s) {
416 int new_wood_subdivisions =
XMLloadint(canopy_node,
"wood_subdivisions");
417 if (new_wood_subdivisions != nullvalue_i) {
421 int new_wood_subdivisions_spread =
XMLloadint(canopy_node,
"wood_subdivisions_spread");
422 if (new_wood_subdivisions_spread != nullvalue_i) {
427 if (h != nullvalue_f) {
431 float new_trunk_height_spread =
XMLloadfloat(canopy_node,
"trunk_height_spread");
432 if (new_trunk_height_spread != nullvalue_f) {
437 if (r != nullvalue_f) {
441 float new_trunk_radius_spread =
XMLloadfloat(canopy_node,
"trunk_radius_spread");
442 if (new_trunk_radius_spread != nullvalue_f) {
446 float new_cordon_length =
XMLloadfloat(canopy_node,
"cordon_length");
447 if (new_cordon_length != nullvalue_f) {
451 float new_cordon_length_spread =
XMLloadfloat(canopy_node,
"cordon_length_spread");
452 if (new_cordon_length_spread != nullvalue_f) {
457 if (ch != nullvalue_f) {
461 float new_cordon_height_spread =
XMLloadfloat(canopy_node,
"cordon_height_spread");
462 if (new_cordon_height_spread != nullvalue_f) {
467 if (cr != nullvalue_f) {
471 float new_cordon_radius_spread =
XMLloadfloat(canopy_node,
"cordon_radius_spread");
472 if (new_cordon_radius_spread != nullvalue_f) {
477 if (sl != nullvalue_f) {
481 float new_shoot_length_spread =
XMLloadfloat(canopy_node,
"shoot_length_spread");
482 if (new_shoot_length_spread != nullvalue_f) {
487 if (sr != nullvalue_f) {
491 float new_shoot_radius_spread =
XMLloadfloat(canopy_node,
"shoot_radius_spread");
492 if (new_shoot_radius_spread != nullvalue_f) {
496 int spc =
XMLloadint(canopy_node,
"shoots_per_cordon");
497 if (spc != nullvalue_i) {
501 int new_shoots_per_cordon_spread =
XMLloadint(canopy_node,
"shoots_per_cordon_spread");
502 if (new_shoots_per_cordon_spread != nullvalue_i) {
506 float lsf =
XMLloadfloat(canopy_node,
"leaf_spacing_fraction");
507 if (lsf != nullvalue_f) {
511 float new_leaf_spacing_fraction_spread =
XMLloadfloat(canopy_node,
"leaf_spacing_fraction_spread");
512 if (new_leaf_spacing_fraction_spread != nullvalue_f) {
517 if (gr != nullvalue_f) {
521 float new_grape_radius_spread =
XMLloadfloat(canopy_node,
"grape_radius_spread");
522 if (new_grape_radius_spread != nullvalue_f) {
526 float clr =
XMLloadfloat(canopy_node,
"cluster_radius");
527 if (clr != nullvalue_f) {
531 float new_cluster_radius_spread =
XMLloadfloat(canopy_node,
"cluster_radius_spread");
532 if (new_cluster_radius_spread != nullvalue_f) {
536 float clhm =
XMLloadfloat(canopy_node,
"cluster_height_max");
537 if (clhm != nullvalue_f) {
541 float new_cluster_height_max_spread =
XMLloadfloat(canopy_node,
"cluster_height_max_spread");
542 if (new_cluster_height_max_spread != nullvalue_f) {
547 if (new_grape_color.
a != 0) {
551 int new_grape_subdivisions =
XMLloadint(canopy_node,
"grape_subdivisions");
552 if (new_grape_subdivisions != nullvalue_i) {
556 int new_grape_subdivisions_spread =
XMLloadint(canopy_node,
"grape_subdivisions_spread");
557 if (new_grape_subdivisions_spread != nullvalue_i) {
561 float new_plant_spacing =
XMLloadfloat(canopy_node,
"plant_spacing");
562 if (new_plant_spacing != nullvalue_f) {
566 float new_plant_spacing_spread =
XMLloadfloat(canopy_node,
"plant_spacing_spread");
567 if (new_plant_spacing_spread != nullvalue_f) {
571 float new_row_spacing =
XMLloadfloat(canopy_node,
"row_spacing");
572 if (new_row_spacing != nullvalue_f) {
576 float new_row_spacing_spread =
XMLloadfloat(canopy_node,
"row_spacing_spread");
577 if (new_row_spacing_spread != nullvalue_f) {
582 if (new_plant_count.
x != nullvalue_i && new_plant_count.
y != nullvalue_i) {
586 float new_dead_probability =
XMLloadfloat(canopy_node,
"dead_probability");
587 if (new_dead_probability != nullvalue_f) {
588 if (new_dead_probability < 0 || new_dead_probability > 1)
589 std::cout <<
"BaseGrapeVineParameters::readParametersFromXML: dead_probability value must be between 0 and 1" << std::endl;
594 float new_missing_plant_probability =
XMLloadfloat(canopy_node,
"missing_plant_probability");
595 if (new_missing_plant_probability != nullvalue_f) {
596 if (new_missing_plant_probability < 0 || new_missing_plant_probability > 1)
597 std::cout <<
"BaseGrapeVineParameters::readParametersFromXML: missing_plant_probability value must be between 0 and 1" << std::endl;
602 float new_canopy_rotation_spread =
XMLloadfloat(canopy_node,
"canopy_rotation_spread");
603 if (new_canopy_rotation_spread != nullvalue_f) {
878 float new_needle_width =
XMLloadfloat(canopy_node,
"needle_width");
879 if (new_needle_width != nullvalue_f) {
883 float new_needle_length =
XMLloadfloat(canopy_node,
"needle_length");
884 if (new_needle_length != nullvalue_f) {
888 int2 new_needle_subdivisions =
XMLloadint2(canopy_node,
"needle_subdivisions");
889 if (new_needle_subdivisions.
x != nullvalue_i && new_needle_subdivisions.
y != nullvalue_i) {
894 if (new_needle_color.
a != 0) {
898 std::string new_wood_texture_file =
XMLloadstring(canopy_node,
"wood_texture_file");
899 if (new_wood_texture_file != nullvalue_s) {
903 int new_wood_subdivisions =
XMLloadint(canopy_node,
"wood_subdivisions");
904 if (new_wood_subdivisions != nullvalue_i) {
908 float new_trunk_height =
XMLloadfloat(canopy_node,
"trunk_height");
909 if (new_trunk_height != nullvalue_f) {
913 float new_trunk_radius =
XMLloadfloat(canopy_node,
"trunk_radius");
914 if (new_trunk_radius != nullvalue_f) {
918 float new_crown_radius =
XMLloadfloat(canopy_node,
"crown_radius");
919 if (new_crown_radius != nullvalue_f) {
923 float new_shoot_radius =
XMLloadfloat(canopy_node,
"shoot_radius");
924 if (new_shoot_radius != nullvalue_f) {
928 float new_level_spacing =
XMLloadfloat(canopy_node,
"level_spacing");
929 if (new_level_spacing != nullvalue_f) {
933 int new_branches_per_level =
XMLloadint(canopy_node,
"branches_per_level");
934 if (new_branches_per_level != nullvalue_i) {
938 float new_shoot_angle =
XMLloadfloat(canopy_node,
"shoot_angle");
939 if (new_shoot_angle != nullvalue_f) {
943 std::string new_canopy_configuration =
XMLloadstring(canopy_node,
"canopy_configuration");
944 if (new_canopy_configuration != nullvalue_s) {
949 if (new_plant_spacing.
x != nullvalue_f && new_plant_spacing.
y != nullvalue_f) {
954 if (new_plant_count.
x != nullvalue_i && new_plant_count.
y != nullvalue_i) {
1436 int new_sorghum_stage =
XMLloadint(canopy_node,
"sorghum_stage");
1437 if (new_sorghum_stage != nullvalue_i) {
1442 float new_s1_stem_length =
XMLloadint(canopy_node,
"s1_stem_length");
1443 if (new_s1_stem_length != nullvalue_i) {
1447 float new_s1_stem_radius =
XMLloadfloat(canopy_node,
"s1_stem_radius");
1448 if (new_s1_stem_radius != nullvalue_f) {
1452 int new_s1_stem_subdivisions =
XMLloadint(canopy_node,
"s1_stem_subdivisions");
1453 if (new_s1_stem_subdivisions != nullvalue_f) {
1458 if (new_s1_leaf_size1.
x != nullvalue_f && new_s1_leaf_size1.
y != nullvalue_f) {
1463 if (new_s1_leaf_size2.
x != nullvalue_f && new_s1_leaf_size2.
y != nullvalue_f) {
1468 if (new_s1_leaf_size3.
x != nullvalue_f && new_s1_leaf_size3.
y != nullvalue_f) {
1472 float new_s1_leaf1_angle =
XMLloadfloat(canopy_node,
"s1_leaf1_angle");
1473 if (new_s1_leaf1_angle != nullvalue_f) {
1477 float new_s1_leaf2_angle =
XMLloadfloat(canopy_node,
"s1_leaf2_angle");
1478 if (new_s1_leaf2_angle != nullvalue_f) {
1482 float new_s1_leaf3_angle =
XMLloadfloat(canopy_node,
"s1_leaf3_angle");
1483 if (new_s1_leaf3_angle != nullvalue_f) {
1487 int2 new_s1_leaf_subdivisions =
XMLloadint2(canopy_node,
"s1_leaf_subdivisions");
1488 if (new_s1_leaf_subdivisions.
x != nullvalue_i && new_s1_leaf_subdivisions.
y != nullvalue_i) {
1492 std::string new_s1_leaf_texture_file =
XMLloadstring(canopy_node,
"s1_leaf_texture_file");
1493 if (new_s1_leaf_texture_file.compare(nullvalue_s) != 0) {
1498 float new_s2_stem_length =
XMLloadint(canopy_node,
"s2_stem_length");
1499 if (new_s2_stem_length != nullvalue_i) {
1503 float new_s2_stem_radius =
XMLloadfloat(canopy_node,
"s2_stem_radius");
1504 if (new_s2_stem_radius != nullvalue_f) {
1508 int new_s2_stem_subdivisions =
XMLloadint(canopy_node,
"s2_stem_subdivisions");
1509 if (new_s2_stem_subdivisions != nullvalue_f) {
1514 if (new_s2_leaf_size1.
x != nullvalue_f && new_s2_leaf_size1.
y != nullvalue_f) {
1519 if (new_s2_leaf_size2.
x != nullvalue_f && new_s2_leaf_size2.
y != nullvalue_f) {
1524 if (new_s2_leaf_size3.
x != nullvalue_f && new_s2_leaf_size3.
y != nullvalue_f) {
1529 if (new_s2_leaf_size4.
x != nullvalue_f && new_s2_leaf_size4.
y != nullvalue_f) {
1534 if (new_s2_leaf_size5.
x != nullvalue_f && new_s2_leaf_size5.
y != nullvalue_f) {
1538 float new_s2_leaf1_angle =
XMLloadfloat(canopy_node,
"s2_leaf1_angle");
1539 if (new_s2_leaf1_angle != nullvalue_f) {
1543 float new_s2_leaf2_angle =
XMLloadfloat(canopy_node,
"s2_leaf2_angle");
1544 if (new_s2_leaf2_angle != nullvalue_f) {
1548 float new_s2_leaf3_angle =
XMLloadfloat(canopy_node,
"s2_leaf3_angle");
1549 if (new_s2_leaf3_angle != nullvalue_f) {
1553 float new_s2_leaf4_angle =
XMLloadfloat(canopy_node,
"s2_leaf4_angle");
1554 if (new_s2_leaf4_angle != nullvalue_f) {
1558 float new_s2_leaf5_angle =
XMLloadfloat(canopy_node,
"s2_leaf5_angle");
1559 if (new_s2_leaf3_angle != nullvalue_f) {
1563 int2 new_s2_leaf_subdivisions =
XMLloadint2(canopy_node,
"s2_leaf_subdivisions");
1564 if (new_s2_leaf_subdivisions.
x != nullvalue_i && new_s2_leaf_subdivisions.
y != nullvalue_i) {
1568 std::string new_s2_leaf_texture_file =
XMLloadstring(canopy_node,
"s2_leaf_texture_file");
1569 if (new_s2_leaf_texture_file.compare(nullvalue_s) != 0) {
1574 float new_s3_stem_length =
XMLloadint(canopy_node,
"s3_stem_length");
1575 if (new_s3_stem_length != nullvalue_i) {
1579 float new_s3_stem_radius =
XMLloadfloat(canopy_node,
"s3_stem_radius");
1580 if (new_s3_stem_radius != nullvalue_f) {
1584 int new_s3_stem_subdivisions =
XMLloadint(canopy_node,
"s3_stem_subdivisions");
1585 if (new_s3_stem_subdivisions != nullvalue_f) {
1590 if (new_s3_leaf_size.
x != nullvalue_f && new_s3_leaf_size.
y != nullvalue_f) {
1594 int2 new_s3_leaf_subdivisions =
XMLloadint2(canopy_node,
"s3_leaf_subdivisions");
1595 if (new_s3_leaf_subdivisions.
x != nullvalue_i && new_s3_leaf_subdivisions.
y != nullvalue_i) {
1599 int new_s3_number_of_leaves =
XMLloadint(canopy_node,
"s3_number_of_leaves");
1600 if (new_s3_number_of_leaves != nullvalue_i) {
1604 float new_s3_mean_leaf_angle =
XMLloadfloat(canopy_node,
"s3_mean_leaf_angle");
1605 if (new_s3_mean_leaf_angle != nullvalue_f) {
1609 std::string new_s3_leaf_texture_file =
XMLloadstring(canopy_node,
"s3_leaf_texture_file");
1610 if (new_s3_leaf_texture_file.compare(nullvalue_s) != 0) {
1615 float new_s4_stem_length =
XMLloadint(canopy_node,
"s4_stem_length");
1616 if (new_s4_stem_length != nullvalue_i) {
1620 float new_s4_stem_radius =
XMLloadfloat(canopy_node,
"s4_stem_radius");
1621 if (new_s4_stem_radius != nullvalue_f) {
1625 int new_s4_stem_subdivisions =
XMLloadint(canopy_node,
"s4_stem_subdivisions");
1626 if (new_s4_stem_subdivisions != nullvalue_f) {
1630 vec2 new_s4_panicle_size =
XMLloadvec2(canopy_node,
"s4_panicle_size");
1631 if (new_s4_panicle_size.
x != nullvalue_f && new_s4_panicle_size.
y != nullvalue_f) {
1635 int new_s4_panicle_subdivisions =
XMLloadint(canopy_node,
"s4_panicle_subdivisions");
1636 if (new_s4_panicle_subdivisions != nullvalue_f) {
1640 std::string new_s4_seed_texture_file =
XMLloadstring(canopy_node,
"s4_seed_texture_file");
1641 if (new_s4_seed_texture_file.compare(nullvalue_s) != 0) {
1646 if (new_s4_leaf_size.
x != nullvalue_f && new_s4_leaf_size.
y != nullvalue_f) {
1650 int2 new_s4_leaf_subdivisions =
XMLloadint2(canopy_node,
"s4_leaf_subdivisions");
1651 if (new_s4_leaf_subdivisions.
x != nullvalue_i && new_s4_leaf_subdivisions.
y != nullvalue_i) {
1655 int new_s4_number_of_leaves =
XMLloadint(canopy_node,
"s4_number_of_leaves");
1656 if (new_s4_number_of_leaves != nullvalue_i) {
1660 float new_s4_mean_leaf_angle =
XMLloadfloat(canopy_node,
"s4_mean_leaf_angle");
1661 if (new_s4_mean_leaf_angle != nullvalue_f) {
1665 std::string new_s4_leaf_texture_file =
XMLloadstring(canopy_node,
"s4_leaf_texture_file");
1666 if (new_s4_leaf_texture_file.compare(nullvalue_s) != 0) {
1671 float new_s5_stem_length =
XMLloadint(canopy_node,
"s5_stem_length");
1672 if (new_s5_stem_length != nullvalue_i) {
1676 float new_s5_stem_radius =
XMLloadfloat(canopy_node,
"s5_stem_radius");
1677 if (new_s5_stem_radius != nullvalue_f) {
1681 float new_s5_stem_bend =
XMLloadfloat(canopy_node,
"s5_stem_bend");
1682 if (new_s5_stem_bend != nullvalue_f) {
1686 int new_s5_stem_subdivisions =
XMLloadint(canopy_node,
"s5_stem_subdivisions");
1687 if (new_s5_stem_subdivisions != nullvalue_f) {
1691 vec2 new_s5_panicle_size =
XMLloadvec2(canopy_node,
"s5_panicle_size");
1692 if (new_s5_panicle_size.
x != nullvalue_f && new_s5_panicle_size.
y != nullvalue_f) {
1696 int new_s5_panicle_subdivisions =
XMLloadint(canopy_node,
"s5_panicle_subdivisions");
1697 if (new_s5_panicle_subdivisions != nullvalue_f) {
1701 std::string new_s5_seed_texture_file =
XMLloadstring(canopy_node,
"s5_seed_texture_file");
1702 if (new_s5_seed_texture_file.compare(nullvalue_s) != 0) {
1707 if (new_s5_leaf_size.
x != nullvalue_f && new_s5_leaf_size.
y != nullvalue_f) {
1711 int2 new_s5_leaf_subdivisions =
XMLloadint2(canopy_node,
"s5_leaf_subdivisions");
1712 if (new_s5_leaf_subdivisions.
x != nullvalue_i && new_s5_leaf_subdivisions.
y != nullvalue_i) {
1716 int new_s5_number_of_leaves =
XMLloadint(canopy_node,
"s5_number_of_leaves");
1717 if (new_s5_number_of_leaves != nullvalue_i) {
1721 float new_s5_mean_leaf_angle =
XMLloadfloat(canopy_node,
"s5_mean_leaf_angle");
1722 if (new_s5_mean_leaf_angle != nullvalue_f) {
1726 std::string new_s5_leaf_texture_file =
XMLloadstring(canopy_node,
"s5_leaf_texture_file");
1727 if (new_s5_leaf_texture_file.compare(nullvalue_s) != 0) {
1731 float new_plant_spacing =
XMLloadfloat(canopy_node,
"plant_spacing");
1732 if (new_plant_spacing != nullvalue_f) {
1736 float new_row_spacing =
XMLloadfloat(canopy_node,
"row_spacing");
1737 if (new_row_spacing != nullvalue_f) {
1742 if (new_plant_count.
x != nullvalue_i && new_plant_count.
y != nullvalue_i) {
1908 if (printmessages) {
1909 std::cout <<
"Reading XML file: " << filename <<
"..." << std::flush;
1913 std::ifstream f(filename);
1915 std::cerr <<
"failed." << std::endl;
1916 throw(std::runtime_error(
"XML file " + std::string(filename) +
" does not exist."));
1920 pugi::xml_document xmldoc;
1923 pugi::xml_parse_result result = xmldoc.load_file(filename);
1927 std::cout <<
"failed." << std::endl;
1928 throw(std::runtime_error(
"XML file " + std::string(filename) +
" parsed with errors, attribute value: [" + xmldoc.child(
"node").attribute(
"attr").value() +
"]\nError description: " + result.description() +
"\n"));
1931 pugi::xml_node helios = xmldoc.child(
"helios");
1933 if (helios.empty()) {
1934 std::cout <<
"failed." << std::endl;
1935 throw(std::runtime_error(
"ERROR (loadXML): XML file must have tag '<helios> ... </helios>' bounding all other tags."));
1939 for (pugi::xml_node cgen = helios.child(
"canopygenerator"); cgen; cgen = cgen.next_sibling(
"CanopyGenerator")) {
1944 for (pugi::xml_node s = cgen.child(
"HomogeneousCanopyParameters"); s; s = s.next_sibling(
"HomogeneousCanopyParameters")) {
1947 storeCanopyParameters<HomogeneousCanopyParameters>(homogeneouscanopyparameters);
1953 for (pugi::xml_node s = cgen.child(
"SphericalCrownsCanopyParameters"); s; s = s.next_sibling(
"SphericalCrownsCanopyParameters")) {
1956 storeCanopyParameters<SphericalCrownsCanopyParameters>(sphericalcrownscanopyparameters);
1962 for (pugi::xml_node s = cgen.child(
"ConicalCrownsCanopyParameters"); s; s = s.next_sibling(
"ConicalCrownsCanopyParameters")) {
1965 storeCanopyParameters<ConicalCrownsCanopyParameters>(conicalcrownscanopyparameters);
1972 for (pugi::xml_node s = cgen.child(
"VSPGrapevineParameters"); s; s = s.next_sibling(
"VSPGrapevineParameters")) {
1975 storeCanopyParameters<VSPGrapevineParameters>(vspgrapevineparameters);
1981 for (pugi::xml_node s = cgen.child(
"SplitGrapevineParameters"); s; s = s.next_sibling(
"SplitGrapevineParameters")) {
1984 storeCanopyParameters<SplitGrapevineParameters>(splitgrapevineparameters);
1991 for (pugi::xml_node s = cgen.child(
"UnilateralGrapevineParameters"); s; s = s.next_sibling(
"UnilateralGrapevineParameters")) {
1994 storeCanopyParameters<UnilateralGrapevineParameters>(unilateralgrapevineparameters);
2001 for (pugi::xml_node s = cgen.child(
"GobletGrapevineParameters"); s; s = s.next_sibling(
"GobletGrapevineParameters")) {
2004 storeCanopyParameters<GobletGrapevineParameters>(gobletgrapevineparameters);
2011 for (pugi::xml_node s = cgen.child(
"WhiteSpruceCanopyParameters"); s; s = s.next_sibling(
"WhiteSpruceCanopyParameters")) {
2014 storeCanopyParameters<WhiteSpruceCanopyParameters>(whitesprucecanopyparameters);
2020 for (pugi::xml_node s = cgen.child(
"StrawberryParameters"); s; s = s.next_sibling(
"StrawberryParameters")) {
2023 storeCanopyParameters<StrawberryParameters>(strawberryparameters);
2029 for (pugi::xml_node s = cgen.child(
"TomatoParameters"); s; s = s.next_sibling(
"TomatoParameters")) {
2032 storeCanopyParameters<TomatoParameters>(tomatoparameters);
2038 for (pugi::xml_node s = cgen.child(
"WalnutCanopyParameters"); s; s = s.next_sibling(
"WalnutCanopyParameters")) {
2041 storeCanopyParameters<WalnutCanopyParameters>(walnutcanopyparameters);
2047 for (pugi::xml_node s = cgen.child(
"SorghumCanopyParameters"); s; s = s.next_sibling(
"SorghumCanopyParameters")) {
2050 storeCanopyParameters<SorghumCanopyParameters>(sorghumcanopyparameters);
2056 for (pugi::xml_node s = cgen.child(
"BeanParameters"); s; s = s.next_sibling(
"BeanParameters")) {
2059 storeCanopyParameters<BeanParameters>(beanparameters);
2065 for (pugi::xml_node s = cgen.child(
"Ground"); s; s = s.next_sibling(
"Ground")) {
2068 if (origin.
x == nullvalue_f || origin.
y == nullvalue_f || origin.
z == nullvalue_f) {
2070 if (printmessages) {
2071 std::cout <<
"WARNING: origin not provided for ground in file " << filename << std::endl;
2076 if (extent.
x == nullvalue_f || extent.
y == nullvalue_f) {
2078 if (printmessages) {
2079 std::cout <<
"WARNING: horizontal extent not provided for ground in file " << filename << std::endl;
2084 if (texture_subtiles.
x == nullvalue_i || texture_subtiles.
y == nullvalue_i) {
2089 if (texture_subpatches.
x == nullvalue_i || texture_subpatches.
y == nullvalue_i) {
2093 std::string texturefile =
XMLloadstring(s,
"ground_texture_file");
2094 if (texturefile == nullvalue_s) {
2095 texturefile =
"plugins/canopygenerator/textures/dirt.jpg";
2096 if (printmessages) {
2097 std::cout <<
"WARNING: texture map file not provided for ground in file " << filename << std::endl;
2102 if (rotation == nullvalue_f) {
2107 buildGround(origin, extent, texture_subtiles, texture_subpatches, texturefile.c_str(), rotation);
2111 std::cout <<
"done." << std::endl;
2158 if (printmessages) {
2159 std::cout <<
"Building homogeneous canopy..." << std::flush;
2162 std::uniform_real_distribution<float> unif_distribution;
2164 UUID_leaf.resize(1);
2167 float solidFractionx = 1.f;
2168 if (params.leaf_texture_file.empty()) {
2172 solidFractionx = context->
getObjectArea(ID0) / (params.leaf_size.x * params.leaf_size.y);
2175 float leafArea = params.leaf_size.x * params.leaf_size.y * solidFractionx;
2176 int Nleaves = (int) lroundf(params.leaf_area_index * params.canopy_extent.x * params.canopy_extent.y / leafArea);
2178 float Lmax = sqrtf(params.leaf_size.x * params.leaf_size.x + params.leaf_size.y * params.leaf_size.y);
2180 for (
int i = 0; i < Nleaves; i++) {
2182 float rx = unif_distribution(generator);
2183 float ry = unif_distribution(generator);
2184 float rz = unif_distribution(generator);
2186 float rp = unif_distribution(generator);
2191 if (params.buffer ==
"z") {
2192 position = params.canopy_origin +
make_vec3((-0.5f + rx) * params.canopy_extent.x, (-0.5f + ry) * params.canopy_extent.y, 0.5f * Lmax + rz * (params.canopy_height - Lmax));
2193 }
else if (params.buffer ==
"xyz") {
2194 position = params.canopy_origin +
make_vec3(0.5f * Lmax + (rx) * (params.canopy_extent.x - Lmax) + -0.5f * params.canopy_extent.x, 0.5f * Lmax + (ry) * (params.canopy_extent.y - Lmax) + -0.5f * params.canopy_extent.y,
2195 0.5f * Lmax + rz * (params.canopy_height - Lmax));
2197 position = params.canopy_origin +
make_vec3((-0.5f + rx) * params.canopy_extent.x, (-0.5f + ry) * params.canopy_extent.y, (rz) * (params.canopy_height));
2200 SphericalCoord rotation(1.f, sampleLeafPDF(params.leaf_angle_distribution.c_str()), 2.f *
float(
M_PI) * rp);
2209 UUID_leaf.front().push_back(UUID);
2215 if (printmessages) {
2216 std::cout <<
"done." << std::endl;
2218 std::cout <<
"Canopy consists of " << UUID_leaf.size() * UUID_leaf.front().size() <<
" leaves and " << UUIDs_all.size() <<
" total primitives." << std::endl;
2224 if (printmessages) {
2225 std::cout <<
"Building canopy of spherical crowns..." << std::flush;
2228 std::uniform_real_distribution<float> unif_distribution;
2230 vec3 r = params.crown_radius;
2232 std::string cconfig = params.canopy_configuration;
2233 if (cconfig !=
"uniform" && cconfig !=
"random") {
2234 std::cout <<
"WARNING: Unknown canopy configuration parameter for spherical crowns canopy: " << cconfig <<
". Using uniformly spaced configuration." << std::endl;
2235 cconfig =
"uniform";
2238 UUID_leaf.resize(params.plant_count.x * params.plant_count.y);
2241 float solidFractionx = 1.f;
2242 if (params.leaf_texture_file.empty()) {
2246 solidFractionx = context->
getObjectArea(ID0) / (params.leaf_size.x * params.leaf_size.y);
2249 float leafArea = params.leaf_size.x * params.leaf_size.y * solidFractionx;
2250 int Nleaves = (int) lroundf(4.f / 3.f *
float(
M_PI) * r.
x * r.
y * r.
z * params.leaf_area_density / leafArea);
2252 vec2 canopy_extent(params.plant_spacing.x *
float(params.plant_count.x), params.plant_spacing.y *
float(params.plant_count.y));
2255 uint prim_count = 0;
2256 for (
int j = 0; j < params.plant_count.y; j++) {
2257 for (
int i = 0; i < params.plant_count.x; i++) {
2260 if (cconfig ==
"uniform") {
2261 center = params.canopy_origin +
make_vec3(-0.5f * canopy_extent.
x + (
float(i) + 0.5f) * params.plant_spacing.x, -0.5f * canopy_extent.
y + (
float(j) + 0.5f) * params.plant_spacing.y, r.
z);
2262 }
else if (cconfig ==
"random") {
2263 float rx = unif_distribution(generator);
2264 float ry = unif_distribution(generator);
2265 center = params.canopy_origin +
make_vec3(-0.5f * canopy_extent.
x +
float(i) * params.plant_spacing.x + r.
x + (params.plant_spacing.x - 2.f * r.
x) * rx,
2266 -0.5f * canopy_extent.
y +
float(j) * params.plant_spacing.y + r.
y + (params.plant_spacing.y - 2.f * r.
y) * ry, r.
z);
2269 if (params.canopy_rotation != 0) {
2273 for (
int l = 0; l < Nleaves; l++) {
2275 vec3 position(-9999, -9999, -9999);
2277 while (pow(position.
x, 2) / pow(params.crown_radius.x, 2) + pow(position.
y, 2) / pow(params.crown_radius.y, 2) + pow(position.
z, 2) / pow(params.crown_radius.z, 2) > 1.f) {
2279 float u = unif_distribution(generator);
2280 float v = unif_distribution(generator);
2281 float w = unif_distribution(generator);
2283 position =
make_vec3((-1 + 2.f * u) * r.
x, (-1 + 2.f * v) * r.
y, (-1 + 2.f * w) * r.
z);
2286 float theta = sampleLeafPDF(params.leaf_angle_distribution.c_str());
2287 float phi = 2.f * float(
M_PI) * unif_distribution(generator);
2296 UUID_leaf.at(plant_ID).push_back(UUID);
2299 std::vector<uint> UUIDs_all =
getAllUUIDs(plant_ID);
2300 prim_count += UUIDs_all.size();
2308 if (printmessages) {
2309 std::cout <<
"done." << std::endl;
2310 std::cout <<
"Canopy consists of " << UUID_leaf.size() * UUID_leaf.front().size() <<
" leaves and " << prim_count <<
" total primitives." << std::endl;
2316 if (printmessages) {
2317 std::cout <<
"Building canopy of conical crowns..." << std::flush;
2320 std::uniform_real_distribution<float> unif_distribution;
2322 float r = params.crown_radius;
2323 float h = params.crown_height;
2325 std::string cconfig = params.canopy_configuration;
2326 if (cconfig !=
"uniform" && cconfig !=
"random") {
2327 std::cout <<
"WARNING: Unknown canopy configuration parameter for conical crowns canopy: " << cconfig <<
". Using uniformly spaced configuration." << std::endl;
2328 cconfig =
"uniform";
2331 UUID_leaf.resize(params.plant_count.x * params.plant_count.y);
2334 float solidFractionx = 1.f;
2335 if (params.leaf_texture_file.empty()) {
2339 solidFractionx = context->
getObjectArea(ID0) / (params.leaf_size.x * params.leaf_size.y);
2342 float leafArea = params.leaf_size.x * params.leaf_size.y * solidFractionx;
2343 int Nleaves = (int) lroundf(1.f / 3.f *
float(
M_PI) * r * r * h * params.leaf_area_density / leafArea);
2345 vec2 canopy_extent(params.plant_spacing.x *
float(params.plant_count.x), params.plant_spacing.y *
float(params.plant_count.y));
2348 uint prim_count = 0;
2349 for (
int j = 0; j < params.plant_count.y; j++) {
2350 for (
int i = 0; i < params.plant_count.x; i++) {
2353 if (cconfig ==
"uniform") {
2354 center = params.canopy_origin +
make_vec3(-0.5f * canopy_extent.
x + (
float(i) + 0.5f) * params.plant_spacing.x, -0.5f * canopy_extent.
y + (
float(j) + 0.5f) * params.plant_spacing.y, 0);
2355 }
else if (cconfig ==
"random") {
2356 float rx = unif_distribution(generator);
2357 float ry = unif_distribution(generator);
2358 center = params.canopy_origin +
make_vec3(-0.5f * canopy_extent.
x +
float(i) * params.plant_spacing.x + r + (params.plant_spacing.x - 2.f * r) * rx,
2359 -0.5f * canopy_extent.
y +
float(j) * params.plant_spacing.y + r + (params.plant_spacing.y - 2.f * r) * ry, 0);
2362 if (params.canopy_rotation != 0) {
2366 for (
int l = 0; l < Nleaves; l++) {
2368 vec3 position(-9999, -9999, -9999);
2370 while ((powf(position.
x, 2) + powf(position.
y, 2)) / powf(r / h, 2) > powf(h - position.
z, 2)) {
2372 float u = unif_distribution(generator);
2373 float v = unif_distribution(generator);
2374 float w = unif_distribution(generator);
2376 position =
make_vec3((-1 + 2.f * u) * r, (-1 + 2.f * v) * r, w * h);
2379 float theta = sampleLeafPDF(params.leaf_angle_distribution.c_str());
2380 float phi = 2.f * float(
M_PI) * unif_distribution(generator);
2389 UUID_leaf.at(plant_ID).push_back(UUID);
2392 std::vector<uint> UUIDs_all =
getAllUUIDs(plant_ID);
2393 prim_count += UUIDs_all.size();
2401 if (printmessages) {
2402 std::cout <<
"done." << std::endl;
2403 std::cout <<
"Canopy consists of " << UUID_leaf.size() * UUID_leaf.front().size() <<
" leaves and " << prim_count <<
" total primitives." << std::endl;
2409 if (printmessages) {
2410 std::cout <<
"Building canopy of VSP grapevine..." << std::flush;
2413 if (params.cordon_height < params.trunk_height) {
2414 std::cout <<
"failed." << std::endl;
2415 throw(std::runtime_error(
"ERROR (CanopyGenerator::buildCanopy)): Cannot build VSP grapevine canopy. Cordon height cannot be less than the trunk height."));
2418 std::uniform_real_distribution<float> unif_distribution;
2420 vec2 canopy_extent(params.plant_spacing *
float(params.plant_count.x), params.row_spacing *
float(params.plant_count.y));
2422 uint prim_count = 0;
2423 for (
int j = 0; j < params.plant_count.y; j++) {
2424 for (
int i = 0; i < params.plant_count.x; i++) {
2426 if (params.missing_plant_probability > 0) {
2427 float random_draw = context->
randu();
2428 if (random_draw <= params.missing_plant_probability) {
2434 float plant_spacing = params.plant_spacing +
getVariation(params.plant_spacing_spread, generator);
2435 float row_spacing = params.row_spacing +
getVariation(params.row_spacing_spread, generator);
2436 vec3 center = params.canopy_origin +
make_vec3(-0.5f * canopy_extent.
x + (
float(i) + 0.5f) * plant_spacing, -0.5f * canopy_extent.
y + (
float(j) + 0.5f) * row_spacing, 0);
2440 std::vector<uint> UUIDs_all =
getAllUUIDs(plant_ID);
2441 prim_count += UUIDs_all.size();
2446 if (printmessages) {
2447 std::cout <<
"done." << std::endl;
2448 std::cout <<
"Canopy consists of " << UUID_leaf.size() * UUID_leaf.front().size() <<
" leaves and " << prim_count <<
" total primitives." << std::endl;
2454 if (printmessages) {
2455 std::cout <<
"Building canopy of split trellis grapevine..." << std::flush;
2458 std::uniform_real_distribution<float> unif_distribution;
2460 vec2 canopy_extent(params.plant_spacing *
float(params.plant_count.x), params.row_spacing *
float(params.plant_count.y));
2462 uint prim_count = 0;
2463 for (
int j = 0; j < params.plant_count.y; j++) {
2464 for (
int i = 0; i < params.plant_count.x; i++) {
2466 if (params.missing_plant_probability > 0) {
2467 float random_draw = context->
randu();
2468 if (random_draw <= params.missing_plant_probability) {
2474 float plant_spacing = params.plant_spacing +
getVariation(params.plant_spacing_spread, generator);
2475 float row_spacing = params.row_spacing +
getVariation(params.row_spacing_spread, generator);
2476 vec3 center = params.canopy_origin +
make_vec3(-0.5f * canopy_extent.
x + (
float(i) + 0.5f) * plant_spacing, -0.5f * canopy_extent.
y + (
float(j) + 0.5f) * row_spacing, 0);
2480 std::vector<uint> UUIDs_all =
getAllUUIDs(plant_ID);
2481 prim_count += UUIDs_all.size();
2486 if (printmessages) {
2487 std::cout <<
"done." << std::endl;
2488 std::cout <<
"Canopy consists of " << UUID_leaf.size() * UUID_leaf.front().size() <<
" leaves and " << prim_count <<
" total primitives." << std::endl;
2494 if (printmessages) {
2495 std::cout <<
"Building canopy of unilateral trellis grapevine..." << std::flush;
2498 std::uniform_real_distribution<float> unif_distribution;
2500 vec2 canopy_extent(params.plant_spacing *
float(params.plant_count.x), params.row_spacing *
float(params.plant_count.y));
2502 uint prim_count = 0;
2503 for (
int j = 0; j < params.plant_count.y; j++) {
2504 for (
int i = 0; i < params.plant_count.x; i++) {
2506 if (params.missing_plant_probability > 0) {
2507 float random_draw = context->
randu();
2508 if (random_draw <= params.missing_plant_probability) {
2514 float plant_spacing = params.plant_spacing +
getVariation(params.plant_spacing_spread, generator);
2515 float row_spacing = params.row_spacing +
getVariation(params.row_spacing_spread, generator);
2516 vec3 center = params.canopy_origin +
make_vec3(-0.5f * canopy_extent.
x + (
float(i) + 0.5f) * plant_spacing, -0.5f * canopy_extent.
y + (
float(j) + 0.5f) * row_spacing, 0);
2520 std::vector<uint> UUIDs_all =
getAllUUIDs(plant_ID);
2521 prim_count += UUIDs_all.size();
2526 if (printmessages) {
2527 std::cout <<
"done." << std::endl;
2528 std::cout <<
"Canopy consists of " << UUID_leaf.size() * UUID_leaf.front().size() <<
" leaves and " << prim_count <<
" total primitives." << std::endl;
2534 if (printmessages) {
2535 std::cout <<
"Building canopy of goblet trellis grapevine..." << std::flush;
2538 std::uniform_real_distribution<float> unif_distribution;
2540 vec2 canopy_extent(params.plant_spacing *
float(params.plant_count.x), params.row_spacing *
float(params.plant_count.y));
2542 uint prim_count = 0;
2543 for (
int j = 0; j < params.plant_count.y; j++) {
2544 for (
int i = 0; i < params.plant_count.x; i++) {
2546 if (params.missing_plant_probability > 0) {
2547 float random_draw = context->
randu();
2548 if (random_draw <= params.missing_plant_probability) {
2554 float plant_spacing = params.plant_spacing +
getVariation(params.plant_spacing_spread, generator);
2555 float row_spacing = params.row_spacing +
getVariation(params.row_spacing_spread, generator);
2556 vec3 center = params.canopy_origin +
make_vec3(-0.5f * canopy_extent.
x + (
float(i) + 0.5f) * plant_spacing, -0.5f * canopy_extent.
y + (
float(j) + 0.5f) * row_spacing, 0);
2560 std::vector<uint> UUIDs_all =
getAllUUIDs(plant_ID);
2561 prim_count += UUIDs_all.size();
2566 if (printmessages) {
2567 std::cout <<
"done." << std::endl;
2568 std::cout <<
"Canopy consists of " << UUID_leaf.size() * UUID_leaf.front().size() <<
" leaves and " << prim_count <<
" total primitives." << std::endl;
2574 if (printmessages) {
2575 std::cout <<
"Building canopy of white spruce trees..." << std::flush;
2578 std::uniform_real_distribution<float> unif_distribution;
2580 vec2 canopy_extent(params.plant_spacing.x *
float(params.plant_count.x), params.plant_spacing.y *
float(params.plant_count.y));
2582 std::string cconfig = params.canopy_configuration;
2583 if (cconfig !=
"uniform" && cconfig !=
"random") {
2584 std::cout <<
"WARNING: Unknown canopy configuration parameter for white spruce canopy: " << cconfig <<
". Using uniformly spaced configuration." << std::endl;
2585 cconfig =
"uniform";
2588 float r = params.crown_radius;
2590 uint prim_count = 0;
2591 for (
int j = 0; j < params.plant_count.y; j++) {
2592 for (
int i = 0; i < params.plant_count.x; i++) {
2595 if (cconfig !=
"uniform") {
2596 center = params.canopy_origin +
make_vec3(-0.5f * canopy_extent.
x + (
float(i) + 0.5f) * params.plant_spacing.x, -0.5f * canopy_extent.
y + (
float(j) + 0.5f) * params.plant_spacing.y, 0);
2597 }
else if (cconfig !=
"random") {
2598 float rx = unif_distribution(generator);
2599 float ry = unif_distribution(generator);
2600 center = params.canopy_origin +
make_vec3(-0.5f * canopy_extent.
x +
float(i) * params.plant_spacing.x + r + (params.plant_spacing.x - 2.f * r) * rx,
2601 -0.5f * canopy_extent.
y +
float(j) * params.plant_spacing.y + r + (params.plant_spacing.y - 2.f * r) * ry, 0);
2604 if (params.canopy_rotation != 0) {
2610 std::vector<uint> UUIDs_all =
getAllUUIDs(plant_ID);
2611 prim_count += UUIDs_all.size();
2615 if (printmessages) {
2616 std::cout <<
"done." << std::endl;
2617 std::cout <<
"Canopy consists of " << UUID_leaf.size() * UUID_leaf.front().size() <<
" leaves and " << prim_count <<
" total primitives." << std::endl;