51 void constrain(Row row,
bool preserveTranslation =
false,
52 size_t preferredNode = std::numeric_limits<size_t>::max())
54 for (
const auto &value : row)
56 if (value.first >= count || !std::isfinite(value.second))
58 throw std::runtime_error(
"Invalid velocity constraint.");
61 const double tolerance = 128 * std::numeric_limits<double>::epsilon();
64 std::map<size_t, size_t> pending;
65 for (
const auto &value : row)
67 const auto found = pivotIndex.find(value.first);
68 if (found != pivotIndex.end())
70 pending.emplace(found->second, value.first);
73 while (!pending.empty())
75 const auto item = *pending.begin();
76 pending.erase(pending.begin());
77 const double factor = row[item.second];
78 row.erase(item.second);
79 for (
const auto &value : pivots[item.first].row)
81 row[value.first] += factor * value.second;
82 const auto found = pivotIndex.find(value.first);
83 if (found != pivotIndex.end())
85 pending.emplace(found->second, value.first);
89 for (
auto it = row.begin(); it != row.end();)
91 if (std::abs(it->second) <= tolerance)
104 auto pivot = std::max_element(row.begin(), row.end(), [](
const auto &
x,
const auto &
y)
105 { return std::abs(x.second) < std::abs(y.second); });
110 if (preserveTranslation)
112 long double otherSum = 0.0L;
113 for (
const auto &value : row)
115 if (value.first !=
pivot->first)
117 otherSum += value.second;
120 pivot->second = -
static_cast<double>(otherSum);
121 if (std::abs(
pivot->second) <= tolerance)
130 pivot = std::max_element(row.begin(), row.end(), [](
const auto &
x,
const auto &
y)
131 { return std::abs(x.second) < std::abs(y.second); });
132 const auto preferred = row.find(preferredNode);
133 if (preferred != row.end() && std::abs(preferred->second) >= 0.5 * std::abs(
pivot->second))
137 const size_t id =
pivot->first;
138 const double coefficient =
pivot->second;
140 for (
auto &value : row)
142 value.second /= -coefficient;
144 pivotIndex.emplace(
id, pivots.size());
145 pivots.push_back({id, std::move(row)});
150 std::vector<Row> expressions(count);
151 size_t freeCount = 0;
152 for (
size_t i = 0;
i < count; ++
i)
154 if (!pivotIndex.count(
i))
156 expressions[
i].emplace(freeCount++, 1.0);
159 for (
auto it = pivots.rbegin(); it != pivots.rend(); ++it)
161 for (
const auto &dependency : it->row)
163 for (
const auto &value : expressions[dependency.first])
165 expressions[it->node][value.first] += dependency.second * value.second;
169 for (
size_t i = 0;
i < count; ++
i)
171 for (
const auto &value : expressions[
i])
173 for (
int d = 0; d < dim; ++d)
175 triplets.emplace_back(dim *
i + d, dim * value.first + d, value.second);