// SPDX-License-Identifier: GPL-2.0-or-later /** @file * PathVectorSatellites a class to manage satellites -per node extra data- in a pathvector *//* * Authors: see git history * Jabiertxof * Nathan Hurst * Johan Engelen * Josh Andler * suv * Mc- * Liam P. White * Krzysztof KosiƄski * This code is in public domain * * Copyright (C) 2018 Authors * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ #include #include #include "util/units.h" Geom::PathVector PathVectorSatellites::getPathVector() const { return _pathvector; } void PathVectorSatellites::setPathVector(Geom::PathVector pathv) { _pathvector = pathv; } Satellites PathVectorSatellites::getSatellites() { return _satellites; } void PathVectorSatellites::setSatellites(Satellites satellites) { _satellites = satellites; } size_t PathVectorSatellites::getTotalSatellites() { size_t counter = 0; for (auto & _satellite : _satellites) { counter += _satellite.size(); } return counter; } std::pair PathVectorSatellites::getIndexData(size_t index) { size_t counter = 0; for (size_t i = 0; i < _satellites.size(); ++i) { for (size_t j = 0; j < _satellites[i].size(); ++j) { if (index == counter) { return std::make_pair(i,j); } counter++; } } return std::make_pair(0,0); } void PathVectorSatellites::setSelected(std::vector selected) { size_t counter = 0; for (auto & _satellite : _satellites) { for (auto & j : _satellite) { if (find (selected.begin(), selected.end(), counter) != selected.end()) { j.setSelected(true); } else { j.setSelected(false); } counter++; } } } void PathVectorSatellites::updateSteps(size_t steps, bool apply_no_radius, bool apply_with_radius, bool only_selected) { for (auto & _satellite : _satellites) { for (auto & j : _satellite) { if ((!apply_no_radius && j.amount == 0) || (!apply_with_radius && j.amount != 0)) { continue; } if (only_selected) { if (j.selected) { j.steps = steps; } } else { j.steps = steps; } } } } void PathVectorSatellites::updateAmount(double radius, bool apply_no_radius, bool apply_with_radius, bool only_selected, bool use_knot_distance, bool flexible) { double power = 0; if (!flexible) { power = radius; } else { power = radius / 100; } for (size_t i = 0; i < _satellites.size(); ++i) { for (size_t j = 0; j < _satellites[i].size(); ++j) { boost::optional previous_index = boost::none; if (j == 0 && _pathvector[i].closed()) { previous_index = count_path_nodes(_pathvector[i]) - 1; } else if (!_pathvector[i].closed() || j != 0) { previous_index = j - 1; } if (!_pathvector[i].closed() && j == 0) { _satellites[i][j].amount = 0; continue; } if (count_path_nodes(_pathvector[i]) == j) { continue; } if ((!apply_no_radius && _satellites[i][j].amount == 0) || (!apply_with_radius && _satellites[i][j].amount != 0)) { continue; } if (_satellites[i][j].selected || !only_selected) { if (!use_knot_distance && !flexible) { if (previous_index) { _satellites[i][j].amount = _satellites[i][j].radToLen(power, _pathvector[i][*previous_index], _pathvector[i][j]); if (power && !_satellites[i][j].amount) { g_warning("Seems a too high radius value"); } } else { _satellites[i][j].amount = 0.0; } } else { _satellites[i][j].amount = power; } } } } } void PathVectorSatellites::convertUnit(Glib::ustring in, Glib::ustring to, bool apply_no_radius, bool apply_with_radius) { for (size_t i = 0; i < _satellites.size(); ++i) { for (size_t j = 0; j < _satellites[i].size(); ++j) { if (!_pathvector[i].closed() && j == 0) { _satellites[i][j].amount = 0; continue; } if (count_path_nodes(_pathvector[i]) == j) { continue; } if ((!apply_no_radius && _satellites[i][j].amount == 0) || (!apply_with_radius && _satellites[i][j].amount != 0)) { continue; } _satellites[i][j].amount = Inkscape::Util::Quantity::convert(_satellites[i][j].amount, in.c_str(), to.c_str()); } } } void PathVectorSatellites::updateSatelliteType(SatelliteType satellitetype, bool apply_no_radius, bool apply_with_radius, bool only_selected) { for (size_t i = 0; i < _satellites.size(); ++i) { for (size_t j = 0; j < _satellites[i].size(); ++j) { if ((!apply_no_radius && _satellites[i][j].amount == 0) || (!apply_with_radius && _satellites[i][j].amount != 0)) { continue; } if (count_path_nodes(_pathvector[i]) == j) { if (!only_selected) { _satellites[i][j].satellite_type = satellitetype; } continue; } if (only_selected) { Geom::Point satellite_point = _pathvector[i].pointAt(j); if (_satellites[i][j].selected) { _satellites[i][j].satellite_type = satellitetype; } } else { _satellites[i][j].satellite_type = satellitetype; } } } } void PathVectorSatellites::recalculateForNewPathVector(Geom::PathVector const pathv, Satellite const S) { // pathv && _pathvector came here: // * with diferent number of nodes // * without empty subpats // * _pathvector and satellites (old data) are paired Satellites satellites; bool found = false; //TODO evaluate fix on nodes at same position size_t number_nodes = count_pathvector_nodes(pathv); size_t previous_number_nodes = getTotalSatellites(); for (const auto & i : pathv) { std::vector path_satellites; size_t count = count_path_nodes(i); for (size_t j = 0; j < count; j++) { found = false; for (size_t k = 0; k < _pathvector.size(); k++) { size_t count2 = count_path_nodes(_pathvector[k]); for (size_t l = 0; l < count2; l++) { if (Geom::are_near(_pathvector[k][l].initialPoint(), i[j].initialPoint())) { path_satellites.push_back(_satellites[k][l]); found = true; break; } } if (found) { break; } } if (!found) { path_satellites.push_back(S); } } satellites.push_back(path_satellites); } setPathVector(pathv); setSatellites(satellites); } /* Local Variables: mode:c++ c-file-style:"stroustrup" c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :