#include "fractal.hpp" #include #include #include using mtl::endl; namespace mlog = mtl::log; using mtl::fixed; using mtl::vec2; using mtl::mat; mtl::mat<2, 2> create_rotation(mtl::fixed angle_cos) { fixed angle_sin = fixed(1) - angle_cos * angle_cos; return mat<2, 2>({ { angle_cos, -angle_sin }, { angle_sin, angle_cos } }); } namespace fractal { // ---------- RULESET ---------- token_id_t ruleset_t::add_token(token_type_e type, mtl::fixed value, uint32_t mark) { if (m_tokens.full()) { throw mtl::length_error(); } token_t tok { .m_type = type, .m_value = value, .m_mark = mark}; m_tokens.push_back(tok); return m_tokens.size() - 1; } group_id_t ruleset_t::add_group_characteristic(const etl::ivector& tokens, uint32_t factor) { if (m_group_characteristics.full()) { throw mtl::length_error(); } if (tokens.size() > g_max_cgroup_tokens) { throw mtl::length_error(); } m_group_characteristics.push_back(group_characteristic_t()); group_characteristic_t& chr = m_group_characteristics.back(); chr.m_factor = factor; for (token_id_t tok : tokens) { if (!valid_token(tok)) { throw mtl::invalid_argument(); } chr.m_token_ids.push_back(tok); } return m_group_characteristics.size() - 1; } weighted_group_id_t ruleset_t::add_weighted_group(const etl::ivector>& weights) { if (m_weighted_groups.full()) { throw mtl::length_error(); } if (weights.size() > g_max_wgroup_weights) { throw mtl::length_error(); } m_weighted_groups.push_back(weighted_group_t()); weighted_group_t& wgroup = m_weighted_groups.back(); for (const auto& weight : weights) { if (!valid_group_characteristic(weight.first)) { throw mtl::invalid_argument(); } wgroup.m_groups.push_back(weight.first); wgroup.m_weights.push_back(weight.second); wgroup.m_weight_total += weight.second; } return m_weighted_groups.size() - 1; } branch_rule_id_t ruleset_t::add_branch_rule(token_id_t match, group_id_t group) { if (!valid_token(match) || !valid_group_characteristic(group)) { throw mtl::invalid_argument(); } branch_rule_t rule { .m_match = match, .m_weighted = false, .m_group = { .basic = group } }; m_branch_rules.push_back(rule); return m_branch_rules.size() - 1; } branch_rule_id_t ruleset_t::add_branch_rule_weighted(token_id_t match, weighted_group_id_t wgroup) { if (!valid_token(match) || !valid_weighted_group(wgroup)) { throw mtl::invalid_argument(); } branch_rule_t rule { .m_match = match, .m_weighted = true, .m_group = { .weighted = wgroup } }; m_branch_rules.push_back(rule); return m_branch_rules.size() - 1; } #if 0 token_id_t generator_t::add_token(token_type_e type, mtl::fixed value) { log::debug << "Adding token with type " << (int)type << endl; if (m_processed) { log::error << "Failed to add token, already preprocessed" << endl; throw mtl::system_error(); } if (m_tokens.full()) { log::error << "Failed to add token, tokens full" << endl; throw mtl::length_error(); } switch (type) { case token_type_e::walk: case token_type_e::rotate: case token_type_e::generate: m_tokens.push_back(token_t{type, value}); return m_tokens.size() - 1; // IDs are simply index into vector default: log::error << "Failed to add token, invalid token type" << endl; throw mtl::invalid_argument(); } } group_id_t generator_t::add_group_characteristic(uint32_t factor, const etl::ivector& tokens) { if (m_processed) { log::error << "Failed to add characteristic, already preprocessed" << endl; throw mtl::system_error(); } if (m_group_characteristics.full()) { log::error << "Failed to add characteristic, vector full" << endl; throw mtl::length_error(); } // We need to look for invalid tokens AOT, because we only modify the // generator if the supplied data is valid. size_t num_tokens = m_tokens.size(); for (token_id_t token : tokens) { if (token >= num_tokens) { log::error << "Failed to add characteristic, invalid token found: " << token << " >= " << num_tokens << endl; throw mtl::invalid_argument(); } } m_group_characteristics.push_back(group_characteristic_t()); group_characteristic_t& characteristic = m_group_characteristics.back(); characteristic.m_factor = factor; characteristic.m_token_ids.assign(tokens.begin(), tokens.end()); return m_group_characteristics.size() - 1; // IDs are just the index into vector } group_id_t generator_t::add_group_characteristic(const etl::ivector& tokens) { return add_group_characteristic(1, tokens); } weighted_group_id_t generator_t::add_weighted_group(const etl::ivector>& group_weights) { if (m_processed) { log::error << "Failed to add weighted group, already preprocessed" << endl; throw mtl::system_error(); } if (m_weighted_groups.full()) { log::error << "Failed to add weighted group, vector full" << endl; throw mtl::length_error(); } size_t num_groups = m_group_characteristics.size(); for (etl::pair pair : group_weights) { if (pair.first >= num_groups) { log::error << "Failed to add weighted group, invalid group found: " << pair.first << " >= " << num_groups << endl; throw mtl::invalid_argument(); } } m_weighted_groups.push_back(weighted_group_t()); weighted_group_t& wgroup = m_weighted_groups.back(); uint32_t weight_total = 0; for (etl::pair pair : group_weights) { wgroup.m_groups.push_back(pair.first); wgroup.m_weights.push_back(pair.second); wgroup.m_weight_total += pair.second; } wgroup.m_weight_total = weight_total; return m_weighted_groups.size() - 1; } weighted_group_id_t generator_t::add_weighted_group(group_id_t group) { if (m_processed) { log::error << "Failed to add weighted group, already preprocessed" << endl; throw mtl::system_error(); } if (m_weighted_groups.full()) { log::error << "Failed to add weighted group, vector full" << endl; throw mtl::length_error(); } if (group >= m_group_characteristics.size()) { log::error << "Failed to add weighted group, invalid group encountered" << endl; throw mtl::invalid_argument(); } m_weighted_groups.push_back(weighted_group_t()); weighted_group_t& wgroup = m_weighted_groups.back(); wgroup.m_groups.push_back(group); wgroup.m_weights.push_back(1); // We still need to supply a weight wgroup.m_weight_total = 1; return m_weighted_groups.size() - 1; } branch_rule_basic_id_t generator_t::add_basic_branch_rule(token_id_t match, weighted_group_id_t wgroup) { if (m_processed) { log::error << "Failed to add basic branch rule, already preprocessed" << endl; throw mtl::system_error(); } if (m_basic_branch_rules.full()) { log::error << "Failed to add basic branch rule, vector full" << endl; throw mtl::length_error(); } if (match >= m_tokens.size()) { log::error << "Failed to add basic branch rule, invalid match token" << endl; throw mtl::invalid_argument(); } if (wgroup >= m_weighted_groups.size()) { log::error << "Failed to add basic branch rule, invalid weighted group" << endl; throw mtl::invalid_argument(); } m_basic_branch_rules.push_back(branch_rule_basic_t{match, wgroup}); return m_basic_branch_rules.size() - 1; } branch_rule_marking_id_t generator_t::add_marking_branch_rule(token_id_t match, uint32_t marker_id) { if (m_processed) { log::error << "Failed to add marking branch rule, already preprocessed" << endl; throw mtl::system_error(); } if (m_basic_branch_rules.full()) { log::error << "Failed to add marking branch rule, vector full" << endl; throw mtl::length_error(); } if (match >= m_tokens.size()) { log::error << "Failed to add marking branch rule, invalid match token" << endl; throw mtl::invalid_argument(); } m_marking_branch_rules.push_back(branch_rule_marking_t{match, marker_id}); return m_marking_branch_rules.size() - 1; } void generator_t::set_axiom(weighted_group_id_t wgroup) { if (wgroup >= m_weighted_groups.size()) { log::error << "Failed to set axiom, invalid weighted group" << endl; throw mtl::invalid_argument(); } m_axiom = wgroup; } void generator_t::preprocess() { } void generator_t::set_scale_factor(mtl::fixed scale_factor) noexcept { } void generator_t::set_initial_position(mtl::vec2 position) noexcept { } void generator_t::set_initial_orientation(mtl::fixed orientation) noexcept { } bool generator_t::step_generation(const etl::ivector& out_markers) noexcept { } #endif } // namespace fractal