Tatooine
line.h
Go to the documentation of this file.
1#ifndef TATOOINE_LINE_H
2#define TATOOINE_LINE_H
3//==============================================================================
10#include <tatooine/handle.h>
12#include <tatooine/linspace.h>
13#include <tatooine/property.h>
14#include <tatooine/tags.h>
15#include <tatooine/tensor.h>
16
17#include <cassert>
18#include <deque>
19#include <list>
20#include <map>
21#include <set>
22#include <stdexcept>
23//==============================================================================
24namespace tatooine {
25//============================================================================
26namespace detail::line {
27//============================================================================
28template <floating_point Real, std::size_t NumDimensions, typename T,
29 template <typename> typename InterpolationKernel>
30struct vertex_property_sampler;
31//============================================================================
32} // namespace detail::line
33//============================================================================
34template <floating_point Real, std::size_t NumDimensions>
35struct line {
36 //============================================================================
38 using real_type = Real;
41 using pos_container_type = std::deque<pos_type>;
43 //============================================================================
44 // Handles
45 //============================================================================
46 struct vertex_handle : handle<vertex_handle> {
48 };
49
52 friend struct detail::line::vertex_container<Real, NumDimensions,
54
56 template <typename T>
59 std::map<std::string, std::unique_ptr<vertex_property_type>>;
60
64
65 template <typename T, template <typename> typename InterpolationKernel>
67 detail::line::vertex_property_sampler<Real, NumDimensions, T,
68 InterpolationKernel>;
69 //============================================================================
70 // static methods
71 //============================================================================
72 static constexpr auto num_dimensions() -> std::size_t {
73 return NumDimensions;
74 }
75 //============================================================================
76 // members
77 //============================================================================
78 private:
80 bool m_is_closed = false;
81
82 protected:
86
87 //============================================================================
88 public:
89 line() = default;
90 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
91 line(line const& other)
93 for (auto& [name, prop] : other.m_vertex_properties) {
94 m_vertex_properties[name] = prop->clone();
95 }
97 m_parameterization_property = &vertex_property<Real>("parameterization");
98 }
99 if (other.m_tangent_property) {
101 &vertex_property<vec<Real, NumDimensions>>("tangents");
102 }
103 }
104 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
105 line(line&& other) noexcept = default;
106 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
107 auto operator=(line const& other) -> line& {
108 m_vertices = other.m_vertices;
109 m_is_closed = other.m_is_closed;
110 m_vertex_properties.clear();
111 for (auto& [name, prop] : other.m_vertex_properties) {
112 m_vertex_properties[name] = prop->clone();
113 }
114 if (other.m_parameterization_property) {
115 m_parameterization_property = &vertex_property<Real>("parameterization");
116 }
117 if (other.m_tangent_property) {
119 &vertex_property<vec<Real, NumDimensions>>("tangents");
120 }
121 return *this;
122 }
123 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
124 auto operator=(line&& other) noexcept -> line& = default;
125 //----------------------------------------------------------------------------
126 line(pos_container_type const& data, bool is_closed = false)
127 : m_vertices{data}, m_is_closed{is_closed} {}
128 //----------------------------------------------------------------------------
129 line(pos_container_type&& data, bool is_closed = false)
130 : m_vertices{std::move(data)}, m_is_closed{is_closed} {}
131 //----------------------------------------------------------------------------
132 line(std::convertible_to<pos_type> auto&&... vs)
133 : m_vertices{pos_type{std::forward<decltype(vs)>(vs)}...},
134 m_is_closed{false} {}
135 //----------------------------------------------------------------------------
136 line(filesystem::path const& path) { read_single(path); }
137 //----------------------------------------------------------------------------
139 //----------------------------------------------------------------------------
140 auto empty() const { return m_vertices.empty(); }
141 //----------------------------------------------------------------------------
142 auto clear() { return m_vertices.clear(); }
143 //============================================================================
144 // vertex
145 //============================================================================
146 auto vertex_at(std::size_t const i) const -> auto const& {
147 return m_vertices[i];
148 }
149 auto vertex_at(std::size_t const i) -> auto& { return m_vertices[i]; }
150 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
151 auto vertex_at(vertex_handle const i) const -> auto const& {
152 return m_vertices[i.index()];
153 }
154 auto vertex_at(vertex_handle const i) -> auto& {
155 return m_vertices[i.index()];
156 }
157 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
158 auto at(vertex_handle const i) const -> auto const& {
159 return m_vertices[i.index()];
160 }
161 auto at(vertex_handle const i) -> auto& { return m_vertices[i.index()]; }
162 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
163 auto operator[](vertex_handle const i) const -> auto const& {
164 return m_vertices[i.index()];
165 }
166 auto operator[](vertex_handle const i) -> auto& {
167 return m_vertices[i.index()];
168 }
169 //----------------------------------------------------------------------------
170 auto front_vertex() const -> auto const& { return m_vertices.front(); }
171 auto front_vertex() -> auto& { return m_vertices.front(); }
172 //----------------------------------------------------------------------------
173 auto back_vertex() const -> auto const& { return m_vertices.back(); }
174 auto back_vertex() -> auto& { return m_vertices.back(); }
175 //----------------------------------------------------------------------------
176 auto push_back(arithmetic auto const... components)
177 requires(sizeof...(components) == NumDimensions)
178 {
179 m_vertices.push_back(pos_type{static_cast<Real>(components)...});
180 for (auto& [name, prop] : m_vertex_properties) {
181 prop->push_back();
182 }
183 return vertex_handle{m_vertices.size() - 1};
184 }
185 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
186 auto push_back(pos_type const& p) {
187 m_vertices.push_back(p);
188 for (auto& [name, prop] : m_vertex_properties) {
189 prop->push_back();
190 }
191 return vertex_handle{m_vertices.size() - 1};
192 }
193 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
194 auto push_back(pos_type&& p) {
195 m_vertices.emplace_back(std::move(p));
196 for (auto& [name, prop] : m_vertex_properties) {
197 prop->push_back();
198 }
199 return vertex_handle{m_vertices.size() - 1};
200 }
201 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
202 template <typename OtherReal>
204 m_vertices.push_back(pos_type{p});
205 for (auto& [name, prop] : m_vertex_properties) {
206 prop->push_back();
207 }
208 return vertex_handle{m_vertices.size() - 1};
209 }
210 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
211 auto pop_back() { m_vertices.pop_back(); }
212 //----------------------------------------------------------------------------
213 auto push_front(arithmetic auto const... components)
214 requires(sizeof...(components) == NumDimensions)
215 {
216 m_vertices.push_front(pos_type{static_cast<Real>(components)...});
217 for (auto& [name, prop] : m_vertex_properties) {
218 prop->push_front();
219 }
220 return vertex_handle{0};
221 }
222 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
223 auto push_front(pos_type const& p) {
224 m_vertices.push_front(p);
225 for (auto& [name, prop] : m_vertex_properties) {
226 prop->push_front();
227 }
228 return vertex_handle{0};
229 }
230 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
232 m_vertices.emplace_front(std::move(p));
233 for (auto& [name, prop] : m_vertex_properties) {
234 prop->push_front();
235 }
236 return vertex_handle{0};
237 }
238 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
239 template <typename OtherReal>
241 m_vertices.push_front(pos_type{p});
242 for (auto& [name, prop] : m_vertex_properties) {
243 prop->push_front();
244 }
245 return vertex_handle{0};
246 }
247 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
248 auto pop_front() { m_vertices.pop_front(); }
249 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
250 auto vertices() const { return vertex_container_type{*this}; }
251 auto num_vertices() const { return m_vertices.size(); }
252 auto num_line_segments() const {
253 return (num_vertices() - (is_closed() ? 0 : 1));
254 }
255 //----------------------------------------------------------------------------
256 template <template <typename> typename InterpolationKernel>
257 auto sampler() const {
259 *this};
260 }
261 //----------------------------------------------------------------------------
262 auto linear_sampler() const { return sampler<interpolation::linear>(); }
263 //----------------------------------------------------------------------------
264 auto cubic_sampler() const { return sampler<interpolation::cubic>(); }
265 //----------------------------------------------------------------------------
266 template <template <typename> typename InterpolationKernel, typename T>
267 auto sampler(typed_vertex_property_type<T> const& prop) const {
269 InterpolationKernel>{*this, prop};
270 }
271 //----------------------------------------------------------------------------
272 template <typename T>
274 return sampler<interpolation::linear>(prop);
275 }
276 //----------------------------------------------------------------------------
277 template <typename T>
279 return sampler<interpolation::cubic>(prop);
280 }
281 //----------------------------------------------------------------------------
282 template <template <typename> typename InterpolationKernel, typename T>
283 auto vertex_property_sampler(std::string const& name) const {
284 return sampler<InterpolationKernel>(vertex_property<T>(name));
285 }
286 //----------------------------------------------------------------------------
287 template <typename T>
288 auto linear_vertex_property_sampler(std::string const& name) const {
289 return vertex_property_sampler<interpolation::linear, T>(name);
290 }
291 //----------------------------------------------------------------------------
292 template <typename T>
293 auto cubic_vertex_property_sampler(std::string const& name) const {
294 return vertex_property_sampler<interpolation::cubic, T>(name);
295 }
296 //============================================================================
297 auto arc_length() const {
298 auto len = Real{};
299 for (std::size_t i = 0; i < vertices().size() - 1; ++i) {
300 len += euclidean_distance(vertex_at(i), vertex_at(i + 1));
301 }
302 return len;
303 }
304 //----------------------------------------------------------------------------
305 auto is_closed() const { return m_is_closed; }
306 auto set_closed(bool const is_closed = true) { m_is_closed = is_closed; }
307 //----------------------------------------------------------------------------
308 template <typename T>
309 auto vertex_property(std::string const& name) -> auto& {
310 if (auto it = m_vertex_properties.find(name);
311 it == end(m_vertex_properties)) {
312 return insert_vertex_property<T>(name);
313 } else {
314 if (typeid(T) != it->second->type()) {
315 throw std::runtime_error{
316 "type of property \"" + name + "\"(" +
317 boost::core::demangle(it->second->type().name()) +
318 ") does not match specified type " + type_name<T>() + "."};
319 }
320 return *dynamic_cast<typed_vertex_property_type<T>*>(
321 m_vertex_properties.at(name).get());
322 }
323 }
324 //----------------------------------------------------------------------------
325 template <typename T>
326 auto vertex_property(std::string const& name) const -> const auto& {
327 if (auto it = m_vertex_properties.find(name);
328 it == end(m_vertex_properties)) {
329 throw std::runtime_error{"property \"" + name + "\" not found"};
330 } else {
331 if (typeid(T) != it->second->type()) {
332 throw std::runtime_error{
333 "type of property \"" + name + "\"(" +
334 boost::core::demangle(it->second->type().name()) +
335 ") does not match specified type " + type_name<T>() + "."};
336 }
337 return *dynamic_cast<typed_vertex_property_type<T>*>(
338 m_vertex_properties.at(name).get());
339 }
340 }
341 //----------------------------------------------------------------------------
342 auto scalar_vertex_property(std::string const& name) const -> auto const& {
343 return vertex_property<tatooine::real_number>(name);
344 }
345 //----------------------------------------------------------------------------
346 auto scalar_vertex_property(std::string const& name) -> auto& {
347 return vertex_property<tatooine::real_number>(name);
348 }
349 //----------------------------------------------------------------------------
350 auto vec2_vertex_property(std::string const& name) const -> auto const& {
351 return vertex_property<vec2>(name);
352 }
353 //----------------------------------------------------------------------------
354 auto vec2_vertex_property(std::string const& name) -> auto& {
355 return vertex_property<vec2>(name);
356 }
357 //----------------------------------------------------------------------------
358 auto vec3_vertex_property(std::string const& name) const -> auto const& {
359 return vertex_property<vec3>(name);
360 }
361 //----------------------------------------------------------------------------
362 auto vec3_vertex_property(std::string const& name) -> auto& {
363 return vertex_property<vec3>(name);
364 }
365 //----------------------------------------------------------------------------
366 auto vec4_vertex_property(std::string const& name) const -> auto const& {
367 return vertex_property<vec4>(name);
368 }
369 //----------------------------------------------------------------------------
370 auto vec4_vertex_property(std::string const& name) -> auto& {
371 return vertex_property<vec4>(name);
372 }
373 //----------------------------------------------------------------------------
374 auto mat2_vertex_property(std::string const& name) const -> auto const& {
375 return vertex_property<mat2>(name);
376 }
377 //----------------------------------------------------------------------------
378 auto mat2_vertex_property(std::string const& name) -> auto& {
379 return vertex_property<mat2>(name);
380 }
381 //----------------------------------------------------------------------------
382 auto mat3_vertex_property(std::string const& name) const -> auto const& {
383 return vertex_property<mat3>(name);
384 }
385 //----------------------------------------------------------------------------
386 auto mat3_vertex_property(std::string const& name) -> auto& {
387 return vertex_property<mat3>(name);
388 }
389 //----------------------------------------------------------------------------
390 auto mat4_vertex_property(std::string const& name) const -> auto const& {
391 return vertex_property<mat4>(name);
392 }
393 //----------------------------------------------------------------------------
394 auto mat4_vertex_property(std::string const& name) -> auto& {
395 return vertex_property<mat4>(name);
396 }
397 //----------------------------------------------------------------------------
398 template <typename T>
399 auto insert_vertex_property(std::string const& name, T const& value = T{})
400 -> auto& {
401 auto [it, suc] = m_vertex_properties.insert(std::pair{
402 name, std::make_unique<typed_vertex_property_type<T>>(value)});
403 auto prop = dynamic_cast<typed_vertex_property_type<T>*>(it->second.get());
404 prop->resize(m_vertices.size());
405 return *prop;
406 }
407 //----------------------------------------------------------------------------
409 std::string const& name,
410 tatooine::real_number const value = tatooine::real_number{}) -> auto& {
411 return insert_vertex_property<tatooine::real_number>(name, value);
412 }
413 //----------------------------------------------------------------------------
415 std::string const& name, tatooine::vec2 const value = tatooine::vec2{})
416 -> auto& {
417 return insert_vertex_property<vec2>(name, value);
418 }
419 //----------------------------------------------------------------------------
421 std::string const& name, tatooine::vec3 const value = tatooine::vec3{})
422 -> auto& {
423 return insert_vertex_property<vec3>(name, value);
424 }
425 //----------------------------------------------------------------------------
427 std::string const& name, tatooine::vec4 const value = tatooine::vec4{})
428 -> auto& {
429 return insert_vertex_property<vec4>(name, value);
430 }
431 //----------------------------------------------------------------------------
433 std::string const& name, tatooine::mat2 const value = tatooine::mat2{})
434 -> auto& {
435 return insert_vertex_property<mat2>(name, value);
436 }
437 //----------------------------------------------------------------------------
439 std::string const& name, tatooine::mat3 const value = tatooine::mat3{})
440 -> auto& {
441 return insert_vertex_property<mat3>(name, value);
442 }
443 //----------------------------------------------------------------------------
445 std::string const& name, tatooine::mat4 const value = tatooine::mat4{})
446 -> auto& {
447 return insert_vertex_property<mat4>(name, value);
448 }
449 //----------------------------------------------------------------------------
450 auto vertex_properties() const -> auto const& { return m_vertex_properties; }
451 //----------------------------------------------------------------------------
452 auto has_vertex_property(const std::string& name) const -> bool {
453 return m_vertex_properties.find(name) != end(m_vertex_properties);
454 }
455 //----------------------------------------------------------------------------
456 auto tangents() -> auto& {
457 if (!m_tangent_property) {
459 &vertex_property<vec<Real, NumDimensions>>("tangents");
460 }
461 return *m_tangent_property;
462 }
463 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
464 auto tangents() const -> auto const& {
465 if (!m_tangent_property) {
466 throw std::runtime_error{"no tangent property present"};
467 }
468 return *m_tangent_property;
469 }
470 //----------------------------------------------------------------------------
471 auto compute_tangents(std::size_t const stencil_size = 3) {
472 auto& t = parameterization();
473 auto& tang = tangents();
474 auto const half = stencil_size / 2;
475
476 for (auto const v : vertices()) {
477 auto lv = half > v.index() ? vertex_handle{0} : v - half;
478 auto const rv = lv.index() + stencil_size - 1 >= vertices().size()
479 ? vertex_handle{vertices().size() - 1}
480 : lv + stencil_size - 1;
481 auto const rpotential = stencil_size - (rv.index() - lv.index() + 1);
482 lv = rpotential > lv.index() ? vertex_handle{0} : lv - rpotential;
483
484 std::vector<real_type> ts(stencil_size);
485 std::size_t i = 0;
486 for (auto vi = lv; vi <= rv; ++vi, ++i) {
487 ts[i] = t[vi] - t[v];
488 }
489 auto coeffs = finite_differences_coefficients(1, ts);
491 i = 0;
492 for (auto vi = lv; vi <= rv; ++vi, ++i) {
493 tang[v] += vertex_at(vi) * coeffs[i];
494 }
495 }
496 }
497 //----------------------------------------------------------------------------
498 auto has_parameterization() const {
499 return m_parameterization_property != nullptr;
500 }
501 //----------------------------------------------------------------------------
502 auto parameterization() -> auto& {
503 if (!has_parameterization()) {
504 m_parameterization_property = &vertex_property<Real>("parameterization");
505 }
507 }
508 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
509 auto parameterization() const -> auto const& {
510 if (!has_parameterization()) {
511 throw std::runtime_error{
512 "Cannot create parameterization property on const line."};
513 }
515 }
516 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
517 auto compute_uniform_parameterization(Real const t0 = 0) -> void {
518 auto& t = parameterization();
519 t.front() = t0;
520 for (std::size_t i = 1; i < vertices().size(); ++i) {
521 t[i] = t[i - 1] + 1;
522 }
523 }
524 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
525 auto compute_normalized_uniform_parameterization(Real const t0 = 0) -> void {
528 }
529 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
530 auto compute_chordal_parameterization(Real const t0 = 0) -> void {
531 auto& t = parameterization();
532 t.front() = t0;
533 for (std::size_t i = 1; i < vertices().size(); ++i) {
534 t[i] = t[i - 1] + euclidean_distance(vertex_at(i), vertex_at(i - 1));
535 }
536 }
537 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
538 auto compute_normalized_chordal_parameterization(Real const t0 = 0) -> void {
541 }
542 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
543 auto compute_centripetal_parameterization(Real const t0 = 0) -> void {
544 auto& t = parameterization();
545 t.front() = t0;
546 for (std::size_t i = 1; i < vertices().size(); ++i) {
547 t[i] = t[i - 1] +
548 std::sqrt(euclidean_distance(vertex_at(i), vertex_at(i - 1)));
549 }
550 }
551 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
553 -> void {
556 }
557 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
558 auto compute_parameterization(Real const t0 = 0) -> void {
560 }
561 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
562 auto compute_normalized_parameterization(Real const t0 = 0) -> void {
565 }
566 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
568 auto& t = parameterization();
569 auto const min = t[vertices().front()];
570 auto const max = t[vertices().back()];
571 auto const norm = 1 / (max - min);
572 for (auto const v : vertices()) {
573 t[v] = (t[v] - min) * norm;
574 }
575 }
576 //----------------------------------------------------------------------------
577 auto write(filesystem::path const& path) -> void {
578 auto const ext = path.extension();
579 if constexpr (NumDimensions == 2 || NumDimensions == 3) {
580 if (ext == ".vtk") {
581 write_vtk(path);
582 return;
583 } else if (ext == ".vtp") {
584 write_vtp(path);
585 return;
586 }
587 }
588 throw std::runtime_error(
589 "Could not write line. Unknown file extension: \"" + ext.string() +
590 "\".");
591 }
592 //----------------------------------------------------------------------------
593 auto write_vtk(filesystem::path const& path,
594 std::string const& title = "tatooine line") const -> void {
595 detail::line::vtk_writer{*this}.write(path, title);
596 }
597 //----------------------------------------------------------------------------
598 template <unsigned_integral HeaderType = std::uint64_t,
599 integral ConnectivityInt = std::int64_t,
600 integral OffsetInt = std::int64_t>
601 auto write_vtp(filesystem::path const& path) const -> void {
603 *this}
604 .write(path);
605 }
606 //----------------------------------------------------------------------------
607 static auto read(filesystem::path const& path) {
608 auto const file_ext = path.extension();
609 if constexpr (NumDimensions == 2 || NumDimensions == 3) {
610 if (file_ext == ".vtp") {
611 return read_vtp(path);
612 }
613 }
614 throw std::runtime_error{"Could not read " + path.string()};
615 }
616 //----------------------------------------------------------------------------
617 auto read_single(filesystem::path const& path) {
618 auto const file_ext = path.extension();
619 if constexpr (NumDimensions == 2 || NumDimensions == 3) {
620 if (file_ext == ".vtp") {
622 }
623 }
624 }
625 //----------------------------------------------------------------------------
626 static auto read_vtk(std::string const& filepath)
627 requires(num_dimensions() == 3)
628 {
629 struct reader : vtk::legacy_file_listener {
630 std::vector<std::array<Real, 3>> points;
631 std::vector<int> lines;
632
633 void on_points(std::vector<std::array<Real, 3>> const& points_) override {
634 points = points_;
635 }
636 void on_lines(std::vector<int> const& lines_) override { lines = lines_; }
637 } listener;
638
639 vtk::legacy_file file{filepath};
640 file.add_listener(listener);
641 file.read();
642
643 std::vector<line<Real, 3>> lines;
644 auto const& vs = listener.points;
645 std::size_t i = 0;
646 while (i < listener.lines.size()) {
647 auto const size = static_cast<std::size_t>(listener.lines[i++]);
648 auto& l = lines.emplace_back();
649 for (; i < size; ++i) {
650 l.push_back({vs[i][0], vs[i][1], vs[i][2]});
651 }
652 }
653 return lines;
654 }
655 //----------------------------------------------------------------------------
656 auto read_vtp_single_piece(std::string const& filepath)
657 requires(num_dimensions() == 2) || (num_dimensions() == 3)
658 {
659 auto reader = vtk::xml::reader{filepath};
660 if (reader.type() != vtk::xml::vtk_type::poly_data) {
661 throw std::runtime_error{"[line::read_vtp] can only read from poly_data"};
662 }
663 read(reader.poly_data()->pieces.back());
664 }
665 //----------------------------------------------------------------------------
666 static auto read_vtp(std::string const& filepath)
667 requires(num_dimensions() == 3) || (num_dimensions() == 3)
668 {
669 auto reader = vtk::xml::reader{filepath};
670 if (reader.type() != vtk::xml::vtk_type::poly_data) {
671 throw std::runtime_error{"[line::read_vtp] can only read from poly_data"};
672 }
673 auto lines = std::vector<this_type>{};
674 lines.reserve(reader.poly_data()->pieces.size());
675
676 for (auto& piece : reader.poly_data()->pieces) {
677 lines.emplace_back().read(piece);
678 }
679 return lines;
680 }
681 //----------------------------------------------------------------------------
684 template <std::size_t N>
685 auto read_vtp_prop(std::string const& name,
686 vtk::xml::data_array const& data_array)
687 requires(num_dimensions() == 2) || (num_dimensions() == 3)
688 {
689 if (data_array.num_components() != N) {
690 return;
691 }
692 auto data_type_getter = [&]<typename value_t>(value_t /*val*/) {
693 using prop_t = std::conditional_t<N == 1, value_t, vec<value_t, N>>;
694 auto& prop = insert_vertex_property<prop_t>(name);
695 auto prop_data_setter = [&prop, i = std::size_t{},
696 this](std::vector<value_t> const& data) mutable {
697 for (auto const v : vertices()) {
698 auto& p = prop[v];
699 if constexpr (N == 1) {
700 p = data[i++];
701 } else {
702 for (std::size_t j = 0; j < N; ++j) {
703 p(j) = data[i++];
704 }
705 }
706 };
707 };
708 data_array.visit_data(prop_data_setter);
709 };
710 vtk::xml::visit(data_array.type(), data_type_getter);
711 }
712 //----------------------------------------------------------------------------
714 auto read_vtp_prop(std::string const& name,
715 vtk::xml::data_array const& data_array)
716 requires(num_dimensions() == 2) || (num_dimensions() == 3)
717 {
718 [&]<std::size_t... Is>(std::index_sequence<Is...>) {
719 (std::invoke(&this_type::read_vtp_prop<Is + 1>, this, name, data_array),
720 ...);
721 }
722 (std::make_index_sequence<10>{});
723 }
724 //----------------------------------------------------------------------------
726 requires(num_dimensions() == 2) || (num_dimensions() == 3)
727 {
728 points.visit_data([&](auto&& point_data) {
729 // always 3 components in vtk data array
730 for (std::size_t i = 0; i < point_data.size(); i += 3) {
731 if constexpr (num_dimensions() == 2) {
732 // just omit third component when reading to a 3d line
733 push_back(point_data[i], point_data[i + 1]);
734 } else if constexpr (num_dimensions() == 3) {
735 push_back(point_data[i], point_data[i + 1], point_data[i + 2]);
736 }
737 }
738 });
739 }
740 //----------------------------------------------------------------------------
742 auto read(vtk::xml::piece const& p)
743 requires(num_dimensions() == 2) || (num_dimensions() == 3)
744 {
745 read_vtp_positions(p.points);
746 for (auto const& [name, data_array] : p.point_data) {
747 read_vtp_prop(name, data_array);
748 }
749 // p.lines.at("connectivity").visit_data([](auto&& connectivity) {
750 // auto i = std::size_t{};
751 // auto left = connectivity[i++];
752 // auto right = connectivity[i++];
753 // push_back(positions[left * 3], positions[left * 3 + 1],
754 // positions[left * 3 + 2]);
755 // push_back(positions[right * 3], positions[right * 3 + 1],
756 // positions[right * 3 + 2]);
757 // auto num_processed = std::size_t(1);
758 //
759 // while (num_processed *2 != connectivity.size()) {
760 // for (std::size_t i = 1; i < connectivity.size(); ++i) {
761 //
762 // }
763 // }
764 // });
765 }
766 //----------------------------------------------------------------------------
767 template <typename Pred>
768 std::vector<line<Real, NumDimensions>> filter(Pred&& pred) const;
769 //----------------------------------------------------------------------------
770 template <template <typename> typename InterpolationKernel, typename T,
771 floating_point ResampleSpaceReal>
773 this_type& resampled_line, std::string const& name,
775 linspace<ResampleSpaceReal> const& resample_space) {
776 auto& resampled_prop = resampled_line.vertex_property<T>(name);
777 auto const prop_sampler = sampler<InterpolationKernel>(prop);
778 auto v = resampled_line.vertices().front();
779 for (auto const t : resample_space) {
780 resampled_prop[v++] = prop_sampler(t);
781 }
782 }
783 //----------------------------------------------------------------------------
784 template <template <typename> typename InterpolationKernel, typename... Ts,
785 floating_point ResampleSpaceReal>
787 this_type& resampled_line, std::string const& name,
788 vertex_property_type const& prop,
789 linspace<ResampleSpaceReal> const& resample_space) {
790 invoke([&] {
791 if (prop.type() == typeid(Ts)) {
792 resample_vertex_property<InterpolationKernel>(
793 resampled_line, name,
794 *dynamic_cast<typed_vertex_property_type<Ts> const*>(&prop),
795 resample_space);
796 }
797 }...);
798 }
799 //----------------------------------------------------------------------------
800 template <template <typename> typename InterpolationKernel,
801 floating_point ResampleSpaceReal>
802 auto resample(linspace<ResampleSpaceReal> const& resample_space) {
803 this_type resampled_line;
804 auto& p = resampled_line.parameterization();
805 auto const positions = sampler<InterpolationKernel>();
806
807 for (auto const t : resample_space) {
808 auto const v = resampled_line.push_back(positions(t));
809 p[v] = t;
810 }
811 for (auto const& [name, prop] : m_vertex_properties) {
813 InterpolationKernel, long double, double, float, vec<long double, 2>,
816 resampled_line, name, *prop, resample_space);
817 }
818 return resampled_line;
819 }
820};
821//==============================================================================
822// deduction guides
823//==============================================================================
824template <typename... Tensors, typename... Reals, std::size_t NumDimensions>
826 -> line<common_type<Reals...>, NumDimensions>;
827//==============================================================================
828// type traits
829//==============================================================================
831template <typename T>
832struct is_line_impl : std::false_type {};
833//------------------------------------------------------------------------------
835template <typename Real, std::size_t N>
836struct is_line_impl<line<Real, N>> : std::true_type {};
837//------------------------------------------------------------------------------
838template <typename T>
839static auto constexpr is_line = is_line_impl<T>::value;
840//==============================================================================
841// concepts
842//==============================================================================
843template <typename T>
844concept range_of_lines = range<T> && is_line<std::ranges::range_value_t<T>>;
845//==============================================================================
846// typedefs
847//==============================================================================
848template <typename T>
850template <typename T>
852template <typename T>
854template <typename T>
856template <std::size_t NumDimensions>
862//==============================================================================
863// implementations
864//==============================================================================
865template <floating_point Real, std::size_t NumDimensions>
866template <typename Pred>
868 -> std::vector<line<Real, NumDimensions>> {
869 auto filtered_lines = std::vector<line<Real, NumDimensions>>{};
870 auto need_new_strip = true;
871
872 auto i = std::size_t{};
873 auto closed = is_closed();
874 for (auto const x : vertices()) {
875 if (pred(x, i)) {
876 if (need_new_strip) {
877 filtered_lines.emplace_back();
878 need_new_strip = false;
879 }
880 filtered_lines.back().push_back(x);
881 } else {
882 closed = false;
883 need_new_strip = true;
884 if (!filtered_lines.empty() &&
885 filtered_lines.back().vertices().size() <= 1)
886 filtered_lines.pop_back();
887 }
888 ++i;
889 }
890
891 if (!filtered_lines.empty() && filtered_lines.back().vertices().size() <= 1) {
892 filtered_lines.pop_back();
893 }
894 if (filtered_lines.size() == 1) {
895 filtered_lines.front().set_closed(closed);
896 }
897 return filtered_lines;
898}
899//==============================================================================
900template <floating_point Real = real_number>
901auto read_lines(filesystem::path const& filepath) {
902 auto ls = std::vector<Line3<Real>>{};
903 auto reader = vtk::xml::reader{filepath};
904 if (reader.type() != vtk::xml::vtk_type::poly_data) {
905 throw std::runtime_error{"[read_lines] can only read from poly_data"};
906 }
907 for (auto& piece : reader.poly_data()->pieces) {
908 ls.push_back(Line3<Real>::read(piece));
909 }
910 return ls;
911}
912//==============================================================================
913} // namespace tatooine
914//==============================================================================
917//==============================================================================
918#endif
Definition: vtk_legacy.h:184
auto add_listener(legacy_file_listener &listener) -> void
Definition: concepts.h:33
Definition: concepts.h:30
Definition: concepts.h:21
Definition: line.h:844
Definition: concepts.h:84
Definition: concepts.h:27
auto finite_differences_coefficients(std::size_t const derivative_order, floating_point auto const ... xs)
See What is this? for an explanation.
Definition: finite_differences_coefficients.h:13
auto visit(data_type dt, auto &&f)
Definition: data_type.h:25
Definition: algorithm.h:6
typename common_type_impl< Ts... >::type common_type
Definition: common_type.h:23
auto end(Range &&range)
Definition: iterator_facade.h:322
auto vertices(pointset< Real, NumDimensions > const &ps)
Definition: vertex_container.h:278
auto read_lines(filesystem::path const &filepath)
Definition: line.h:901
constexpr auto invoke(invocable auto &&...funcs)
Definition: functional.h:8
constexpr auto norm(base_tensor< Tensor, T, N > const &t, unsigned p=2) -> T
Definition: norm.h:23
constexpr auto max(A &&a, B &&b)
Definition: math.h:20
auto size(vec< ValueType, N > const &v)
Definition: vec.h:148
static auto constexpr is_line
Definition: line.h:839
constexpr auto min(A &&a, B &&b)
Definition: math.h:15
static constexpr forward_tag forward
Definition: tags.h:9
constexpr auto euclidean_distance(base_tensor< Tensor0, T0, N > const &lhs, base_tensor< Tensor1, T1, N > const &rhs)
Definition: distance.h:19
Definition: base_tensor.h:23
Definition: property.h:244
virtual auto type() const -> const std::type_info &=0
for identifying type.
Definition: vertex_container.h:17
Definition: vertex_property_sampler.h:11
Definition: vtk_writer.h:18
auto write(filesystem::path const &path, std::string const &title) const
Definition: vtk_writer.h:27
Definition: vtp_writer.h:18
auto write(filesystem::path const &path) const
Definition: vtp_writer.h:27
Definition: handle.h:14
auto index() const
Definition: handle.h:64
constexpr handle()
Definition: handle.h:24
All types that are no lines.
Definition: line.h:832
Definition: line.h:46
Definition: line.h:35
auto clear()
Definition: line.h:142
auto front_vertex() -> auto &
Definition: line.h:171
auto operator[](vertex_handle const i) const -> auto const &
Definition: line.h:163
auto pop_back()
Definition: line.h:211
auto write(filesystem::path const &path) -> void
Definition: line.h:577
auto mat2_vertex_property(std::string const &name) const -> auto const &
Definition: line.h:374
pos_container_type m_vertices
Definition: line.h:79
auto sampler() const
Definition: line.h:257
auto read_single(filesystem::path const &path)
Definition: line.h:617
auto vertices() const
Definition: line.h:250
auto set_closed(bool const is_closed=true)
Definition: line.h:306
auto copy_without_properties()
Definition: line.h:138
auto push_back(arithmetic auto const ... components)
Definition: line.h:176
auto mat3_vertex_property(std::string const &name) -> auto &
Definition: line.h:386
auto compute_parameterization(Real const t0=0) -> void
Definition: line.h:558
auto write_vtk(filesystem::path const &path, std::string const &title="tatooine line") const -> void
Definition: line.h:593
auto compute_normalized_parameterization(Real const t0=0) -> void
Definition: line.h:562
auto vertex_at(std::size_t const i) const -> auto const &
Definition: line.h:146
auto insert_scalar_vertex_property(std::string const &name, tatooine::real_number const value=tatooine::real_number{}) -> auto &
Definition: line.h:408
auto read(vtk::xml::piece const &p)
TODO actually read connectivy data array from the lines tag.
Definition: line.h:742
auto has_vertex_property(const std::string &name) const -> bool
Definition: line.h:452
static auto read_vtk(std::string const &filepath)
Definition: line.h:626
auto compute_centripetal_parameterization(Real const t0=0) -> void
Definition: line.h:543
auto num_vertices() const
Definition: line.h:251
auto read_vtp_positions(vtk::xml::data_array const &points)
Definition: line.h:725
Real real_type
Definition: line.h:38
auto cubic_sampler() const
Definition: line.h:264
auto back_vertex() -> auto &
Definition: line.h:174
line(line const &other)
Definition: line.h:91
auto tangents() -> auto &
Definition: line.h:456
line(pos_container_type &&data, bool is_closed=false)
Definition: line.h:129
auto vertex_property(std::string const &name) const -> const auto &
Definition: line.h:326
auto linear_vertex_property_sampler(std::string const &name) const
Definition: line.h:288
vec_type pos_type
Definition: line.h:40
auto mat4_vertex_property(std::string const &name) const -> auto const &
Definition: line.h:390
auto mat2_vertex_property(std::string const &name) -> auto &
Definition: line.h:378
auto tangents() const -> auto const &
Definition: line.h:464
std::vector< line< Real, NumDimensions > > filter(Pred &&pred) const
auto push_back(pos_type const &p)
Definition: line.h:186
auto has_parameterization() const
Definition: line.h:498
auto mat4_vertex_property(std::string const &name) -> auto &
Definition: line.h:394
auto at(vertex_handle const i) const -> auto const &
Definition: line.h:158
auto operator=(line const &other) -> line &
Definition: line.h:107
static auto read_vtp(std::string const &filepath)
Definition: line.h:666
auto pop_front()
Definition: line.h:248
auto compute_uniform_parameterization(Real const t0=0) -> void
Definition: line.h:517
auto num_line_segments() const
Definition: line.h:252
auto read_vtp_single_piece(std::string const &filepath)
Definition: line.h:656
auto compute_normalized_chordal_parameterization(Real const t0=0) -> void
Definition: line.h:538
auto vec3_vertex_property(std::string const &name) -> auto &
Definition: line.h:362
line()=default
auto vertex_at(std::size_t const i) -> auto &
Definition: line.h:149
auto push_front(arithmetic auto const ... components)
Definition: line.h:213
auto push_front(vec< OtherReal, NumDimensions > const &p)
Definition: line.h:240
auto compute_chordal_parameterization(Real const t0=0) -> void
Definition: line.h:530
parameterization_property_type * m_parameterization_property
Definition: line.h:84
static constexpr auto num_dimensions() -> std::size_t
Definition: line.h:72
auto resample_vertex_property(this_type &resampled_line, std::string const &name, vertex_property_type const &prop, linspace< ResampleSpaceReal > const &resample_space)
Definition: line.h:786
vertex_property_container_type m_vertex_properties
Definition: line.h:83
auto read_vtp_prop(std::string const &name, vtk::xml::data_array const &data_array)
Calls read_vtp_prop<N> with N = 1..10.
Definition: line.h:714
auto scalar_vertex_property(std::string const &name) -> auto &
Definition: line.h:346
line(filesystem::path const &path)
Definition: line.h:136
auto resample(linspace< ResampleSpaceReal > const &resample_space)
Definition: line.h:802
line(line &&other) noexcept=default
auto front_vertex() const -> auto const &
Definition: line.h:170
auto vec3_vertex_property(std::string const &name) const -> auto const &
Definition: line.h:358
auto vec2_vertex_property(std::string const &name) const -> auto const &
Definition: line.h:350
auto resample_vertex_property(this_type &resampled_line, std::string const &name, typed_vertex_property_type< T > const &prop, linspace< ResampleSpaceReal > const &resample_space)
Definition: line.h:772
static auto read(filesystem::path const &path)
Definition: line.h:607
auto is_closed() const
Definition: line.h:305
auto mat3_vertex_property(std::string const &name) const -> auto const &
Definition: line.h:382
auto at(vertex_handle const i) -> auto &
Definition: line.h:161
auto push_front(pos_type &&p)
Definition: line.h:231
auto vec4_vertex_property(std::string const &name) -> auto &
Definition: line.h:370
auto empty() const
Definition: line.h:140
auto sampler(typed_vertex_property_type< T > const &prop) const
Definition: line.h:267
auto linear_sampler(typed_vertex_property_type< T > const &prop) const
Definition: line.h:273
auto insert_vertex_property(std::string const &name, T const &value=T{}) -> auto &
Definition: line.h:399
auto push_back(pos_type &&p)
Definition: line.h:194
auto push_back(vec< OtherReal, NumDimensions > const &p)
Definition: line.h:203
std::map< std::string, std::unique_ptr< vertex_property_type > > vertex_property_container_type
Definition: line.h:59
auto linear_sampler() const
Definition: line.h:262
auto push_front(pos_type const &p)
Definition: line.h:223
auto vec2_vertex_property(std::string const &name) -> auto &
Definition: line.h:354
auto operator=(line &&other) noexcept -> line &=default
auto vertex_property_sampler(std::string const &name) const
Definition: line.h:283
auto cubic_sampler(typed_vertex_property_type< T > const &prop) const
Definition: line.h:278
auto vec4_vertex_property(std::string const &name) const -> auto const &
Definition: line.h:366
auto insert_vec2_vertex_property(std::string const &name, tatooine::vec2 const value=tatooine::vec2{}) -> auto &
Definition: line.h:414
line(std::convertible_to< pos_type > auto &&... vs)
Definition: line.h:132
auto read_vtp_prop(std::string const &name, vtk::xml::data_array const &data_array)
Definition: line.h:685
auto insert_mat2_vertex_property(std::string const &name, tatooine::mat2 const value=tatooine::mat2{}) -> auto &
Definition: line.h:432
tangent_property_type * m_tangent_property
Definition: line.h:85
auto vertex_properties() const -> auto const &
Definition: line.h:450
auto parameterization() -> auto &
Definition: line.h:502
std::deque< pos_type > pos_container_type
Definition: line.h:41
auto insert_mat4_vertex_property(std::string const &name, tatooine::mat4 const value=tatooine::mat4{}) -> auto &
Definition: line.h:444
auto vertex_at(vertex_handle const i) const -> auto const &
Definition: line.h:151
auto arc_length() const
Definition: line.h:297
auto compute_tangents(std::size_t const stencil_size=3)
Definition: line.h:471
auto operator[](vertex_handle const i) -> auto &
Definition: line.h:166
auto parameterization() const -> auto const &
Definition: line.h:509
auto insert_mat3_vertex_property(std::string const &name, tatooine::mat3 const value=tatooine::mat3{}) -> auto &
Definition: line.h:438
vec< Real, NumDimensions > vec_type
Definition: line.h:39
bool m_is_closed
Definition: line.h:80
auto compute_normalized_centripetal_parameterization(Real const t0=0) -> void
Definition: line.h:552
auto vertex_property(std::string const &name) -> auto &
Definition: line.h:309
auto normalize_parameterization() -> void
Definition: line.h:567
auto back_vertex() const -> auto const &
Definition: line.h:173
auto scalar_vertex_property(std::string const &name) const -> auto const &
Definition: line.h:342
auto cubic_vertex_property_sampler(std::string const &name) const
Definition: line.h:293
auto insert_vec4_vertex_property(std::string const &name, tatooine::vec4 const value=tatooine::vec4{}) -> auto &
Definition: line.h:426
line(pos_container_type const &data, bool is_closed=false)
Definition: line.h:126
auto insert_vec3_vertex_property(std::string const &name, tatooine::vec3 const value=tatooine::vec3{}) -> auto &
Definition: line.h:420
auto vertex_at(vertex_handle const i) -> auto &
Definition: line.h:154
auto compute_normalized_uniform_parameterization(Real const t0=0) -> void
Definition: line.h:525
auto write_vtp(filesystem::path const &path) const -> void
Definition: line.h:601
Definition: linspace.h:26
Definition: mat.h:14
Definition: property.h:293
static auto constexpr zeros()
Definition: vec.h:26
Definition: vtk_legacy.h:92
Definition: data_array.h:19
Definition: piece.h:14
Definition: reader.h:25