diff --git a/lib/Slic3r/ExPolygon.pm b/lib/Slic3r/ExPolygon.pm index 27aa1a59b..6adb650c2 100644 --- a/lib/Slic3r/ExPolygon.pm +++ b/lib/Slic3r/ExPolygon.pm @@ -7,18 +7,6 @@ use warnings; use List::Util qw(first); use Slic3r::Geometry::Clipper qw(union_ex diff_pl); -sub wkt { - my $self = shift; - return sprintf "POLYGON(%s)", - join ',', map "($_)", map { join ',', map "$_->[0] $_->[1]", @$_ } @$self; -} - -sub dump_perl { - my $self = shift; - return sprintf "[%s]", - join ',', map "[$_]", map { join ',', map "[$_->[0],$_->[1]]", @$_ } @$self; -} - sub offset { my $self = shift; return Slic3r::Geometry::Clipper::offset(\@$self, @_); diff --git a/lib/Slic3r/GUI/2DBed.pm b/lib/Slic3r/GUI/2DBed.pm index ebbc70b6b..0891a4836 100644 --- a/lib/Slic3r/GUI/2DBed.pm +++ b/lib/Slic3r/GUI/2DBed.pm @@ -1,4 +1,5 @@ # Bed shape dialog +# still used by the Slic3r::GUI::Controller::ManualControlDialog Perl module. package Slic3r::GUI::2DBed; use strict; diff --git a/lib/Slic3r/Point.pm b/lib/Slic3r/Point.pm index 535a97194..1134138ea 100644 --- a/lib/Slic3r/Point.pm +++ b/lib/Slic3r/Point.pm @@ -7,11 +7,6 @@ sub new_scale { return $class->new(map Slic3r::Geometry::scale($_), @_); } -sub dump_perl { - my $self = shift; - return sprintf "[%s,%s]", @$self; -} - package Slic3r::Pointf; use strict; use warnings; diff --git a/lib/Slic3r/Polyline.pm b/lib/Slic3r/Polyline.pm index 9cc142409..a42b5d1c4 100644 --- a/lib/Slic3r/Polyline.pm +++ b/lib/Slic3r/Polyline.pm @@ -10,9 +10,4 @@ sub new_scale { return $class->new(map [ Slic3r::Geometry::scale($_->[X]), Slic3r::Geometry::scale($_->[Y]) ], @points); } -sub dump_perl { - my $self = shift; - return sprintf "[%s]", join ',', map "[$_->[0],$_->[1]]", @$self; -} - 1; diff --git a/xs/lib/Slic3r/XS.pm b/xs/lib/Slic3r/XS.pm index a4847fb45..391b06dac 100644 --- a/xs/lib/Slic3r/XS.pm +++ b/xs/lib/Slic3r/XS.pm @@ -33,16 +33,6 @@ use overload '@{}' => sub { $_[0]->arrayref }, 'fallback' => 1; -package Slic3r::Point3; -use overload - '@{}' => sub { [ $_[0]->x, $_[0]->y, $_[0]->z ] }, #, - 'fallback' => 1; - -sub pp { - my ($self) = @_; - return [ @$self ]; -} - package Slic3r::Pointf; use overload '@{}' => sub { $_[0]->arrayref }, diff --git a/xs/src/admesh/connect.cpp b/xs/src/admesh/connect.cpp index e9129d007..da5b66720 100644 --- a/xs/src/admesh/connect.cpp +++ b/xs/src/admesh/connect.cpp @@ -25,11 +25,11 @@ #include #include +#include + #include "stl.h" -static void stl_match_neighbors_exact(stl_file *stl, - stl_hash_edge *edge_a, stl_hash_edge *edge_b); static void stl_match_neighbors_nearby(stl_file *stl, stl_hash_edge *edge_a, stl_hash_edge *edge_b); static void stl_record_neighbors(stl_file *stl, @@ -43,7 +43,6 @@ static int stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge, static void insert_hash_edge(stl_file *stl, stl_hash_edge edge, void (*match_neighbors)(stl_file *stl, stl_hash_edge *edge_a, stl_hash_edge *edge_b)); -static int stl_get_hash_for_edge(int M, stl_hash_edge *edge); static int stl_compare_function(stl_hash_edge *edge_a, stl_hash_edge *edge_b); static void stl_free_edges(stl_file *stl); static void stl_remove_facet(stl_file *stl, int facet_number); @@ -82,37 +81,20 @@ stl_check_facets_exact(stl_file *stl) { for(i = 0; i < stl->stats.number_of_facets; i++) { facet = stl->facet_start[i]; - // Positive and negative zeros are possible in the floats, which are considered equal by the FP unit. - // When using a memcmp on raw floats, those numbers report to be different. - // Unify all +0 and -0 to +0 to make the floats equal under memcmp. - { - uint32_t *f = (uint32_t*)&facet; - for (int j = 0; j < 12; ++ j, ++ f) // 3x vertex + normal: 4x3 = 12 floats - if (*f == 0x80000000) - // Negative zero, switch to positive zero. - *f = 0; - } - - /* If any two of the three vertices are found to be exactally the same, call them degenerate and remove the facet. */ - if( !memcmp(&facet.vertex[0], &facet.vertex[1], - sizeof(stl_vertex)) - || !memcmp(&facet.vertex[1], &facet.vertex[2], - sizeof(stl_vertex)) - || !memcmp(&facet.vertex[0], &facet.vertex[2], - sizeof(stl_vertex))) { + // If any two of the three vertices are found to be exactally the same, call them degenerate and remove the facet. + if (facet.vertex[0] == facet.vertex[1] || + facet.vertex[1] == facet.vertex[2] || + facet.vertex[0] == facet.vertex[2]) { stl->stats.degenerate_facets += 1; stl_remove_facet(stl, i); - i--; + -- i; continue; - } for(j = 0; j < 3; j++) { edge.facet_number = i; edge.which_edge = j; - stl_load_edge_exact(stl, &edge, &facet.vertex[j], - &facet.vertex[(j + 1) % 3]); - - insert_hash_edge(stl, edge, stl_match_neighbors_exact); + stl_load_edge_exact(stl, &edge, &facet.vertex[j], &facet.vertex[(j + 1) % 3]); + insert_hash_edge(stl, edge, stl_record_neighbors); } } stl_free_edges(stl); @@ -131,28 +113,33 @@ stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge, if (stl->error) return; { - float diff_x = ABS(a->x - b->x); - float diff_y = ABS(a->y - b->y); - float diff_z = ABS(a->z - b->z); - float max_diff = STL_MAX(diff_x, diff_y); - max_diff = STL_MAX(diff_z, max_diff); - stl->stats.shortest_edge = STL_MIN(max_diff, stl->stats.shortest_edge); + stl_vertex diff = (*a - *b).cwiseAbs(); + float max_diff = std::max(diff(0), std::max(diff(1), diff(2))); + stl->stats.shortest_edge = std::min(max_diff, stl->stats.shortest_edge); } // Ensure identical vertex ordering of equal edges. // This method is numerically robust. - if ((a->x != b->x) ? - (a->x < b->x) : - ((a->y != b->y) ? - (a->y < b->y) : - (a->z < b->z))) { - memcpy(&edge->key[0], a, sizeof(stl_vertex)); - memcpy(&edge->key[3], b, sizeof(stl_vertex)); + if (stl_vertex_lower(*a, *b)) { } else { - memcpy(&edge->key[0], b, sizeof(stl_vertex)); - memcpy(&edge->key[3], a, sizeof(stl_vertex)); + std::swap(a, b); edge->which_edge += 3; /* this edge is loaded backwards */ } + memcpy(&edge->key[0], a->data(), sizeof(stl_vertex)); + memcpy(&edge->key[sizeof(stl_vertex)], b->data(), sizeof(stl_vertex)); + // Switch negative zeros to positive zeros, so memcmp will consider them to be equal. + for (size_t i = 0; i < 6; ++ i) { + unsigned char *p = edge->key + i * 4; +#ifdef BOOST_LITTLE_ENDIAN + if (p[0] == 0 && p[1] == 0 && p[2] == 0 && p[3] == 0x80) + // Negative zero, switch to positive zero. + p[3] = 0; +#else /* BOOST_LITTLE_ENDIAN */ + if (p[0] == 0x80 && p[1] == 0 && p[2] == 0 && p[3] == 0) + // Negative zero, switch to positive zero. + p[0] = 0; +#endif /* BOOST_LITTLE_ENDIAN */ + } } static void @@ -188,21 +175,17 @@ stl_initialize_facet_check_exact(stl_file *stl) { } } -static void -insert_hash_edge(stl_file *stl, stl_hash_edge edge, +static void insert_hash_edge(stl_file *stl, stl_hash_edge edge, void (*match_neighbors)(stl_file *stl, - stl_hash_edge *edge_a, stl_hash_edge *edge_b)) { - stl_hash_edge *link; - stl_hash_edge *new_edge; - stl_hash_edge *temp; - int chain_number; - + stl_hash_edge *edge_a, stl_hash_edge *edge_b)) +{ if (stl->error) return; - chain_number = stl_get_hash_for_edge(stl->M, &edge); - - link = stl->heads[chain_number]; + int chain_number = edge.hash(stl->M); + stl_hash_edge *link = stl->heads[chain_number]; + stl_hash_edge *new_edge; + stl_hash_edge *temp; if(link == stl->tail) { /* This list doesn't have any edges currently in it. Add this one. */ new_edge = (stl_hash_edge*)malloc(sizeof(stl_hash_edge)); @@ -252,30 +235,17 @@ insert_hash_edge(stl_file *stl, stl_hash_edge edge, } } - -static int -stl_get_hash_for_edge(int M, stl_hash_edge *edge) { - return ((edge->key[0] / 23 + edge->key[1] / 19 + edge->key[2] / 17 - + edge->key[3] /13 + edge->key[4] / 11 + edge->key[5] / 7 ) % M); +// Return 1 if the edges are not matched. +static inline int stl_compare_function(stl_hash_edge *edge_a, stl_hash_edge *edge_b) +{ + // Don't match edges of the same facet + return (edge_a->facet_number == edge_b->facet_number) || (*edge_a != *edge_b); } -static int -stl_compare_function(stl_hash_edge *edge_a, stl_hash_edge *edge_b) { - if(edge_a->facet_number == edge_b->facet_number) { - return 1; /* Don't match edges of the same facet */ - } else { - return memcmp(edge_a, edge_b, SIZEOF_EDGE_SORT); - } -} - -void -stl_check_facets_nearby(stl_file *stl, float tolerance) { - stl_hash_edge edge[3]; - stl_facet facet; - int i; - int j; - - if (stl->error) return; +void stl_check_facets_nearby(stl_file *stl, float tolerance) +{ + if (stl->error) + return; if( (stl->stats.connected_facets_1_edge == stl->stats.number_of_facets) && (stl->stats.connected_facets_2_edge == stl->stats.number_of_facets) @@ -286,27 +256,19 @@ stl_check_facets_nearby(stl_file *stl, float tolerance) { stl_initialize_facet_check_nearby(stl); - for(i = 0; i < stl->stats.number_of_facets; i++) { - facet = stl->facet_start[i]; - // Positive and negative zeros are possible in the floats, which are considered equal by the FP unit. - // When using a memcmp on raw floats, those numbers report to be different. - // Unify all +0 and -0 to +0 to make the floats equal under memcmp. - { - uint32_t *f = (uint32_t*)&facet; - for (int j = 0; j < 12; ++ j, ++ f) // 3x vertex + normal: 4x3 = 12 floats - if (*f == 0x80000000) - // Negative zero, switch to positive zero. - *f = 0; - } - for(j = 0; j < 3; j++) { + for (int i = 0; i < stl->stats.number_of_facets; ++ i) { + //FIXME is the copy necessary? + stl_facet facet = stl->facet_start[i]; + for (int j = 0; j < 3; j++) { if(stl->neighbors_start[i].neighbor[j] == -1) { - edge[j].facet_number = i; - edge[j].which_edge = j; - if(stl_load_edge_nearby(stl, &edge[j], &facet.vertex[j], + stl_hash_edge edge; + edge.facet_number = i; + edge.which_edge = j; + if(stl_load_edge_nearby(stl, &edge, &facet.vertex[j], &facet.vertex[(j + 1) % 3], tolerance)) { /* only insert edges that have different keys */ - insert_hash_edge(stl, edge[j], stl_match_neighbors_nearby); + insert_hash_edge(stl, edge, stl_match_neighbors_nearby); } } } @@ -315,27 +277,17 @@ stl_check_facets_nearby(stl_file *stl, float tolerance) { stl_free_edges(stl); } -static int -stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge, - stl_vertex *a, stl_vertex *b, float tolerance) { +static int stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge, stl_vertex *a, stl_vertex *b, float tolerance) +{ // Index of a grid cell spaced by tolerance. - uint32_t vertex1[3] = { - (uint32_t)((a->x - stl->stats.min.x) / tolerance), - (uint32_t)((a->y - stl->stats.min.y) / tolerance), - (uint32_t)((a->z - stl->stats.min.z) / tolerance) - }; - uint32_t vertex2[3] = { - (uint32_t)((b->x - stl->stats.min.x) / tolerance), - (uint32_t)((b->y - stl->stats.min.y) / tolerance), - (uint32_t)((b->z - stl->stats.min.z) / tolerance) - }; + typedef Eigen::Matrix Vec3i; + Vec3i vertex1 = (*a / tolerance).cast(); + Vec3i vertex2 = (*b / tolerance).cast(); + static_assert(sizeof(Vec3i) == 12, "size of Vec3i incorrect"); - if( (vertex1[0] == vertex2[0]) - && (vertex1[1] == vertex2[1]) - && (vertex1[2] == vertex2[2])) { - /* Both vertices hash to the same value */ + if (vertex1 == vertex2) + // Both vertices hash to the same value return 0; - } // Ensure identical vertex ordering of edges, which vertices land into equal grid cells. // This method is numerically robust. @@ -344,30 +296,27 @@ stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge, ((vertex1[1] != vertex2[1]) ? (vertex1[1] < vertex2[1]) : (vertex1[2] < vertex2[2]))) { - memcpy(&edge->key[0], vertex1, sizeof(stl_vertex)); - memcpy(&edge->key[3], vertex2, sizeof(stl_vertex)); + memcpy(&edge->key[0], vertex1.data(), sizeof(stl_vertex)); + memcpy(&edge->key[sizeof(stl_vertex)], vertex2.data(), sizeof(stl_vertex)); } else { - memcpy(&edge->key[0], vertex2, sizeof(stl_vertex)); - memcpy(&edge->key[3], vertex1, sizeof(stl_vertex)); + memcpy(&edge->key[0], vertex2.data(), sizeof(stl_vertex)); + memcpy(&edge->key[sizeof(stl_vertex)], vertex1.data(), sizeof(stl_vertex)); edge->which_edge += 3; /* this edge is loaded backwards */ } return 1; } -static void -stl_free_edges(stl_file *stl) { - int i; - stl_hash_edge *temp; - - if (stl->error) return; +static void stl_free_edges(stl_file *stl) +{ + if (stl->error) + return; if(stl->stats.malloced != stl->stats.freed) { - for(i = 0; i < stl->M; i++) { - for(temp = stl->heads[i]; stl->heads[i] != stl->tail; - temp = stl->heads[i]) { + for (int i = 0; i < stl->M; i++) { + for (stl_hash_edge *temp = stl->heads[i]; stl->heads[i] != stl->tail; temp = stl->heads[i]) { stl->heads[i] = stl->heads[i]->next; free(temp); - stl->stats.freed++; + ++ stl->stats.freed; } } } @@ -375,8 +324,8 @@ stl_free_edges(stl_file *stl) { free(stl->tail); } -static void -stl_initialize_facet_check_nearby(stl_file *stl) { +static void stl_initialize_facet_check_nearby(stl_file *stl) +{ int i; if (stl->error) return; @@ -467,16 +416,8 @@ stl_record_neighbors(stl_file *stl, } } -static void -stl_match_neighbors_exact(stl_file *stl, - stl_hash_edge *edge_a, stl_hash_edge *edge_b) { - if (stl->error) return; - stl_record_neighbors(stl, edge_a, edge_b); -} - -static void -stl_match_neighbors_nearby(stl_file *stl, - stl_hash_edge *edge_a, stl_hash_edge *edge_b) { +static void stl_match_neighbors_nearby(stl_file *stl, stl_hash_edge *edge_a, stl_hash_edge *edge_b) +{ int facet1; int facet2; int vertex1; @@ -517,9 +458,7 @@ stl_match_neighbors_nearby(stl_file *stl, } -static void -stl_change_vertices(stl_file *stl, int facet_num, int vnot, - stl_vertex new_vertex) { +static void stl_change_vertices(stl_file *stl, int facet_num, int vnot, stl_vertex new_vertex) { int first_facet; int direction; int next_edge; @@ -551,30 +490,30 @@ stl_change_vertices(stl_file *stl, int facet_num, int vnot, } } #if 0 - if (stl->facet_start[facet_num].vertex[pivot_vertex].x == new_vertex.x && - stl->facet_start[facet_num].vertex[pivot_vertex].y == new_vertex.y && - stl->facet_start[facet_num].vertex[pivot_vertex].z == new_vertex.z) + if (stl->facet_start[facet_num].vertex[pivot_vertex](0) == new_vertex(0) && + stl->facet_start[facet_num].vertex[pivot_vertex](1) == new_vertex(1) && + stl->facet_start[facet_num].vertex[pivot_vertex](2) == new_vertex(2)) printf("Changing vertex %f,%f,%f: Same !!!\r\n", - new_vertex.x, new_vertex.y, new_vertex.z); + new_vertex(0), new_vertex(1), new_vertex(2)); else { - if (stl->facet_start[facet_num].vertex[pivot_vertex].x != new_vertex.x) + if (stl->facet_start[facet_num].vertex[pivot_vertex](0) != new_vertex(0)) printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n", - stl->facet_start[facet_num].vertex[pivot_vertex].x, - *reinterpret_cast(&stl->facet_start[facet_num].vertex[pivot_vertex].x), - new_vertex.x, - *reinterpret_cast(&new_vertex.x)); - if (stl->facet_start[facet_num].vertex[pivot_vertex].y != new_vertex.y) + stl->facet_start[facet_num].vertex[pivot_vertex](0), + *reinterpret_cast(&stl->facet_start[facet_num].vertex[pivot_vertex](0)), + new_vertex(0), + *reinterpret_cast(&new_vertex(0))); + if (stl->facet_start[facet_num].vertex[pivot_vertex](1) != new_vertex(1)) printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n", - stl->facet_start[facet_num].vertex[pivot_vertex].y, - *reinterpret_cast(&stl->facet_start[facet_num].vertex[pivot_vertex].y), - new_vertex.y, - *reinterpret_cast(&new_vertex.y)); - if (stl->facet_start[facet_num].vertex[pivot_vertex].z != new_vertex.z) + stl->facet_start[facet_num].vertex[pivot_vertex](1), + *reinterpret_cast(&stl->facet_start[facet_num].vertex[pivot_vertex](1)), + new_vertex(1), + *reinterpret_cast(&new_vertex(1))); + if (stl->facet_start[facet_num].vertex[pivot_vertex](2) != new_vertex(2)) printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n", - stl->facet_start[facet_num].vertex[pivot_vertex].z, - *reinterpret_cast(&stl->facet_start[facet_num].vertex[pivot_vertex].z), - new_vertex.z, - *reinterpret_cast(&new_vertex.z)); + stl->facet_start[facet_num].vertex[pivot_vertex](2), + *reinterpret_cast(&stl->facet_start[facet_num].vertex[pivot_vertex](2)), + new_vertex(2), + *reinterpret_cast(&new_vertex(2))); } #endif stl->facet_start[facet_num].vertex[pivot_vertex] = new_vertex; @@ -595,7 +534,6 @@ Try using a smaller tolerance or don't do a nearby check\n"); } } - static void stl_which_vertices_to_change(stl_file *stl, stl_hash_edge *edge_a, stl_hash_edge *edge_b, int *facet1, int *vertex1, @@ -622,11 +560,10 @@ stl_which_vertices_to_change(stl_file *stl, stl_hash_edge *edge_a, v1b = (edge_b->which_edge + 1) % 3; } - /* Of the first pair, which vertex, if any, should be changed */ - if(!memcmp(&stl->facet_start[edge_a->facet_number].vertex[v1a], - &stl->facet_start[edge_b->facet_number].vertex[v1b], - sizeof(stl_vertex))) { - /* These facets are already equal. No need to change. */ + // Of the first pair, which vertex, if any, should be changed + if(stl->facet_start[edge_a->facet_number].vertex[v1a] == + stl->facet_start[edge_b->facet_number].vertex[v1b]) { + // These facets are already equal. No need to change. *facet1 = -1; } else { if( (stl->neighbors_start[edge_a->facet_number].neighbor[v1a] == -1) @@ -644,10 +581,9 @@ stl_which_vertices_to_change(stl_file *stl, stl_hash_edge *edge_a, } /* Of the second pair, which vertex, if any, should be changed */ - if(!memcmp(&stl->facet_start[edge_a->facet_number].vertex[v2a], - &stl->facet_start[edge_b->facet_number].vertex[v2b], - sizeof(stl_vertex))) { - /* These facets are already equal. No need to change. */ + if(stl->facet_start[edge_a->facet_number].vertex[v2a] == + stl->facet_start[edge_b->facet_number].vertex[v2b]) { + // These facets are already equal. No need to change. *facet2 = -1; } else { if( (stl->neighbors_start[edge_a->facet_number].neighbor[v2a] == -1) @@ -718,40 +654,35 @@ in stl_remove_facet: neighbor = %d numfacets = %d this is wrong\n", } } -void -stl_remove_unconnected_facets(stl_file *stl) { +void stl_remove_unconnected_facets(stl_file *stl) +{ /* A couple of things need to be done here. One is to remove any */ /* completely unconnected facets (0 edges connected) since these are */ /* useless and could be completely wrong. The second thing that needs to */ /* be done is to remove any degenerate facets that were created during */ /* stl_check_facets_nearby(). */ + if (stl->error) + return; - int i; - - if (stl->error) return; - - /* remove degenerate facets */ - for(i = 0; i < stl->stats.number_of_facets; i++) { - if( !memcmp(&stl->facet_start[i].vertex[0], - &stl->facet_start[i].vertex[1], sizeof(stl_vertex)) - || !memcmp(&stl->facet_start[i].vertex[1], - &stl->facet_start[i].vertex[2], sizeof(stl_vertex)) - || !memcmp(&stl->facet_start[i].vertex[0], - &stl->facet_start[i].vertex[2], sizeof(stl_vertex))) { + // remove degenerate facets + for (int i = 0; i < stl->stats.number_of_facets; ++ i) { + if(stl->facet_start[i].vertex[0] == stl->facet_start[i].vertex[1] || + stl->facet_start[i].vertex[0] == stl->facet_start[i].vertex[2] || + stl->facet_start[i].vertex[1] == stl->facet_start[i].vertex[2]) { stl_remove_degenerate(stl, i); i--; } } if(stl->stats.connected_facets_1_edge < stl->stats.number_of_facets) { - /* remove completely unconnected facets */ - for(i = 0; i < stl->stats.number_of_facets; i++) { - if( (stl->neighbors_start[i].neighbor[0] == -1) - && (stl->neighbors_start[i].neighbor[1] == -1) - && (stl->neighbors_start[i].neighbor[2] == -1)) { - /* This facet is completely unconnected. Remove it. */ + // remove completely unconnected facets + for (int i = 0; i < stl->stats.number_of_facets; i++) { + if (stl->neighbors_start[i].neighbor[0] == -1 && + stl->neighbors_start[i].neighbor[1] == -1 && + stl->neighbors_start[i].neighbor[2] == -1) { + // This facet is completely unconnected. Remove it. stl_remove_facet(stl, i); - i--; + -- i; } } } @@ -771,30 +702,24 @@ stl_remove_degenerate(stl_file *stl, int facet) { if (stl->error) return; - if( !memcmp(&stl->facet_start[facet].vertex[0], - &stl->facet_start[facet].vertex[1], sizeof(stl_vertex)) - && !memcmp(&stl->facet_start[facet].vertex[1], - &stl->facet_start[facet].vertex[2], sizeof(stl_vertex))) { + if (stl->facet_start[facet].vertex[0] == stl->facet_start[facet].vertex[1] && + stl->facet_start[facet].vertex[1] == stl->facet_start[facet].vertex[2]) { /* all 3 vertices are equal. Just remove the facet. I don't think*/ /* this is really possible, but just in case... */ printf("removing a facet in stl_remove_degenerate\n"); - stl_remove_facet(stl, facet); return; } - if(!memcmp(&stl->facet_start[facet].vertex[0], - &stl->facet_start[facet].vertex[1], sizeof(stl_vertex))) { + if (stl->facet_start[facet].vertex[0] == stl->facet_start[facet].vertex[1]) { edge1 = 1; edge2 = 2; edge3 = 0; - } else if(!memcmp(&stl->facet_start[facet].vertex[1], - &stl->facet_start[facet].vertex[2], sizeof(stl_vertex))) { + } else if (stl->facet_start[facet].vertex[1] == stl->facet_start[facet].vertex[2]) { edge1 = 0; edge2 = 2; edge3 = 1; - } else if(!memcmp(&stl->facet_start[facet].vertex[2], - &stl->facet_start[facet].vertex[0], sizeof(stl_vertex))) { + } else if (stl->facet_start[facet].vertex[2] == stl->facet_start[facet].vertex[0]) { edge1 = 0; edge2 = 1; edge3 = 2; @@ -883,7 +808,7 @@ stl_fill_holes(stl_file *stl) { stl_load_edge_exact(stl, &edge, &facet.vertex[j], &facet.vertex[(j + 1) % 3]); - insert_hash_edge(stl, edge, stl_match_neighbors_exact); + insert_hash_edge(stl, edge, stl_record_neighbors); } } @@ -939,7 +864,7 @@ stl_fill_holes(stl_file *stl) { stl_load_edge_exact(stl, &edge, &new_facet.vertex[k], &new_facet.vertex[(k + 1) % 3]); - insert_hash_edge(stl, edge, stl_match_neighbors_exact); + insert_hash_edge(stl, edge, stl_record_neighbors); } break; } else { @@ -977,9 +902,7 @@ stl_add_facet(stl_file *stl, stl_facet *new_facet) { stl->facet_start[stl->stats.number_of_facets] = *new_facet; /* note that the normal vector is not set here, just initialized to 0 */ - stl->facet_start[stl->stats.number_of_facets].normal.x = 0.0; - stl->facet_start[stl->stats.number_of_facets].normal.y = 0.0; - stl->facet_start[stl->stats.number_of_facets].normal.z = 0.0; + stl->facet_start[stl->stats.number_of_facets].normal = stl_normal::Zero(); stl->neighbors_start[stl->stats.number_of_facets].neighbor[0] = -1; stl->neighbors_start[stl->stats.number_of_facets].neighbor[1] = -1; diff --git a/xs/src/admesh/normals.cpp b/xs/src/admesh/normals.cpp index b7cf9a8ab..a8faa44bd 100644 --- a/xs/src/admesh/normals.cpp +++ b/xs/src/admesh/normals.cpp @@ -27,12 +27,6 @@ #include "stl.h" -static void stl_reverse_vector(float v[]) { - v[0] *= -1; - v[1] *= -1; - v[2] *= -1; -} - static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag); static void @@ -228,102 +222,52 @@ static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_ /* Returns 2 if the normal is not within tolerance and backwards */ /* Returns 4 if the status is unknown. */ - float normal[3]; - float test_norm[3]; stl_facet *facet; facet = &stl->facet_start[facet_num]; + stl_normal normal; stl_calculate_normal(normal, facet); stl_normalize_vector(normal); + stl_normal normal_dif = (normal - facet->normal).cwiseAbs(); - if( (ABS(normal[0] - facet->normal.x) < 0.001) - && (ABS(normal[1] - facet->normal.y) < 0.001) - && (ABS(normal[2] - facet->normal.z) < 0.001)) { + const float eps = 0.001f; + if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) { /* It is not really necessary to change the values here */ /* but just for consistency, I will. */ - facet->normal.x = normal[0]; - facet->normal.y = normal[1]; - facet->normal.z = normal[2]; + facet->normal = normal; return 0; } - test_norm[0] = facet->normal.x; - test_norm[1] = facet->normal.y; - test_norm[2] = facet->normal.z; - + stl_normal test_norm = facet->normal; stl_normalize_vector(test_norm); - if( (ABS(normal[0] - test_norm[0]) < 0.001) - && (ABS(normal[1] - test_norm[1]) < 0.001) - && (ABS(normal[2] - test_norm[2]) < 0.001)) { + normal_dif = (normal - test_norm).cwiseAbs(); + if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) { if(normal_fix_flag) { - facet->normal.x = normal[0]; - facet->normal.y = normal[1]; - facet->normal.z = normal[2]; + facet->normal = normal; stl->stats.normals_fixed += 1; } return 1; } - stl_reverse_vector(test_norm); - if( (ABS(normal[0] - test_norm[0]) < 0.001) - && (ABS(normal[1] - test_norm[1]) < 0.001) - && (ABS(normal[2] - test_norm[2]) < 0.001)) { - /* Facet is backwards. */ + test_norm *= -1.f; + normal_dif = (normal - test_norm).cwiseAbs(); + if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) { + // Facet is backwards. if(normal_fix_flag) { - facet->normal.x = normal[0]; - facet->normal.y = normal[1]; - facet->normal.z = normal[2]; + facet->normal = normal; stl->stats.normals_fixed += 1; } return 2; } if(normal_fix_flag) { - facet->normal.x = normal[0]; - facet->normal.y = normal[1]; - facet->normal.z = normal[2]; + facet->normal = normal; stl->stats.normals_fixed += 1; } return 4; } -void stl_calculate_normal(float normal[], stl_facet *facet) { - float v1[3] = { - facet->vertex[1].x - facet->vertex[0].x, - facet->vertex[1].y - facet->vertex[0].y, - facet->vertex[1].z - facet->vertex[0].z - }; - float v2[3] = { - facet->vertex[2].x - facet->vertex[0].x, - facet->vertex[2].y - facet->vertex[0].y, - facet->vertex[2].z - facet->vertex[0].z - }; - normal[0] = (float)((double)v1[1] * (double)v2[2]) - ((double)v1[2] * (double)v2[1]); - normal[1] = (float)((double)v1[2] * (double)v2[0]) - ((double)v1[0] * (double)v2[2]); - normal[2] = (float)((double)v1[0] * (double)v2[1]) - ((double)v1[1] * (double)v2[0]); -} - -void stl_normalize_vector(float v[]) { - double length; - double factor; - float min_normal_length; - - length = sqrt((double)v[0] * (double)v[0] + (double)v[1] * (double)v[1] + (double)v[2] * (double)v[2]); - min_normal_length = 0.000000000001; - if(length < min_normal_length) { - v[0] = 0.0; - v[1] = 0.0; - v[2] = 0.0; - return; - } - factor = 1.0 / length; - v[0] *= factor; - v[1] *= factor; - v[2] *= factor; -} - -void -stl_fix_normal_values(stl_file *stl) { +void stl_fix_normal_values(stl_file *stl) { int i; if (stl->error) return; @@ -333,20 +277,16 @@ stl_fix_normal_values(stl_file *stl) { } } -void -stl_reverse_all_facets(stl_file *stl) { - int i; - float normal[3]; +void stl_reverse_all_facets(stl_file *stl) +{ + if (stl->error) + return; - if (stl->error) return; - - for(i = 0; i < stl->stats.number_of_facets; i++) { + stl_normal normal; + for(int i = 0; i < stl->stats.number_of_facets; i++) { stl_reverse_facet(stl, i); stl_calculate_normal(normal, &stl->facet_start[i]); stl_normalize_vector(normal); - stl->facet_start[i].normal.x = normal[0]; - stl->facet_start[i].normal.y = normal[1]; - stl->facet_start[i].normal.z = normal[2]; + stl->facet_start[i].normal = normal; } } - diff --git a/xs/src/admesh/shared.cpp b/xs/src/admesh/shared.cpp index 8080f3574..91bb82e00 100644 --- a/xs/src/admesh/shared.cpp +++ b/xs/src/admesh/shared.cpp @@ -169,7 +169,7 @@ stl_write_off(stl_file *stl, char *file) { for(i = 0; i < stl->stats.shared_vertices; i++) { fprintf(fp, "\t%f %f %f\n", - stl->v_shared[i].x, stl->v_shared[i].y, stl->v_shared[i].z); + stl->v_shared[i](0), stl->v_shared[i](1), stl->v_shared[i](2)); } for(i = 0; i < stl->stats.number_of_facets; i++) { fprintf(fp, "\t3 %d %d %d\n", stl->v_indices[i].vertex[0], @@ -216,10 +216,10 @@ stl_write_vrml(stl_file *stl, char *file) { for(i = 0; i < (stl->stats.shared_vertices - 1); i++) { fprintf(fp, "\t\t\t\t%f %f %f,\n", - stl->v_shared[i].x, stl->v_shared[i].y, stl->v_shared[i].z); + stl->v_shared[i](0), stl->v_shared[i](1), stl->v_shared[i](2)); } fprintf(fp, "\t\t\t\t%f %f %f]\n", - stl->v_shared[i].x, stl->v_shared[i].y, stl->v_shared[i].z); + stl->v_shared[i](0), stl->v_shared[i](1), stl->v_shared[i](2)); fprintf(fp, "\t\t}\n"); fprintf(fp, "\t\tDEF STLTriangles IndexedFaceSet {\n"); fprintf(fp, "\t\t\tcoordIndex [\n"); @@ -254,7 +254,7 @@ void stl_write_obj (stl_file *stl, char *file) { } for (i = 0; i < stl->stats.shared_vertices; i++) { - fprintf(fp, "v %f %f %f\n", stl->v_shared[i].x, stl->v_shared[i].y, stl->v_shared[i].z); + fprintf(fp, "v %f %f %f\n", stl->v_shared[i](0), stl->v_shared[i](1), stl->v_shared[i](2)); } for (i = 0; i < stl->stats.number_of_facets; i++) { fprintf(fp, "f %d %d %d\n", stl->v_indices[i].vertex[0]+1, stl->v_indices[i].vertex[1]+1, stl->v_indices[i].vertex[2]+1); diff --git a/xs/src/admesh/stl.h b/xs/src/admesh/stl.h index dc0f7ae19..5f7a3c5c1 100644 --- a/xs/src/admesh/stl.h +++ b/xs/src/admesh/stl.h @@ -27,9 +27,7 @@ #include #include -#define STL_MAX(A,B) ((A)>(B)? (A):(B)) -#define STL_MIN(A,B) ((A)<(B)? (A):(B)) -#define ABS(X) ((X) < 0 ? -(X) : (X)) +#include // Size of the binary STL header, free form. #define LABEL_SIZE 80 @@ -39,31 +37,16 @@ #define HEADER_SIZE 84 #define STL_MIN_FILE_SIZE 284 #define ASCII_LINES_PER_FACET 7 -// Comparing an edge by memcmp, 2x3x4 bytes = 24 -#define SIZEOF_EDGE_SORT 24 - -typedef struct { - float x; - float y; - float z; -} stl_vertex; +typedef Eigen::Matrix stl_vertex; +typedef Eigen::Matrix stl_normal; static_assert(sizeof(stl_vertex) == 12, "size of stl_vertex incorrect"); - -typedef struct { - float x; - float y; - float z; -} stl_normal; - static_assert(sizeof(stl_normal) == 12, "size of stl_normal incorrect"); -typedef char stl_extra[2]; - typedef struct { stl_normal normal; stl_vertex vertex[3]; - stl_extra extra; + char extra[2]; } stl_facet; #define SIZEOF_STL_FACET 50 @@ -81,8 +64,12 @@ typedef struct { } stl_edge; typedef struct stl_hash_edge { - // Key of a hash edge: 2x binary copy of a floating point vertex. - uint32_t key[6]; + // Key of a hash edge: sorted vertices of the edge. + unsigned char key[2 * sizeof(stl_vertex)]; + // Compare two keys. + bool operator==(const stl_hash_edge &rhs) { return memcmp(key, rhs.key, sizeof(key)) == 0; } + bool operator!=(const stl_hash_edge &rhs) { return ! (*this == rhs); } + int hash(int M) const { return ((key[0] / 23 + key[1] / 19 + key[2] / 17 + key[3] /13 + key[4] / 11 + key[5] / 7 ) % M); } // Index of a facet owning this edge. int facet_number; // Index of this edge inside the facet with an index of facet_number. @@ -91,8 +78,6 @@ typedef struct stl_hash_edge { struct stl_hash_edge *next; } stl_hash_edge; -static_assert(offsetof(stl_hash_edge, facet_number) == SIZEOF_EDGE_SORT, "size of stl_hash_edge.key incorrect"); - typedef struct { // Index of a neighbor facet. int neighbor[3]; @@ -179,8 +164,8 @@ extern void stl_fix_normal_values(stl_file *stl); extern void stl_reverse_all_facets(stl_file *stl); extern void stl_translate(stl_file *stl, float x, float y, float z); extern void stl_translate_relative(stl_file *stl, float x, float y, float z); -extern void stl_scale_versor(stl_file *stl, float versor[3]); -extern void stl_scale(stl_file *stl, float factor); +extern void stl_scale_versor(stl_file *stl, const stl_vertex &versor); +inline void stl_scale(stl_file *stl, float factor) { stl_scale_versor(stl, stl_vertex(factor, factor, factor)); } extern void stl_rotate_x(stl_file *stl, float angle); extern void stl_rotate_y(stl_file *stl, float angle); extern void stl_rotate_z(stl_file *stl, float angle); @@ -195,8 +180,20 @@ extern void stl_write_obj(stl_file *stl, char *file); extern void stl_write_off(stl_file *stl, char *file); extern void stl_write_dxf(stl_file *stl, char *file, char *label); extern void stl_write_vrml(stl_file *stl, char *file); -extern void stl_calculate_normal(float normal[], stl_facet *facet); -extern void stl_normalize_vector(float v[]); +inline void stl_calculate_normal(stl_normal &normal, stl_facet *facet) { + normal = (facet->vertex[1] - facet->vertex[0]).cross(facet->vertex[2] - facet->vertex[0]); +} +inline void stl_normalize_vector(stl_normal &normal) { + double length = normal.cast().norm(); + if (length < 0.000000000001) + normal = stl_normal::Zero(); + else + normal *= (1.0 / length); +} +inline bool stl_vertex_lower(const stl_vertex &a, const stl_vertex &b) { + return (a(0) != b(0)) ? (a(0) < b(0)) : + ((a(1) != b(1)) ? (a(1) < b(1)) : (a(2) < b(2))); +} extern void stl_calculate_volume(stl_file *stl); extern void stl_repair(stl_file *stl, int fixall_flag, int exact_flag, int tolerance_flag, float tolerance, int increment_flag, float increment, int nearby_flag, int iterations, int remove_unconnected_flag, int fill_holes_flag, int normal_directions_flag, int normal_values_flag, int reverse_all_flag, int verbose_flag); @@ -204,8 +201,8 @@ extern void stl_repair(stl_file *stl, int fixall_flag, int exact_flag, int toler extern void stl_initialize(stl_file *stl); extern void stl_count_facets(stl_file *stl, const char *file); extern void stl_allocate(stl_file *stl); -extern void stl_read(stl_file *stl, int first_facet, int first); -extern void stl_facet_stats(stl_file *stl, stl_facet facet, int first); +extern void stl_read(stl_file *stl, int first_facet, bool first); +extern void stl_facet_stats(stl_file *stl, stl_facet facet, bool &first); extern void stl_reallocate(stl_file *stl); extern void stl_add_facet(stl_file *stl, stl_facet *new_facet); extern void stl_get_size(stl_file *stl); diff --git a/xs/src/admesh/stl_io.cpp b/xs/src/admesh/stl_io.cpp index 1603981fc..81e29d286 100644 --- a/xs/src/admesh/stl_io.cpp +++ b/xs/src/admesh/stl_io.cpp @@ -44,9 +44,9 @@ stl_print_edges(stl_file *stl, FILE *file) { for(i = 0; i < edges_allocated; i++) { fprintf(file, "%d, %f, %f, %f, %f, %f, %f\n", stl->edge_start[i].facet_number, - stl->edge_start[i].p1.x, stl->edge_start[i].p1.y, - stl->edge_start[i].p1.z, stl->edge_start[i].p2.x, - stl->edge_start[i].p2.y, stl->edge_start[i].p2.z); + stl->edge_start[i].p1(0), stl->edge_start[i].p1(1), + stl->edge_start[i].p1(2), stl->edge_start[i].p2(0), + stl->edge_start[i].p2(1), stl->edge_start[i].p2(2)); } } @@ -75,11 +75,11 @@ File type : ASCII STL file\n"); Header : %s\n", stl->stats.header); fprintf(file, "============== Size ==============\n"); fprintf(file, "Min X = % f, Max X = % f\n", - stl->stats.min.x, stl->stats.max.x); + stl->stats.min(0), stl->stats.max(0)); fprintf(file, "Min Y = % f, Max Y = % f\n", - stl->stats.min.y, stl->stats.max.y); + stl->stats.min(1), stl->stats.max(1)); fprintf(file, "Min Z = % f, Max Z = % f\n", - stl->stats.min.z, stl->stats.max.z); + stl->stats.min(2), stl->stats.max(2)); fprintf(file, "\ ========= Facet Status ========== Original ============ Final ====\n"); @@ -149,18 +149,18 @@ stl_write_ascii(stl_file *stl, const char *file, const char *label) { for(i = 0; i < stl->stats.number_of_facets; i++) { fprintf(fp, " facet normal % .8E % .8E % .8E\n", - stl->facet_start[i].normal.x, stl->facet_start[i].normal.y, - stl->facet_start[i].normal.z); + stl->facet_start[i].normal(0), stl->facet_start[i].normal(1), + stl->facet_start[i].normal(2)); fprintf(fp, " outer loop\n"); fprintf(fp, " vertex % .8E % .8E % .8E\n", - stl->facet_start[i].vertex[0].x, stl->facet_start[i].vertex[0].y, - stl->facet_start[i].vertex[0].z); + stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1), + stl->facet_start[i].vertex[0](2)); fprintf(fp, " vertex % .8E % .8E % .8E\n", - stl->facet_start[i].vertex[1].x, stl->facet_start[i].vertex[1].y, - stl->facet_start[i].vertex[1].z); + stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1), + stl->facet_start[i].vertex[1](2)); fprintf(fp, " vertex % .8E % .8E % .8E\n", - stl->facet_start[i].vertex[2].x, stl->facet_start[i].vertex[2].y, - stl->facet_start[i].vertex[2].z); + stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), + stl->facet_start[i].vertex[2](2)); fprintf(fp, " endloop\n"); fprintf(fp, " endfacet\n"); } @@ -264,9 +264,9 @@ void stl_write_vertex(stl_file *stl, int facet, int vertex) { if (stl->error) return; printf(" vertex %d/%d % .8E % .8E % .8E\n", vertex, facet, - stl->facet_start[facet].vertex[vertex].x, - stl->facet_start[facet].vertex[vertex].y, - stl->facet_start[facet].vertex[vertex].z); + stl->facet_start[facet].vertex[vertex](0), + stl->facet_start[facet].vertex[vertex](1), + stl->facet_start[facet].vertex[vertex](2)); } void @@ -309,10 +309,10 @@ stl_write_quad_object(stl_file *stl, char *file) { int i; int j; char *error_msg; - stl_vertex connect_color; - stl_vertex uncon_1_color; - stl_vertex uncon_2_color; - stl_vertex uncon_3_color; + stl_vertex connect_color = stl_vertex::Zero(); + stl_vertex uncon_1_color = stl_vertex::Zero(); + stl_vertex uncon_2_color = stl_vertex::Zero(); + stl_vertex uncon_3_color = stl_vertex::Zero(); stl_vertex color; if (stl->error) return; @@ -330,19 +330,6 @@ stl_write_quad_object(stl_file *stl, char *file) { return; } - connect_color.x = 0.0; - connect_color.y = 0.0; - connect_color.z = 1.0; - uncon_1_color.x = 0.0; - uncon_1_color.y = 1.0; - uncon_1_color.z = 0.0; - uncon_2_color.x = 1.0; - uncon_2_color.y = 1.0; - uncon_2_color.z = 1.0; - uncon_3_color.x = 1.0; - uncon_3_color.y = 0.0; - uncon_3_color.z = 0.0; - fprintf(fp, "CQUAD\n"); for(i = 0; i < stl->stats.number_of_facets; i++) { j = ((stl->neighbors_start[i].neighbor[0] == -1) + @@ -358,21 +345,21 @@ stl_write_quad_object(stl_file *stl, char *file) { color = uncon_3_color; } fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n", - stl->facet_start[i].vertex[0].x, - stl->facet_start[i].vertex[0].y, - stl->facet_start[i].vertex[0].z, color.x, color.y, color.z); + stl->facet_start[i].vertex[0](0), + stl->facet_start[i].vertex[0](1), + stl->facet_start[i].vertex[0](2), color(0), color(1), color(2)); fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n", - stl->facet_start[i].vertex[1].x, - stl->facet_start[i].vertex[1].y, - stl->facet_start[i].vertex[1].z, color.x, color.y, color.z); + stl->facet_start[i].vertex[1](0), + stl->facet_start[i].vertex[1](1), + stl->facet_start[i].vertex[1](2), color(0), color(1), color(2)); fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n", - stl->facet_start[i].vertex[2].x, - stl->facet_start[i].vertex[2].y, - stl->facet_start[i].vertex[2].z, color.x, color.y, color.z); + stl->facet_start[i].vertex[2](0), + stl->facet_start[i].vertex[2](1), + stl->facet_start[i].vertex[2](2), color(0), color(1), color(2)); fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n", - stl->facet_start[i].vertex[2].x, - stl->facet_start[i].vertex[2].y, - stl->facet_start[i].vertex[2].z, color.x, color.y, color.z); + stl->facet_start[i].vertex[2](0), + stl->facet_start[i].vertex[2](1), + stl->facet_start[i].vertex[2](2), color(0), color(1), color(2)); } fclose(fp); } @@ -409,17 +396,17 @@ stl_write_dxf(stl_file *stl, char *file, char *label) { for(i = 0; i < stl->stats.number_of_facets; i++) { fprintf(fp, "0\n3DFACE\n8\n0\n"); fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n", - stl->facet_start[i].vertex[0].x, stl->facet_start[i].vertex[0].y, - stl->facet_start[i].vertex[0].z); + stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1), + stl->facet_start[i].vertex[0](2)); fprintf(fp, "11\n%f\n21\n%f\n31\n%f\n", - stl->facet_start[i].vertex[1].x, stl->facet_start[i].vertex[1].y, - stl->facet_start[i].vertex[1].z); + stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1), + stl->facet_start[i].vertex[1](2)); fprintf(fp, "12\n%f\n22\n%f\n32\n%f\n", - stl->facet_start[i].vertex[2].x, stl->facet_start[i].vertex[2].y, - stl->facet_start[i].vertex[2].z); + stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), + stl->facet_start[i].vertex[2](2)); fprintf(fp, "13\n%f\n23\n%f\n33\n%f\n", - stl->facet_start[i].vertex[2].x, stl->facet_start[i].vertex[2].y, - stl->facet_start[i].vertex[2].z); + stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), + stl->facet_start[i].vertex[2](2)); } fprintf(fp, "0\nENDSEC\n0\nEOF\n"); diff --git a/xs/src/admesh/stlinit.cpp b/xs/src/admesh/stlinit.cpp index e572ce930..47a37f0a5 100644 --- a/xs/src/admesh/stlinit.cpp +++ b/xs/src/admesh/stlinit.cpp @@ -40,7 +40,7 @@ stl_open(stl_file *stl, const char *file) { stl_initialize(stl); stl_count_facets(stl, file); stl_allocate(stl); - stl_read(stl, 0, 1); + stl_read(stl, 0, true); if (!stl->error) fclose(stl->fp); } @@ -227,7 +227,7 @@ stl_open_merge(stl_file *stl, char *file_to_merge) { Start at num_facets_so_far, the index to the first unused facet. Also say that this isn't our first time so we should augment stats like min and max instead of erasing them. */ - stl_read(stl, num_facets_so_far, 0); + stl_read(stl, num_facets_so_far, false); /* Restore the stl information we overwrote (for stl_read) so that it still accurately reflects the subject part: */ @@ -255,8 +255,7 @@ stl_reallocate(stl_file *stl) { /* Reads the contents of the file pointed to by stl->fp into the stl structure, starting at facet first_facet. The second argument says if it's our first time running this for the stl and therefore we should reset our max and min stats. */ -void -stl_read(stl_file *stl, int first_facet, int first) { +void stl_read(stl_file *stl, int first_facet, bool first) { stl_facet facet; int i; @@ -294,11 +293,11 @@ stl_read(stl_file *stl, int first_facet, int first) { assert(res_normal == 3); int res_outer_loop = fscanf(stl->fp, " outer loop"); assert(res_outer_loop == 0); - int res_vertex1 = fscanf(stl->fp, " vertex %f %f %f", &facet.vertex[0].x, &facet.vertex[0].y, &facet.vertex[0].z); + int res_vertex1 = fscanf(stl->fp, " vertex %f %f %f", &facet.vertex[0](0), &facet.vertex[0](1), &facet.vertex[0](2)); assert(res_vertex1 == 3); - int res_vertex2 = fscanf(stl->fp, " vertex %f %f %f", &facet.vertex[1].x, &facet.vertex[1].y, &facet.vertex[1].z); + int res_vertex2 = fscanf(stl->fp, " vertex %f %f %f", &facet.vertex[1](0), &facet.vertex[1](1), &facet.vertex[1](2)); assert(res_vertex2 == 3); - int res_vertex3 = fscanf(stl->fp, " vertex %f %f %f", &facet.vertex[2].x, &facet.vertex[2].y, &facet.vertex[2].z); + int res_vertex3 = fscanf(stl->fp, " vertex %f %f %f", &facet.vertex[2](0), &facet.vertex[2](1), &facet.vertex[2](2)); assert(res_vertex3 == 3); int res_endloop = fscanf(stl->fp, " endloop"); assert(res_endloop == 0); @@ -311,9 +310,9 @@ stl_read(stl_file *stl, int first_facet, int first) { } // The facet normal has been parsed as a single string as to workaround for not a numbers in the normal definition. - if (sscanf(normal_buf[0], "%f", &facet.normal.x) != 1 || - sscanf(normal_buf[1], "%f", &facet.normal.y) != 1 || - sscanf(normal_buf[2], "%f", &facet.normal.z) != 1) { + if (sscanf(normal_buf[0], "%f", &facet.normal(0)) != 1 || + sscanf(normal_buf[1], "%f", &facet.normal(1)) != 1 || + sscanf(normal_buf[2], "%f", &facet.normal(2)) != 1) { // Normal was mangled. Maybe denormals or "not a number" were stored? // Just reset the normal and silently ignore it. memset(&facet.normal, 0, sizeof(facet.normal)); @@ -326,104 +325,45 @@ stl_read(stl_file *stl, int first_facet, int first) { // It may be worth to round these numbers to zero during loading to reduce the number of errors reported // during the STL import. for (size_t j = 0; j < 3; ++ j) { - if (facet.vertex[j].x > -1e-12f && facet.vertex[j].x < 1e-12f) - printf("stl_read: facet %d.x = %e\r\n", j, facet.vertex[j].x); - if (facet.vertex[j].y > -1e-12f && facet.vertex[j].y < 1e-12f) - printf("stl_read: facet %d.y = %e\r\n", j, facet.vertex[j].y); - if (facet.vertex[j].z > -1e-12f && facet.vertex[j].z < 1e-12f) - printf("stl_read: facet %d.z = %e\r\n", j, facet.vertex[j].z); + if (facet.vertex[j](0) > -1e-12f && facet.vertex[j](0) < 1e-12f) + printf("stl_read: facet %d(0) = %e\r\n", j, facet.vertex[j](0)); + if (facet.vertex[j](1) > -1e-12f && facet.vertex[j](1) < 1e-12f) + printf("stl_read: facet %d(1) = %e\r\n", j, facet.vertex[j](1)); + if (facet.vertex[j](2) > -1e-12f && facet.vertex[j](2) < 1e-12f) + printf("stl_read: facet %d(2) = %e\r\n", j, facet.vertex[j](2)); } #endif -#if 1 - { - // Positive and negative zeros are possible in the floats, which are considered equal by the FP unit. - // When using a memcmp on raw floats, those numbers report to be different. - // Unify all +0 and -0 to +0 to make the floats equal under memcmp. - uint32_t *f = (uint32_t*)&facet; - for (int j = 0; j < 12; ++ j, ++ f) // 3x vertex + normal: 4x3 = 12 floats - if (*f == 0x80000000) - // Negative zero, switch to positive zero. - *f = 0; - } -#else - { - // Due to the nature of the floating point numbers, close to zero values may be represented with singificantly higher precision - // than the rest of the vertices. Round them to zero. - float *f = (float*)&facet; - for (int j = 0; j < 12; ++ j, ++ f) // 3x vertex + normal: 4x3 = 12 floats - if (*f > -1e-12f && *f < 1e-12f) - // Negative zero, switch to positive zero. - *f = 0; - } -#endif /* Write the facet into memory. */ - memcpy(stl->facet_start+i, &facet, SIZEOF_STL_FACET); + stl->facet_start[i] = facet; stl_facet_stats(stl, facet, first); - first = 0; } - stl->stats.size.x = stl->stats.max.x - stl->stats.min.x; - stl->stats.size.y = stl->stats.max.y - stl->stats.min.y; - stl->stats.size.z = stl->stats.max.z - stl->stats.min.z; - stl->stats.bounding_diameter = sqrt( - stl->stats.size.x * stl->stats.size.x + - stl->stats.size.y * stl->stats.size.y + - stl->stats.size.z * stl->stats.size.z - ); + stl->stats.size = stl->stats.max - stl->stats.min; + stl->stats.bounding_diameter = stl->stats.size.norm(); } -void -stl_facet_stats(stl_file *stl, stl_facet facet, int first) { - float diff_x; - float diff_y; - float diff_z; - float max_diff; +void stl_facet_stats(stl_file *stl, stl_facet facet, bool &first) +{ + if (stl->error) + return; - if (stl->error) return; + // While we are going through all of the facets, let's find the + // maximum and minimum values for x, y, and z - /* while we are going through all of the facets, let's find the */ - /* maximum and minimum values for x, y, and z */ - - /* Initialize the max and min values the first time through*/ if (first) { - stl->stats.max.x = facet.vertex[0].x; - stl->stats.min.x = facet.vertex[0].x; - stl->stats.max.y = facet.vertex[0].y; - stl->stats.min.y = facet.vertex[0].y; - stl->stats.max.z = facet.vertex[0].z; - stl->stats.min.z = facet.vertex[0].z; - - diff_x = ABS(facet.vertex[0].x - facet.vertex[1].x); - diff_y = ABS(facet.vertex[0].y - facet.vertex[1].y); - diff_z = ABS(facet.vertex[0].z - facet.vertex[1].z); - max_diff = STL_MAX(diff_x, diff_y); - max_diff = STL_MAX(diff_z, max_diff); - stl->stats.shortest_edge = max_diff; - - first = 0; + // Initialize the max and min values the first time through + stl->stats.min = facet.vertex[0]; + stl->stats.max = facet.vertex[0]; + stl_vertex diff = (facet.vertex[1] - facet.vertex[0]).cwiseAbs(); + stl->stats.shortest_edge = std::max(diff(0), std::max(diff(1), diff(2))); + first = false; } - /* now find the max and min values */ - stl->stats.max.x = STL_MAX(stl->stats.max.x, facet.vertex[0].x); - stl->stats.min.x = STL_MIN(stl->stats.min.x, facet.vertex[0].x); - stl->stats.max.y = STL_MAX(stl->stats.max.y, facet.vertex[0].y); - stl->stats.min.y = STL_MIN(stl->stats.min.y, facet.vertex[0].y); - stl->stats.max.z = STL_MAX(stl->stats.max.z, facet.vertex[0].z); - stl->stats.min.z = STL_MIN(stl->stats.min.z, facet.vertex[0].z); - - stl->stats.max.x = STL_MAX(stl->stats.max.x, facet.vertex[1].x); - stl->stats.min.x = STL_MIN(stl->stats.min.x, facet.vertex[1].x); - stl->stats.max.y = STL_MAX(stl->stats.max.y, facet.vertex[1].y); - stl->stats.min.y = STL_MIN(stl->stats.min.y, facet.vertex[1].y); - stl->stats.max.z = STL_MAX(stl->stats.max.z, facet.vertex[1].z); - stl->stats.min.z = STL_MIN(stl->stats.min.z, facet.vertex[1].z); - - stl->stats.max.x = STL_MAX(stl->stats.max.x, facet.vertex[2].x); - stl->stats.min.x = STL_MIN(stl->stats.min.x, facet.vertex[2].x); - stl->stats.max.y = STL_MAX(stl->stats.max.y, facet.vertex[2].y); - stl->stats.min.y = STL_MIN(stl->stats.min.y, facet.vertex[2].y); - stl->stats.max.z = STL_MAX(stl->stats.max.z, facet.vertex[2].z); - stl->stats.min.z = STL_MIN(stl->stats.min.z, facet.vertex[2].z); + // Now find the max and min values. + for (size_t i = 0; i < 3; ++ i) { + stl->stats.min = stl->stats.min.cwiseMin(facet.vertex[i]); + stl->stats.max = stl->stats.max.cwiseMax(facet.vertex[i]); + } } void diff --git a/xs/src/admesh/util.cpp b/xs/src/admesh/util.cpp index f3bf59b56..fba1ee76b 100644 --- a/xs/src/admesh/util.cpp +++ b/xs/src/admesh/util.cpp @@ -62,7 +62,7 @@ stl_verify_neighbors(stl_file *stl) { edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3]; edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3]; } - if(memcmp(&edge_a, &edge_b, SIZEOF_EDGE_SORT) != 0) { + if (edge_a.p1 != edge_b.p1 || edge_a.p2 != edge_b.p2) { /* These edges should match but they don't. Print results. */ printf("edge %d of facet %d doesn't match edge %d of facet %d\n", j, i, vnot + 1, neighbor); @@ -73,114 +73,67 @@ stl_verify_neighbors(stl_file *stl) { } } -void -stl_translate(stl_file *stl, float x, float y, float z) { - int i; - int j; - - if (stl->error) return; - - for(i = 0; i < stl->stats.number_of_facets; i++) { - for(j = 0; j < 3; j++) { - stl->facet_start[i].vertex[j].x -= (stl->stats.min.x - x); - stl->facet_start[i].vertex[j].y -= (stl->stats.min.y - y); - stl->facet_start[i].vertex[j].z -= (stl->stats.min.z - z); - } - } - stl->stats.max.x -= (stl->stats.min.x - x); - stl->stats.max.y -= (stl->stats.min.y - y); - stl->stats.max.z -= (stl->stats.min.z - z); - stl->stats.min.x = x; - stl->stats.min.y = y; - stl->stats.min.z = z; +void stl_translate(stl_file *stl, float x, float y, float z) +{ + if (stl->error) + return; + stl_vertex new_min(x, y, z); + stl_vertex shift = new_min - stl->stats.min; + for (int i = 0; i < stl->stats.number_of_facets; ++ i) + for (int j = 0; j < 3; ++ j) + stl->facet_start[i].vertex[j] += shift; + stl->stats.min = new_min; + stl->stats.max += shift; stl_invalidate_shared_vertices(stl); } /* Translates the stl by x,y,z, relatively from wherever it is currently */ -void -stl_translate_relative(stl_file *stl, float x, float y, float z) { - int i; - int j; - - if (stl->error) return; - - for(i = 0; i < stl->stats.number_of_facets; i++) { - for(j = 0; j < 3; j++) { - stl->facet_start[i].vertex[j].x += x; - stl->facet_start[i].vertex[j].y += y; - stl->facet_start[i].vertex[j].z += z; - } - } - stl->stats.min.x += x; - stl->stats.min.y += y; - stl->stats.min.z += z; - stl->stats.max.x += x; - stl->stats.max.y += y; - stl->stats.max.z += z; +void stl_translate_relative(stl_file *stl, float x, float y, float z) +{ + if (stl->error) + return; + stl_vertex shift(x, y, z); + for (int i = 0; i < stl->stats.number_of_facets; ++ i) + for (int j = 0; j < 3; ++ j) + stl->facet_start[i].vertex[j] += shift; + stl->stats.min += shift; + stl->stats.max += shift; stl_invalidate_shared_vertices(stl); } -void -stl_scale_versor(stl_file *stl, float versor[3]) { - int i; - int j; - - if (stl->error) return; - - /* scale extents */ - stl->stats.min.x *= versor[0]; - stl->stats.min.y *= versor[1]; - stl->stats.min.z *= versor[2]; - stl->stats.max.x *= versor[0]; - stl->stats.max.y *= versor[1]; - stl->stats.max.z *= versor[2]; - - /* scale size */ - stl->stats.size.x *= versor[0]; - stl->stats.size.y *= versor[1]; - stl->stats.size.z *= versor[2]; - - /* scale volume */ - if (stl->stats.volume > 0.0) { - stl->stats.volume *= (versor[0] * versor[1] * versor[2]); - } - - for(i = 0; i < stl->stats.number_of_facets; i++) { - for(j = 0; j < 3; j++) { - stl->facet_start[i].vertex[j].x *= versor[0]; - stl->facet_start[i].vertex[j].y *= versor[1]; - stl->facet_start[i].vertex[j].z *= versor[2]; - } - } +void stl_scale_versor(stl_file *stl, const stl_vertex &versor) +{ + if (stl->error) + return; + // Scale extents. + auto s = versor.array(); + stl->stats.min.array() *= s; + stl->stats.max.array() *= s; + // Scale size. + stl->stats.size.array() *= s; + // Scale volume. + if (stl->stats.volume > 0.0) + stl->stats.volume *= versor(0) * versor(1) * versor(2); + // Scale the mesh. + for (int i = 0; i < stl->stats.number_of_facets; ++ i) + for (int j = 0; j < 3; ++ j) + stl->facet_start[i].vertex[j].array() *= s; stl_invalidate_shared_vertices(stl); } -void -stl_scale(stl_file *stl, float factor) { - float versor[3]; - - if (stl->error) return; - - versor[0] = factor; - versor[1] = factor; - versor[2] = factor; - stl_scale_versor(stl, versor); -} - -static void calculate_normals(stl_file *stl) { - float normal[3]; - - if (stl->error) return; +static void calculate_normals(stl_file *stl) +{ + if (stl->error) + return; + stl_normal normal; for(uint32_t i = 0; i < stl->stats.number_of_facets; i++) { stl_calculate_normal(normal, &stl->facet_start[i]); stl_normalize_vector(normal); - stl->facet_start[i].normal.x = normal[0]; - stl->facet_start[i].normal.y = normal[1]; - stl->facet_start[i].normal.z = normal[2]; + stl->facet_start[i].normal = normal; } } @@ -193,9 +146,9 @@ void stl_transform(stl_file *stl, float *trafo3x4) { for (i_vertex = 0; i_vertex < 3; ++ i_vertex) { stl_vertex &v_dst = vertices[i_vertex]; stl_vertex v_src = v_dst; - v_dst.x = trafo3x4[0] * v_src.x + trafo3x4[1] * v_src.y + trafo3x4[2] * v_src.z + trafo3x4[3]; - v_dst.y = trafo3x4[4] * v_src.x + trafo3x4[5] * v_src.y + trafo3x4[6] * v_src.z + trafo3x4[7]; - v_dst.z = trafo3x4[8] * v_src.x + trafo3x4[9] * v_src.y + trafo3x4[10] * v_src.z + trafo3x4[11]; + v_dst(0) = trafo3x4[0] * v_src(0) + trafo3x4[1] * v_src(1) + trafo3x4[2] * v_src(2) + trafo3x4[3]; + v_dst(1) = trafo3x4[4] * v_src(0) + trafo3x4[5] * v_src(1) + trafo3x4[6] * v_src(2) + trafo3x4[7]; + v_dst(2) = trafo3x4[8] * v_src(0) + trafo3x4[9] * v_src(1) + trafo3x4[10] * v_src(2) + trafo3x4[11]; } } stl_get_size(stl); @@ -214,8 +167,8 @@ stl_rotate_x(stl_file *stl, float angle) { for(i = 0; i < stl->stats.number_of_facets; i++) { for(j = 0; j < 3; j++) { - stl_rotate(&stl->facet_start[i].vertex[j].y, - &stl->facet_start[i].vertex[j].z, c, s); + stl_rotate(&stl->facet_start[i].vertex[j](1), + &stl->facet_start[i].vertex[j](2), c, s); } } stl_get_size(stl); @@ -234,8 +187,8 @@ stl_rotate_y(stl_file *stl, float angle) { for(i = 0; i < stl->stats.number_of_facets; i++) { for(j = 0; j < 3; j++) { - stl_rotate(&stl->facet_start[i].vertex[j].z, - &stl->facet_start[i].vertex[j].x, c, s); + stl_rotate(&stl->facet_start[i].vertex[j](2), + &stl->facet_start[i].vertex[j](0), c, s); } } stl_get_size(stl); @@ -254,8 +207,8 @@ stl_rotate_z(stl_file *stl, float angle) { for(i = 0; i < stl->stats.number_of_facets; i++) { for(j = 0; j < 3; j++) { - stl_rotate(&stl->facet_start[i].vertex[j].x, - &stl->facet_start[i].vertex[j].y, c, s); + stl_rotate(&stl->facet_start[i].vertex[j](0), + &stl->facet_start[i].vertex[j](1), c, s); } } stl_get_size(stl); @@ -272,142 +225,98 @@ stl_rotate(float *x, float *y, const double c, const double s) { *y = float(s * xold + c * yold); } -extern void -stl_get_size(stl_file *stl) { - int i; - int j; - - if (stl->error) return; - if (stl->stats.number_of_facets == 0) return; - - stl->stats.min.x = stl->facet_start[0].vertex[0].x; - stl->stats.min.y = stl->facet_start[0].vertex[0].y; - stl->stats.min.z = stl->facet_start[0].vertex[0].z; - stl->stats.max.x = stl->facet_start[0].vertex[0].x; - stl->stats.max.y = stl->facet_start[0].vertex[0].y; - stl->stats.max.z = stl->facet_start[0].vertex[0].z; - - for(i = 0; i < stl->stats.number_of_facets; i++) { - for(j = 0; j < 3; j++) { - stl->stats.min.x = STL_MIN(stl->stats.min.x, - stl->facet_start[i].vertex[j].x); - stl->stats.min.y = STL_MIN(stl->stats.min.y, - stl->facet_start[i].vertex[j].y); - stl->stats.min.z = STL_MIN(stl->stats.min.z, - stl->facet_start[i].vertex[j].z); - stl->stats.max.x = STL_MAX(stl->stats.max.x, - stl->facet_start[i].vertex[j].x); - stl->stats.max.y = STL_MAX(stl->stats.max.y, - stl->facet_start[i].vertex[j].y); - stl->stats.max.z = STL_MAX(stl->stats.max.z, - stl->facet_start[i].vertex[j].z); +void stl_get_size(stl_file *stl) +{ + if (stl->error || stl->stats.number_of_facets == 0) + return; + stl->stats.min = stl->facet_start[0].vertex[0]; + stl->stats.max = stl->stats.min; + for (int i = 0; i < stl->stats.number_of_facets; ++ i) { + const stl_facet &face = stl->facet_start[i]; + for (int j = 0; j < 3; ++ j) { + stl->stats.min = stl->stats.min.cwiseMin(face.vertex[j]); + stl->stats.max = stl->stats.max.cwiseMax(face.vertex[j]); } } - stl->stats.size.x = stl->stats.max.x - stl->stats.min.x; - stl->stats.size.y = stl->stats.max.y - stl->stats.min.y; - stl->stats.size.z = stl->stats.max.z - stl->stats.min.z; - stl->stats.bounding_diameter = sqrt( - stl->stats.size.x * stl->stats.size.x + - stl->stats.size.y * stl->stats.size.y + - stl->stats.size.z * stl->stats.size.z - ); + stl->stats.size = stl->stats.max - stl->stats.min; + stl->stats.bounding_diameter = stl->stats.size.norm(); } -void -stl_mirror_xy(stl_file *stl) { - int i; - int j; - float temp_size; +void stl_mirror_xy(stl_file *stl) +{ + if (stl->error) + return; - if (stl->error) return; - - for(i = 0; i < stl->stats.number_of_facets; i++) { - for(j = 0; j < 3; j++) { - stl->facet_start[i].vertex[j].z *= -1.0; + for(int i = 0; i < stl->stats.number_of_facets; i++) { + for(int j = 0; j < 3; j++) { + stl->facet_start[i].vertex[j](2) *= -1.0; } } - temp_size = stl->stats.min.z; - stl->stats.min.z = stl->stats.max.z; - stl->stats.max.z = temp_size; - stl->stats.min.z *= -1.0; - stl->stats.max.z *= -1.0; + float temp_size = stl->stats.min(2); + stl->stats.min(2) = stl->stats.max(2); + stl->stats.max(2) = temp_size; + stl->stats.min(2) *= -1.0; + stl->stats.max(2) *= -1.0; stl_reverse_all_facets(stl); stl->stats.facets_reversed -= stl->stats.number_of_facets; /* for not altering stats */ } -void -stl_mirror_yz(stl_file *stl) { - int i; - int j; - float temp_size; - +void stl_mirror_yz(stl_file *stl) +{ if (stl->error) return; - for(i = 0; i < stl->stats.number_of_facets; i++) { - for(j = 0; j < 3; j++) { - stl->facet_start[i].vertex[j].x *= -1.0; + for (int i = 0; i < stl->stats.number_of_facets; i++) { + for (int j = 0; j < 3; j++) { + stl->facet_start[i].vertex[j](0) *= -1.0; } } - temp_size = stl->stats.min.x; - stl->stats.min.x = stl->stats.max.x; - stl->stats.max.x = temp_size; - stl->stats.min.x *= -1.0; - stl->stats.max.x *= -1.0; + float temp_size = stl->stats.min(0); + stl->stats.min(0) = stl->stats.max(0); + stl->stats.max(0) = temp_size; + stl->stats.min(0) *= -1.0; + stl->stats.max(0) *= -1.0; stl_reverse_all_facets(stl); stl->stats.facets_reversed -= stl->stats.number_of_facets; /* for not altering stats */ } -void -stl_mirror_xz(stl_file *stl) { - int i; - int j; - float temp_size; +void stl_mirror_xz(stl_file *stl) +{ + if (stl->error) + return; - if (stl->error) return; - - for(i = 0; i < stl->stats.number_of_facets; i++) { - for(j = 0; j < 3; j++) { - stl->facet_start[i].vertex[j].y *= -1.0; + for (int i = 0; i < stl->stats.number_of_facets; i++) { + for (int j = 0; j < 3; j++) { + stl->facet_start[i].vertex[j](1) *= -1.0; } } - temp_size = stl->stats.min.y; - stl->stats.min.y = stl->stats.max.y; - stl->stats.max.y = temp_size; - stl->stats.min.y *= -1.0; - stl->stats.max.y *= -1.0; + float temp_size = stl->stats.min(1); + stl->stats.min(1) = stl->stats.max(1); + stl->stats.max(1) = temp_size; + stl->stats.min(1) *= -1.0; + stl->stats.max(1) *= -1.0; stl_reverse_all_facets(stl); stl->stats.facets_reversed -= stl->stats.number_of_facets; /* for not altering stats */ } -static float get_volume(stl_file *stl) { - stl_vertex p0; - stl_vertex p; - stl_normal n; - float height; - float area; - float volume = 0.0; +static float get_volume(stl_file *stl) +{ + if (stl->error) + return 0; - if (stl->error) return 0; - - /* Choose a point, any point as the reference */ - p0.x = stl->facet_start[0].vertex[0].x; - p0.y = stl->facet_start[0].vertex[0].y; - p0.z = stl->facet_start[0].vertex[0].z; - - for(uint32_t i = 0; i < stl->stats.number_of_facets; i++) { - p.x = stl->facet_start[i].vertex[0].x - p0.x; - p.y = stl->facet_start[i].vertex[0].y - p0.y; - p.z = stl->facet_start[i].vertex[0].z - p0.z; - /* Do dot product to get distance from point to plane */ - n = stl->facet_start[i].normal; - height = (n.x * p.x) + (n.y * p.y) + (n.z * p.z); - area = get_area(&stl->facet_start[i]); + // Choose a point, any point as the reference. + stl_vertex p0 = stl->facet_start[0].vertex[0]; + float volume = 0.f; + for(uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { + // Do dot product to get distance from point to plane. + float height = stl->facet_start[i].normal.dot(stl->facet_start[i].vertex[0] - p0); + float area = get_area(&stl->facet_start[i]); volume += (area * height) / 3.0f; } return volume; } -void stl_calculate_volume(stl_file *stl) { +void stl_calculate_volume(stl_file *stl) +{ if (stl->error) return; stl->stats.volume = get_volume(stl); if(stl->stats.volume < 0.0) { @@ -416,35 +325,32 @@ void stl_calculate_volume(stl_file *stl) { } } -static float get_area(stl_facet *facet) { - double cross[3][3]; - float sum[3]; - float n[3]; - float area; - int i; - +static float get_area(stl_facet *facet) +{ /* cast to double before calculating cross product because large coordinates can result in overflowing product (bad area is responsible for bad volume and bad facets reversal) */ - for(i = 0; i < 3; i++) { - cross[i][0]=(((double)facet->vertex[i].y * (double)facet->vertex[(i + 1) % 3].z) - - ((double)facet->vertex[i].z * (double)facet->vertex[(i + 1) % 3].y)); - cross[i][1]=(((double)facet->vertex[i].z * (double)facet->vertex[(i + 1) % 3].x) - - ((double)facet->vertex[i].x * (double)facet->vertex[(i + 1) % 3].z)); - cross[i][2]=(((double)facet->vertex[i].x * (double)facet->vertex[(i + 1) % 3].y) - - ((double)facet->vertex[i].y * (double)facet->vertex[(i + 1) % 3].x)); + double cross[3][3]; + for (int i = 0; i < 3; i++) { + cross[i][0]=(((double)facet->vertex[i](1) * (double)facet->vertex[(i + 1) % 3](2)) - + ((double)facet->vertex[i](2) * (double)facet->vertex[(i + 1) % 3](1))); + cross[i][1]=(((double)facet->vertex[i](2) * (double)facet->vertex[(i + 1) % 3](0)) - + ((double)facet->vertex[i](0) * (double)facet->vertex[(i + 1) % 3](2))); + cross[i][2]=(((double)facet->vertex[i](0) * (double)facet->vertex[(i + 1) % 3](1)) - + ((double)facet->vertex[i](1) * (double)facet->vertex[(i + 1) % 3](0))); } - sum[0] = cross[0][0] + cross[1][0] + cross[2][0]; - sum[1] = cross[0][1] + cross[1][1] + cross[2][1]; - sum[2] = cross[0][2] + cross[1][2] + cross[2][2]; + stl_normal sum; + sum(0) = cross[0][0] + cross[1][0] + cross[2][0]; + sum(1) = cross[0][1] + cross[1][1] + cross[2][1]; + sum(2) = cross[0][2] + cross[1][2] + cross[2][2]; - /* This should already be done. But just in case, let's do it again */ + // This should already be done. But just in case, let's do it again. + //FIXME this is questionable. the "sum" normal should be accurate, while the normal "n" may be calculated with a low accuracy. + stl_normal n; stl_calculate_normal(n, facet); stl_normalize_vector(n); - - area = 0.5 * (n[0] * sum[0] + n[1] * sum[1] + n[2] * sum[2]); - return area; + return 0.5f * n.dot(sum); } void stl_repair(stl_file *stl, diff --git a/xs/src/eigen/Eigen/Cholesky b/xs/src/eigen/Eigen/Cholesky index 369d1f5ec..1332b540d 100644 --- a/xs/src/eigen/Eigen/Cholesky +++ b/xs/src/eigen/Eigen/Cholesky @@ -9,6 +9,7 @@ #define EIGEN_CHOLESKY_MODULE_H #include "Core" +#include "Jacobi" #include "src/Core/util/DisableStupidWarnings.h" @@ -31,7 +32,11 @@ #include "src/Cholesky/LLT.h" #include "src/Cholesky/LDLT.h" #ifdef EIGEN_USE_LAPACKE +#ifdef EIGEN_USE_MKL +#include "mkl_lapacke.h" +#else #include "src/misc/lapacke.h" +#endif #include "src/Cholesky/LLT_LAPACKE.h" #endif diff --git a/xs/src/eigen/Eigen/Core b/xs/src/eigen/Eigen/Core index 0f7fa630d..4d4901e03 100644 --- a/xs/src/eigen/Eigen/Core +++ b/xs/src/eigen/Eigen/Core @@ -14,6 +14,22 @@ // first thing Eigen does: stop the compiler from committing suicide #include "src/Core/util/DisableStupidWarnings.h" +#if defined(__CUDACC__) && !defined(EIGEN_NO_CUDA) + #define EIGEN_CUDACC __CUDACC__ +#endif + +#if defined(__CUDA_ARCH__) && !defined(EIGEN_NO_CUDA) + #define EIGEN_CUDA_ARCH __CUDA_ARCH__ +#endif + +#if defined(__CUDACC_VER_MAJOR__) && (__CUDACC_VER_MAJOR__ >= 9) +#define EIGEN_CUDACC_VER ((__CUDACC_VER_MAJOR__ * 10000) + (__CUDACC_VER_MINOR__ * 100)) +#elif defined(__CUDACC_VER__) +#define EIGEN_CUDACC_VER __CUDACC_VER__ +#else +#define EIGEN_CUDACC_VER 0 +#endif + // Handle NVCC/CUDA/SYCL #if defined(__CUDACC__) || defined(__SYCL_DEVICE_ONLY__) // Do not try asserts on CUDA and SYCL! @@ -155,6 +171,9 @@ #ifdef __AVX512DQ__ #define EIGEN_VECTORIZE_AVX512DQ #endif + #ifdef __AVX512ER__ + #define EIGEN_VECTORIZE_AVX512ER + #endif #endif // include files @@ -229,7 +248,7 @@ #if defined __CUDACC__ #define EIGEN_VECTORIZE_CUDA #include - #if defined __CUDACC_VER__ && __CUDACC_VER__ >= 70500 + #if EIGEN_CUDACC_VER >= 70500 #define EIGEN_HAS_CUDA_FP16 #endif #endif @@ -352,6 +371,7 @@ using std::ptrdiff_t; #include "src/Core/MathFunctions.h" #include "src/Core/GenericPacketMath.h" #include "src/Core/MathFunctionsImpl.h" +#include "src/Core/arch/Default/ConjHelper.h" #if defined EIGEN_VECTORIZE_AVX512 #include "src/Core/arch/SSE/PacketMath.h" @@ -367,6 +387,7 @@ using std::ptrdiff_t; #include "src/Core/arch/AVX/MathFunctions.h" #include "src/Core/arch/AVX/Complex.h" #include "src/Core/arch/AVX/TypeCasting.h" + #include "src/Core/arch/SSE/TypeCasting.h" #elif defined EIGEN_VECTORIZE_SSE #include "src/Core/arch/SSE/PacketMath.h" #include "src/Core/arch/SSE/MathFunctions.h" diff --git a/xs/src/eigen/Eigen/Eigenvalues b/xs/src/eigen/Eigen/Eigenvalues index 009e529e1..f3f661b07 100644 --- a/xs/src/eigen/Eigen/Eigenvalues +++ b/xs/src/eigen/Eigen/Eigenvalues @@ -45,7 +45,11 @@ #include "src/Eigenvalues/GeneralizedEigenSolver.h" #include "src/Eigenvalues/MatrixBaseEigenvalues.h" #ifdef EIGEN_USE_LAPACKE +#ifdef EIGEN_USE_MKL +#include "mkl_lapacke.h" +#else #include "src/misc/lapacke.h" +#endif #include "src/Eigenvalues/RealSchur_LAPACKE.h" #include "src/Eigenvalues/ComplexSchur_LAPACKE.h" #include "src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h" diff --git a/xs/src/eigen/Eigen/LU b/xs/src/eigen/Eigen/LU index 6f6c55629..6418a86e1 100644 --- a/xs/src/eigen/Eigen/LU +++ b/xs/src/eigen/Eigen/LU @@ -28,7 +28,11 @@ #include "src/LU/FullPivLU.h" #include "src/LU/PartialPivLU.h" #ifdef EIGEN_USE_LAPACKE +#ifdef EIGEN_USE_MKL +#include "mkl_lapacke.h" +#else #include "src/misc/lapacke.h" +#endif #include "src/LU/PartialPivLU_LAPACKE.h" #endif #include "src/LU/Determinant.h" diff --git a/xs/src/eigen/Eigen/QR b/xs/src/eigen/Eigen/QR index 80838e3bd..c7e914469 100644 --- a/xs/src/eigen/Eigen/QR +++ b/xs/src/eigen/Eigen/QR @@ -36,7 +36,11 @@ #include "src/QR/ColPivHouseholderQR.h" #include "src/QR/CompleteOrthogonalDecomposition.h" #ifdef EIGEN_USE_LAPACKE +#ifdef EIGEN_USE_MKL +#include "mkl_lapacke.h" +#else #include "src/misc/lapacke.h" +#endif #include "src/QR/HouseholderQR_LAPACKE.h" #include "src/QR/ColPivHouseholderQR_LAPACKE.h" #endif diff --git a/xs/src/eigen/Eigen/QtAlignedMalloc b/xs/src/eigen/Eigen/QtAlignedMalloc index c6571f129..4f07df02a 100644 --- a/xs/src/eigen/Eigen/QtAlignedMalloc +++ b/xs/src/eigen/Eigen/QtAlignedMalloc @@ -27,7 +27,7 @@ void qFree(void *ptr) void *qRealloc(void *ptr, std::size_t size) { void* newPtr = Eigen::internal::aligned_malloc(size); - memcpy(newPtr, ptr, size); + std::memcpy(newPtr, ptr, size); Eigen::internal::aligned_free(ptr); return newPtr; } diff --git a/xs/src/eigen/Eigen/SVD b/xs/src/eigen/Eigen/SVD index 86143c23d..5d0e75f7f 100644 --- a/xs/src/eigen/Eigen/SVD +++ b/xs/src/eigen/Eigen/SVD @@ -37,7 +37,11 @@ #include "src/SVD/JacobiSVD.h" #include "src/SVD/BDCSVD.h" #if defined(EIGEN_USE_LAPACKE) && !defined(EIGEN_USE_LAPACKE_STRICT) +#ifdef EIGEN_USE_MKL +#include "mkl_lapacke.h" +#else #include "src/misc/lapacke.h" +#endif #include "src/SVD/JacobiSVD_LAPACKE.h" #endif diff --git a/xs/src/eigen/Eigen/src/Cholesky/LDLT.h b/xs/src/eigen/Eigen/src/Cholesky/LDLT.h index fcee7b2e3..0313a54bf 100644 --- a/xs/src/eigen/Eigen/src/Cholesky/LDLT.h +++ b/xs/src/eigen/Eigen/src/Cholesky/LDLT.h @@ -248,7 +248,7 @@ template class LDLT /** \brief Reports whether previous computation was successful. * * \returns \c Success if computation was succesful, - * \c NumericalIssue if the matrix.appears to be negative. + * \c NumericalIssue if the factorization failed because of a zero pivot. */ ComputationInfo info() const { @@ -376,6 +376,8 @@ template<> struct ldlt_inplace if((rs>0) && pivot_is_valid) A21 /= realAkk; + else if(rs>0) + ret = ret && (A21.array()==Scalar(0)).all(); if(found_zero_pivot && pivot_is_valid) ret = false; // factorization failed else if(!pivot_is_valid) found_zero_pivot = true; @@ -568,13 +570,14 @@ void LDLT<_MatrixType,_UpLo>::_solve_impl(const RhsType &rhs, DstType &dst) cons // more precisely, use pseudo-inverse of D (see bug 241) using std::abs; const typename Diagonal::RealReturnType vecD(vectorD()); - // In some previous versions, tolerance was set to the max of 1/highest and the maximal diagonal entry * epsilon - // as motivated by LAPACK's xGELSS: + // In some previous versions, tolerance was set to the max of 1/highest (or rather numeric_limits::min()) + // and the maximal diagonal entry * epsilon as motivated by LAPACK's xGELSS: // RealScalar tolerance = numext::maxi(vecD.array().abs().maxCoeff() * NumTraits::epsilon(),RealScalar(1) / NumTraits::highest()); // However, LDLT is not rank revealing, and so adjusting the tolerance wrt to the highest // diagonal element is not well justified and leads to numerical issues in some cases. // Moreover, Lapack's xSYTRS routines use 0 for the tolerance. - RealScalar tolerance = RealScalar(1) / NumTraits::highest(); + // Using numeric_limits::min() gives us more robustness to denormals. + RealScalar tolerance = (std::numeric_limits::min)(); for (Index i = 0; i < vecD.size(); ++i) { diff --git a/xs/src/eigen/Eigen/src/Cholesky/LLT.h b/xs/src/eigen/Eigen/src/Cholesky/LLT.h index 87ca8d423..e1624d21b 100644 --- a/xs/src/eigen/Eigen/src/Cholesky/LLT.h +++ b/xs/src/eigen/Eigen/src/Cholesky/LLT.h @@ -24,7 +24,7 @@ template struct LLT_Traits; * * \tparam _MatrixType the type of the matrix of which we are computing the LL^T Cholesky decomposition * \tparam _UpLo the triangular part that will be used for the decompositon: Lower (default) or Upper. - * The other triangular part won't be read. + * The other triangular part won't be read. * * This class performs a LL^T Cholesky decomposition of a symmetric, positive definite * matrix A such that A = LL^* = U^*U, where L is lower triangular. @@ -41,14 +41,18 @@ template struct LLT_Traits; * Example: \include LLT_example.cpp * Output: \verbinclude LLT_example.out * + * \b Performance: for best performance, it is recommended to use a column-major storage format + * with the Lower triangular part (the default), or, equivalently, a row-major storage format + * with the Upper triangular part. Otherwise, you might get a 20% slowdown for the full factorization + * step, and rank-updates can be up to 3 times slower. + * * This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism. * + * Note that during the decomposition, only the lower (or upper, as defined by _UpLo) triangular part of A is considered. + * Therefore, the strict lower part does not have to store correct values. + * * \sa MatrixBase::llt(), SelfAdjointView::llt(), class LDLT */ - /* HEY THIS DOX IS DISABLED BECAUSE THERE's A BUG EITHER HERE OR IN LDLT ABOUT THAT (OR BOTH) - * Note that during the decomposition, only the upper triangular part of A is considered. Therefore, - * the strict lower part does not have to store correct values. - */ template class LLT { public: @@ -146,7 +150,7 @@ template class LLT } template - void solveInPlace(MatrixBase &bAndX) const; + void solveInPlace(const MatrixBase &bAndX) const; template LLT& compute(const EigenBase& matrix); @@ -177,7 +181,7 @@ template class LLT /** \brief Reports whether previous computation was successful. * * \returns \c Success if computation was succesful, - * \c NumericalIssue if the matrix.appears to be negative. + * \c NumericalIssue if the matrix.appears not to be positive definite. */ ComputationInfo info() const { @@ -425,7 +429,8 @@ LLT& LLT::compute(const EigenBase eigen_assert(a.rows()==a.cols()); const Index size = a.rows(); m_matrix.resize(size, size); - m_matrix = a.derived(); + if (!internal::is_same_dense(m_matrix, a.derived())) + m_matrix = a.derived(); // Compute matrix L1 norm = max abs column sum. m_l1_norm = RealScalar(0); @@ -485,11 +490,14 @@ void LLT<_MatrixType,_UpLo>::_solve_impl(const RhsType &rhs, DstType &dst) const * * This version avoids a copy when the right hand side matrix b is not needed anymore. * + * \warning The parameter is only marked 'const' to make the C++ compiler accept a temporary expression here. + * This function will const_cast it, so constness isn't honored here. + * * \sa LLT::solve(), MatrixBase::llt() */ template template -void LLT::solveInPlace(MatrixBase &bAndX) const +void LLT::solveInPlace(const MatrixBase &bAndX) const { eigen_assert(m_isInitialized && "LLT is not initialized."); eigen_assert(m_matrix.rows()==bAndX.rows()); diff --git a/xs/src/eigen/Eigen/src/Core/Array.h b/xs/src/eigen/Eigen/src/Core/Array.h index 0d34269fd..e10020d4f 100644 --- a/xs/src/eigen/Eigen/src/Core/Array.h +++ b/xs/src/eigen/Eigen/src/Core/Array.h @@ -231,10 +231,16 @@ class Array : Base(other) { } + private: + struct PrivateType {}; + public: + /** \sa MatrixBase::operator=(const EigenBase&) */ template EIGEN_DEVICE_FUNC - EIGEN_STRONG_INLINE Array(const EigenBase &other) + EIGEN_STRONG_INLINE Array(const EigenBase &other, + typename internal::enable_if::value, + PrivateType>::type = PrivateType()) : Base(other.derived()) { } diff --git a/xs/src/eigen/Eigen/src/Core/ArrayBase.h b/xs/src/eigen/Eigen/src/Core/ArrayBase.h index f0232f65e..3dbc7084c 100644 --- a/xs/src/eigen/Eigen/src/Core/ArrayBase.h +++ b/xs/src/eigen/Eigen/src/Core/ArrayBase.h @@ -175,7 +175,7 @@ template class ArrayBase */ template template -EIGEN_STRONG_INLINE Derived & +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived & ArrayBase::operator-=(const ArrayBase &other) { call_assignment(derived(), other.derived(), internal::sub_assign_op()); @@ -188,7 +188,7 @@ ArrayBase::operator-=(const ArrayBase &other) */ template template -EIGEN_STRONG_INLINE Derived & +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived & ArrayBase::operator+=(const ArrayBase& other) { call_assignment(derived(), other.derived(), internal::add_assign_op()); @@ -201,7 +201,7 @@ ArrayBase::operator+=(const ArrayBase& other) */ template template -EIGEN_STRONG_INLINE Derived & +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived & ArrayBase::operator*=(const ArrayBase& other) { call_assignment(derived(), other.derived(), internal::mul_assign_op()); @@ -214,7 +214,7 @@ ArrayBase::operator*=(const ArrayBase& other) */ template template -EIGEN_STRONG_INLINE Derived & +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived & ArrayBase::operator/=(const ArrayBase& other) { call_assignment(derived(), other.derived(), internal::div_assign_op()); diff --git a/xs/src/eigen/Eigen/src/Core/ArrayWrapper.h b/xs/src/eigen/Eigen/src/Core/ArrayWrapper.h index a04521a16..688aadd62 100644 --- a/xs/src/eigen/Eigen/src/Core/ArrayWrapper.h +++ b/xs/src/eigen/Eigen/src/Core/ArrayWrapper.h @@ -32,7 +32,8 @@ struct traits > // Let's remove NestByRefBit enum { Flags0 = traits::type >::Flags, - Flags = Flags0 & ~NestByRefBit + LvalueBitFlag = is_lvalue::value ? LvalueBit : 0, + Flags = (Flags0 & ~(NestByRefBit | LvalueBit)) | LvalueBitFlag }; }; } @@ -129,7 +130,8 @@ struct traits > // Let's remove NestByRefBit enum { Flags0 = traits::type >::Flags, - Flags = Flags0 & ~NestByRefBit + LvalueBitFlag = is_lvalue::value ? LvalueBit : 0, + Flags = (Flags0 & ~(NestByRefBit | LvalueBit)) | LvalueBitFlag }; }; } diff --git a/xs/src/eigen/Eigen/src/Core/AssignEvaluator.h b/xs/src/eigen/Eigen/src/Core/AssignEvaluator.h index b0ec7b7ca..dbe435d86 100644 --- a/xs/src/eigen/Eigen/src/Core/AssignEvaluator.h +++ b/xs/src/eigen/Eigen/src/Core/AssignEvaluator.h @@ -39,7 +39,7 @@ public: enum { DstAlignment = DstEvaluator::Alignment, SrcAlignment = SrcEvaluator::Alignment, - DstHasDirectAccess = DstFlags & DirectAccessBit, + DstHasDirectAccess = (DstFlags & DirectAccessBit) == DirectAccessBit, JointAlignment = EIGEN_PLAIN_ENUM_MIN(DstAlignment,SrcAlignment) }; @@ -83,7 +83,7 @@ private: && int(OuterStride)!=Dynamic && int(OuterStride)%int(InnerPacketSize)==0 && (EIGEN_UNALIGNED_VECTORIZE || int(JointAlignment)>=int(InnerRequiredAlignment)), MayLinearize = bool(StorageOrdersAgree) && (int(DstFlags) & int(SrcFlags) & LinearAccessBit), - MayLinearVectorize = bool(MightVectorize) && MayLinearize && DstHasDirectAccess + MayLinearVectorize = bool(MightVectorize) && bool(MayLinearize) && bool(DstHasDirectAccess) && (EIGEN_UNALIGNED_VECTORIZE || (int(DstAlignment)>=int(LinearRequiredAlignment)) || MaxSizeAtCompileTime == Dynamic), /* If the destination isn't aligned, we have to do runtime checks and we don't unroll, so it's only good for large enough sizes. */ diff --git a/xs/src/eigen/Eigen/src/Core/Assign_MKL.h b/xs/src/eigen/Eigen/src/Core/Assign_MKL.h index 6c2ab9264..6866095bf 100644 --- a/xs/src/eigen/Eigen/src/Core/Assign_MKL.h +++ b/xs/src/eigen/Eigen/src/Core/Assign_MKL.h @@ -84,7 +84,8 @@ class vml_assign_traits struct Assignment, SrcXprNested>, assign_op, \ Dense2Dense, typename enable_if::EnableVml>::type> { \ typedef CwiseUnaryOp, SrcXprNested> SrcXprType; \ - static void run(DstXprType &dst, const SrcXprType &src, const assign_op &/*func*/) { \ + static void run(DstXprType &dst, const SrcXprType &src, const assign_op &func) { \ + resize_if_allowed(dst, src, func); \ eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); \ if(vml_assign_traits::Traversal==LinearTraversal) { \ VMLOP(dst.size(), (const VMLTYPE*)src.nestedExpression().data(), \ @@ -144,7 +145,8 @@ EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(ceil, Ceil, _) Dense2Dense, typename enable_if::EnableVml>::type> { \ typedef CwiseBinaryOp, SrcXprNested, \ const CwiseNullaryOp,Plain> > SrcXprType; \ - static void run(DstXprType &dst, const SrcXprType &src, const assign_op &/*func*/) { \ + static void run(DstXprType &dst, const SrcXprType &src, const assign_op &func) { \ + resize_if_allowed(dst, src, func); \ eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); \ VMLTYPE exponent = reinterpret_cast(src.rhs().functor().m_other); \ if(vml_assign_traits::Traversal==LinearTraversal) \ diff --git a/xs/src/eigen/Eigen/src/Core/CoreEvaluators.h b/xs/src/eigen/Eigen/src/Core/CoreEvaluators.h index f7c1effca..910889efa 100644 --- a/xs/src/eigen/Eigen/src/Core/CoreEvaluators.h +++ b/xs/src/eigen/Eigen/src/Core/CoreEvaluators.h @@ -977,7 +977,7 @@ struct evaluator > OuterStrideAtCompileTime = HasSameStorageOrderAsArgType ? int(outer_stride_at_compile_time::ret) : int(inner_stride_at_compile_time::ret), - MaskPacketAccessBit = (InnerStrideAtCompileTime == 1) ? PacketAccessBit : 0, + MaskPacketAccessBit = (InnerStrideAtCompileTime == 1 || HasSameStorageOrderAsArgType) ? PacketAccessBit : 0, FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1 || (InnerPanel && (evaluator::Flags&LinearAccessBit))) ? LinearAccessBit : 0, FlagsRowMajorBit = XprType::Flags&RowMajorBit, @@ -987,7 +987,9 @@ struct evaluator > Flags = Flags0 | FlagsLinearAccessBit | FlagsRowMajorBit, PacketAlignment = unpacket_traits::alignment, - Alignment0 = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % int(PacketAlignment)) == 0)) ? int(PacketAlignment) : 0, + Alignment0 = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) + && (OuterStrideAtCompileTime!=0) + && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % int(PacketAlignment)) == 0)) ? int(PacketAlignment) : 0, Alignment = EIGEN_PLAIN_ENUM_MIN(evaluator::Alignment, Alignment0) }; typedef block_evaluator block_evaluator_type; @@ -1018,14 +1020,16 @@ struct unary_evaluator, IndexBa EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& block) : m_argImpl(block.nestedExpression()), m_startRow(block.startRow()), - m_startCol(block.startCol()) + m_startCol(block.startCol()), + m_linear_offset(InnerPanel?(XprType::IsRowMajor ? block.startRow()*block.cols() : block.startCol()*block.rows()):0) { } typedef typename XprType::Scalar Scalar; typedef typename XprType::CoeffReturnType CoeffReturnType; enum { - RowsAtCompileTime = XprType::RowsAtCompileTime + RowsAtCompileTime = XprType::RowsAtCompileTime, + ForwardLinearAccess = InnerPanel && bool(evaluator::Flags&LinearAccessBit) }; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE @@ -1037,7 +1041,10 @@ struct unary_evaluator, IndexBa EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { - return coeff(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); + if (ForwardLinearAccess) + return m_argImpl.coeff(m_linear_offset.value() + index); + else + return coeff(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE @@ -1049,7 +1056,10 @@ struct unary_evaluator, IndexBa EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { - return coeffRef(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); + if (ForwardLinearAccess) + return m_argImpl.coeffRef(m_linear_offset.value() + index); + else + return coeffRef(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); } template @@ -1063,8 +1073,11 @@ struct unary_evaluator, IndexBa EIGEN_STRONG_INLINE PacketType packet(Index index) const { - return packet(RowsAtCompileTime == 1 ? 0 : index, - RowsAtCompileTime == 1 ? index : 0); + if (ForwardLinearAccess) + return m_argImpl.template packet(m_linear_offset.value() + index); + else + return packet(RowsAtCompileTime == 1 ? 0 : index, + RowsAtCompileTime == 1 ? index : 0); } template @@ -1078,15 +1091,19 @@ struct unary_evaluator, IndexBa EIGEN_STRONG_INLINE void writePacket(Index index, const PacketType& x) { - return writePacket(RowsAtCompileTime == 1 ? 0 : index, - RowsAtCompileTime == 1 ? index : 0, - x); + if (ForwardLinearAccess) + return m_argImpl.template writePacket(m_linear_offset.value() + index, x); + else + return writePacket(RowsAtCompileTime == 1 ? 0 : index, + RowsAtCompileTime == 1 ? index : 0, + x); } protected: evaluator m_argImpl; const variable_if_dynamic m_startRow; const variable_if_dynamic m_startCol; + const variable_if_dynamic m_linear_offset; }; // TODO: This evaluator does not actually use the child evaluator; diff --git a/xs/src/eigen/Eigen/src/Core/CwiseNullaryOp.h b/xs/src/eigen/Eigen/src/Core/CwiseNullaryOp.h index dd498f758..ddd607e38 100644 --- a/xs/src/eigen/Eigen/src/Core/CwiseNullaryOp.h +++ b/xs/src/eigen/Eigen/src/Core/CwiseNullaryOp.h @@ -105,7 +105,7 @@ class CwiseNullaryOp : public internal::dense_xpr_base< CwiseNullaryOp template -EIGEN_STRONG_INLINE const CwiseNullaryOp::PlainObject> +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const CwiseNullaryOp::PlainObject> DenseBase::NullaryExpr(Index rows, Index cols, const CustomNullaryOp& func) { return CwiseNullaryOp(rows, cols, func); @@ -150,7 +150,7 @@ DenseBase::NullaryExpr(Index size, const CustomNullaryOp& func) */ template template -EIGEN_STRONG_INLINE const CwiseNullaryOp::PlainObject> +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const CwiseNullaryOp::PlainObject> DenseBase::NullaryExpr(const CustomNullaryOp& func) { return CwiseNullaryOp(RowsAtCompileTime, ColsAtCompileTime, func); @@ -192,7 +192,7 @@ DenseBase::Constant(Index rows, Index cols, const Scalar& value) * \sa class CwiseNullaryOp */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Constant(Index size, const Scalar& value) { return DenseBase::NullaryExpr(size, internal::scalar_constant_op(value)); @@ -208,7 +208,7 @@ DenseBase::Constant(Index size, const Scalar& value) * \sa class CwiseNullaryOp */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Constant(const Scalar& value) { EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) @@ -220,7 +220,7 @@ DenseBase::Constant(const Scalar& value) * \sa LinSpaced(Index,Scalar,Scalar), setLinSpaced(Index,const Scalar&,const Scalar&) */ template -EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType DenseBase::LinSpaced(Sequential_t, Index size, const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) @@ -232,7 +232,7 @@ DenseBase::LinSpaced(Sequential_t, Index size, const Scalar& low, const * \sa LinSpaced(Scalar,Scalar) */ template -EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType DenseBase::LinSpaced(Sequential_t, const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) @@ -264,7 +264,7 @@ DenseBase::LinSpaced(Sequential_t, const Scalar& low, const Scalar& hig * \sa setLinSpaced(Index,const Scalar&,const Scalar&), CwiseNullaryOp */ template -EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType DenseBase::LinSpaced(Index size, const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) @@ -276,7 +276,7 @@ DenseBase::LinSpaced(Index size, const Scalar& low, const Scalar& high) * Special version for fixed size types which does not require the size parameter. */ template -EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::RandomAccessLinSpacedReturnType DenseBase::LinSpaced(const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) @@ -286,7 +286,7 @@ DenseBase::LinSpaced(const Scalar& low, const Scalar& high) /** \returns true if all coefficients in this matrix are approximately equal to \a val, to within precision \a prec */ template -bool DenseBase::isApproxToConstant +EIGEN_DEVICE_FUNC bool DenseBase::isApproxToConstant (const Scalar& val, const RealScalar& prec) const { typename internal::nested_eval::type self(derived()); @@ -301,7 +301,7 @@ bool DenseBase::isApproxToConstant * * \returns true if all coefficients in this matrix are approximately equal to \a value, to within precision \a prec */ template -bool DenseBase::isConstant +EIGEN_DEVICE_FUNC bool DenseBase::isConstant (const Scalar& val, const RealScalar& prec) const { return isApproxToConstant(val, prec); @@ -312,7 +312,7 @@ bool DenseBase::isConstant * \sa setConstant(), Constant(), class CwiseNullaryOp */ template -EIGEN_STRONG_INLINE void DenseBase::fill(const Scalar& val) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void DenseBase::fill(const Scalar& val) { setConstant(val); } @@ -322,7 +322,7 @@ EIGEN_STRONG_INLINE void DenseBase::fill(const Scalar& val) * \sa fill(), setConstant(Index,const Scalar&), setConstant(Index,Index,const Scalar&), setZero(), setOnes(), Constant(), class CwiseNullaryOp, setZero(), setOnes() */ template -EIGEN_STRONG_INLINE Derived& DenseBase::setConstant(const Scalar& val) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setConstant(const Scalar& val) { return derived() = Constant(rows(), cols(), val); } @@ -337,7 +337,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase::setConstant(const Scalar& val) * \sa MatrixBase::setConstant(const Scalar&), setConstant(Index,Index,const Scalar&), class CwiseNullaryOp, MatrixBase::Constant(const Scalar&) */ template -EIGEN_STRONG_INLINE Derived& +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setConstant(Index size, const Scalar& val) { resize(size); @@ -356,7 +356,7 @@ PlainObjectBase::setConstant(Index size, const Scalar& val) * \sa MatrixBase::setConstant(const Scalar&), setConstant(Index,const Scalar&), class CwiseNullaryOp, MatrixBase::Constant(const Scalar&) */ template -EIGEN_STRONG_INLINE Derived& +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setConstant(Index rows, Index cols, const Scalar& val) { resize(rows, cols); @@ -380,7 +380,7 @@ PlainObjectBase::setConstant(Index rows, Index cols, const Scalar& val) * \sa LinSpaced(Index,const Scalar&,const Scalar&), CwiseNullaryOp */ template -EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(Index newSize, const Scalar& low, const Scalar& high) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(Index newSize, const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) return derived() = Derived::NullaryExpr(newSize, internal::linspaced_op(low,high,newSize)); @@ -400,7 +400,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(Index newSize, con * \sa LinSpaced(Index,const Scalar&,const Scalar&), setLinSpaced(Index, const Scalar&, const Scalar&), CwiseNullaryOp */ template -EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(const Scalar& low, const Scalar& high) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(const Scalar& low, const Scalar& high) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) return setLinSpaced(size(), low, high); @@ -423,7 +423,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(const Scalar& low, * \sa Zero(), Zero(Index) */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Zero(Index rows, Index cols) { return Constant(rows, cols, Scalar(0)); @@ -446,7 +446,7 @@ DenseBase::Zero(Index rows, Index cols) * \sa Zero(), Zero(Index,Index) */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Zero(Index size) { return Constant(size, Scalar(0)); @@ -463,7 +463,7 @@ DenseBase::Zero(Index size) * \sa Zero(Index), Zero(Index,Index) */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Zero() { return Constant(Scalar(0)); @@ -478,7 +478,7 @@ DenseBase::Zero() * \sa class CwiseNullaryOp, Zero() */ template -bool DenseBase::isZero(const RealScalar& prec) const +EIGEN_DEVICE_FUNC bool DenseBase::isZero(const RealScalar& prec) const { typename internal::nested_eval::type self(derived()); for(Index j = 0; j < cols(); ++j) @@ -496,7 +496,7 @@ bool DenseBase::isZero(const RealScalar& prec) const * \sa class CwiseNullaryOp, Zero() */ template -EIGEN_STRONG_INLINE Derived& DenseBase::setZero() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setZero() { return setConstant(Scalar(0)); } @@ -511,7 +511,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase::setZero() * \sa DenseBase::setZero(), setZero(Index,Index), class CwiseNullaryOp, DenseBase::Zero() */ template -EIGEN_STRONG_INLINE Derived& +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setZero(Index newSize) { resize(newSize); @@ -529,7 +529,7 @@ PlainObjectBase::setZero(Index newSize) * \sa DenseBase::setZero(), setZero(Index), class CwiseNullaryOp, DenseBase::Zero() */ template -EIGEN_STRONG_INLINE Derived& +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setZero(Index rows, Index cols) { resize(rows, cols); @@ -553,7 +553,7 @@ PlainObjectBase::setZero(Index rows, Index cols) * \sa Ones(), Ones(Index), isOnes(), class Ones */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Ones(Index rows, Index cols) { return Constant(rows, cols, Scalar(1)); @@ -576,7 +576,7 @@ DenseBase::Ones(Index rows, Index cols) * \sa Ones(), Ones(Index,Index), isOnes(), class Ones */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Ones(Index newSize) { return Constant(newSize, Scalar(1)); @@ -593,7 +593,7 @@ DenseBase::Ones(Index newSize) * \sa Ones(Index), Ones(Index,Index), isOnes(), class Ones */ template -EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase::ConstantReturnType DenseBase::Ones() { return Constant(Scalar(1)); @@ -608,7 +608,7 @@ DenseBase::Ones() * \sa class CwiseNullaryOp, Ones() */ template -bool DenseBase::isOnes +EIGEN_DEVICE_FUNC bool DenseBase::isOnes (const RealScalar& prec) const { return isApproxToConstant(Scalar(1), prec); @@ -622,7 +622,7 @@ bool DenseBase::isOnes * \sa class CwiseNullaryOp, Ones() */ template -EIGEN_STRONG_INLINE Derived& DenseBase::setOnes() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::setOnes() { return setConstant(Scalar(1)); } @@ -637,7 +637,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase::setOnes() * \sa MatrixBase::setOnes(), setOnes(Index,Index), class CwiseNullaryOp, MatrixBase::Ones() */ template -EIGEN_STRONG_INLINE Derived& +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setOnes(Index newSize) { resize(newSize); @@ -655,7 +655,7 @@ PlainObjectBase::setOnes(Index newSize) * \sa MatrixBase::setOnes(), setOnes(Index), class CwiseNullaryOp, MatrixBase::Ones() */ template -EIGEN_STRONG_INLINE Derived& +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& PlainObjectBase::setOnes(Index rows, Index cols) { resize(rows, cols); @@ -679,7 +679,7 @@ PlainObjectBase::setOnes(Index rows, Index cols) * \sa Identity(), setIdentity(), isIdentity() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::IdentityReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::IdentityReturnType MatrixBase::Identity(Index rows, Index cols) { return DenseBase::NullaryExpr(rows, cols, internal::scalar_identity_op()); @@ -696,7 +696,7 @@ MatrixBase::Identity(Index rows, Index cols) * \sa Identity(Index,Index), setIdentity(), isIdentity() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::IdentityReturnType +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::IdentityReturnType MatrixBase::Identity() { EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) @@ -771,7 +771,7 @@ struct setIdentity_impl * \sa class CwiseNullaryOp, Identity(), Identity(Index,Index), isIdentity() */ template -EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity() { return internal::setIdentity_impl::run(derived()); } @@ -787,7 +787,7 @@ EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity() * \sa MatrixBase::setIdentity(), class CwiseNullaryOp, MatrixBase::Identity() */ template -EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity(Index rows, Index cols) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity(Index rows, Index cols) { derived().resize(rows, cols); return setIdentity(); @@ -800,7 +800,7 @@ EIGEN_STRONG_INLINE Derived& MatrixBase::setIdentity(Index rows, Index * \sa MatrixBase::Unit(Index), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::Unit(Index newSize, Index i) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::Unit(Index newSize, Index i) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) return BasisReturnType(SquareMatrixType::Identity(newSize,newSize), i); @@ -815,7 +815,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBa * \sa MatrixBase::Unit(Index,Index), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::Unit(Index i) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::Unit(Index i) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) return BasisReturnType(SquareMatrixType::Identity(),i); @@ -828,7 +828,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBa * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitX() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitX() { return Derived::Unit(0); } /** \returns an expression of the Y axis unit vector (0,1{,0}^*) @@ -838,7 +838,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBa * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitY() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitY() { return Derived::Unit(1); } /** \returns an expression of the Z axis unit vector (0,0,1{,0}^*) @@ -848,7 +848,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBa * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitZ() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitZ() { return Derived::Unit(2); } /** \returns an expression of the W axis unit vector (0,0,0,1) @@ -858,7 +858,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBa * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() */ template -EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitW() +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitW() { return Derived::Unit(3); } } // end namespace Eigen diff --git a/xs/src/eigen/Eigen/src/Core/DenseBase.h b/xs/src/eigen/Eigen/src/Core/DenseBase.h index 46fe5193c..90066ae73 100644 --- a/xs/src/eigen/Eigen/src/Core/DenseBase.h +++ b/xs/src/eigen/Eigen/src/Core/DenseBase.h @@ -296,7 +296,7 @@ template class DenseBase EIGEN_DEVICE_FUNC Derived& operator=(const ReturnByValue& func); - /** \ínternal + /** \internal * Copies \a other into *this without evaluating other. \returns a reference to *this. * \deprecated */ template @@ -484,9 +484,9 @@ template class DenseBase return derived().coeff(0,0); } - bool all() const; - bool any() const; - Index count() const; + EIGEN_DEVICE_FUNC bool all() const; + EIGEN_DEVICE_FUNC bool any() const; + EIGEN_DEVICE_FUNC Index count() const; typedef VectorwiseOp RowwiseReturnType; typedef const VectorwiseOp ConstRowwiseReturnType; diff --git a/xs/src/eigen/Eigen/src/Core/Diagonal.h b/xs/src/eigen/Eigen/src/Core/Diagonal.h index 49e711257..afcaf3575 100644 --- a/xs/src/eigen/Eigen/src/Core/Diagonal.h +++ b/xs/src/eigen/Eigen/src/Core/Diagonal.h @@ -70,7 +70,10 @@ template class Diagonal EIGEN_DENSE_PUBLIC_INTERFACE(Diagonal) EIGEN_DEVICE_FUNC - explicit inline Diagonal(MatrixType& matrix, Index a_index = DiagIndex) : m_matrix(matrix), m_index(a_index) {} + explicit inline Diagonal(MatrixType& matrix, Index a_index = DiagIndex) : m_matrix(matrix), m_index(a_index) + { + eigen_assert( a_index <= m_matrix.cols() && -a_index <= m_matrix.rows() ); + } EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Diagonal) diff --git a/xs/src/eigen/Eigen/src/Core/Dot.h b/xs/src/eigen/Eigen/src/Core/Dot.h index 06ef18b8b..1fe7a84a4 100644 --- a/xs/src/eigen/Eigen/src/Core/Dot.h +++ b/xs/src/eigen/Eigen/src/Core/Dot.h @@ -31,7 +31,8 @@ struct dot_nocheck typedef scalar_conj_product_op::Scalar,typename traits::Scalar> conj_prod; typedef typename conj_prod::result_type ResScalar; EIGEN_DEVICE_FUNC - static inline ResScalar run(const MatrixBase& a, const MatrixBase& b) + EIGEN_STRONG_INLINE + static ResScalar run(const MatrixBase& a, const MatrixBase& b) { return a.template binaryExpr(b).sum(); } @@ -43,7 +44,8 @@ struct dot_nocheck typedef scalar_conj_product_op::Scalar,typename traits::Scalar> conj_prod; typedef typename conj_prod::result_type ResScalar; EIGEN_DEVICE_FUNC - static inline ResScalar run(const MatrixBase& a, const MatrixBase& b) + EIGEN_STRONG_INLINE + static ResScalar run(const MatrixBase& a, const MatrixBase& b) { return a.transpose().template binaryExpr(b).sum(); } @@ -65,6 +67,7 @@ struct dot_nocheck template template EIGEN_DEVICE_FUNC +EIGEN_STRONG_INLINE typename ScalarBinaryOpTraits::Scalar,typename internal::traits::Scalar>::ReturnType MatrixBase::dot(const MatrixBase& other) const { @@ -102,7 +105,7 @@ EIGEN_STRONG_INLINE typename NumTraits::Scala * \sa lpNorm(), dot(), squaredNorm() */ template -inline typename NumTraits::Scalar>::Real MatrixBase::norm() const +EIGEN_STRONG_INLINE typename NumTraits::Scalar>::Real MatrixBase::norm() const { return numext::sqrt(squaredNorm()); } @@ -117,7 +120,7 @@ inline typename NumTraits::Scalar>::Real Matr * \sa norm(), normalize() */ template -inline const typename MatrixBase::PlainObject +EIGEN_STRONG_INLINE const typename MatrixBase::PlainObject MatrixBase::normalized() const { typedef typename internal::nested_eval::type _Nested; @@ -139,7 +142,7 @@ MatrixBase::normalized() const * \sa norm(), normalized() */ template -inline void MatrixBase::normalize() +EIGEN_STRONG_INLINE void MatrixBase::normalize() { RealScalar z = squaredNorm(); // NOTE: after extensive benchmarking, this conditional does not impact performance, at least on recent x86 CPU @@ -160,7 +163,7 @@ inline void MatrixBase::normalize() * \sa stableNorm(), stableNormalize(), normalized() */ template -inline const typename MatrixBase::PlainObject +EIGEN_STRONG_INLINE const typename MatrixBase::PlainObject MatrixBase::stableNormalized() const { typedef typename internal::nested_eval::type _Nested; @@ -185,7 +188,7 @@ MatrixBase::stableNormalized() const * \sa stableNorm(), stableNormalized(), normalize() */ template -inline void MatrixBase::stableNormalize() +EIGEN_STRONG_INLINE void MatrixBase::stableNormalize() { RealScalar w = cwiseAbs().maxCoeff(); RealScalar z = (derived()/w).squaredNorm(); diff --git a/xs/src/eigen/Eigen/src/Core/EigenBase.h b/xs/src/eigen/Eigen/src/Core/EigenBase.h index f76995af9..b195506a9 100644 --- a/xs/src/eigen/Eigen/src/Core/EigenBase.h +++ b/xs/src/eigen/Eigen/src/Core/EigenBase.h @@ -14,6 +14,7 @@ namespace Eigen { /** \class EigenBase + * \ingroup Core_Module * * Common base class for all classes T such that MatrixBase has an operator=(T) and a constructor MatrixBase(T). * @@ -128,6 +129,7 @@ template struct EigenBase */ template template +EIGEN_DEVICE_FUNC Derived& DenseBase::operator=(const EigenBase &other) { call_assignment(derived(), other.derived()); @@ -136,6 +138,7 @@ Derived& DenseBase::operator=(const EigenBase &other) template template +EIGEN_DEVICE_FUNC Derived& DenseBase::operator+=(const EigenBase &other) { call_assignment(derived(), other.derived(), internal::add_assign_op()); @@ -144,6 +147,7 @@ Derived& DenseBase::operator+=(const EigenBase &other) template template +EIGEN_DEVICE_FUNC Derived& DenseBase::operator-=(const EigenBase &other) { call_assignment(derived(), other.derived(), internal::sub_assign_op()); diff --git a/xs/src/eigen/Eigen/src/Core/GeneralProduct.h b/xs/src/eigen/Eigen/src/Core/GeneralProduct.h index 0f16cd8e3..6f0cc80e9 100644 --- a/xs/src/eigen/Eigen/src/Core/GeneralProduct.h +++ b/xs/src/eigen/Eigen/src/Core/GeneralProduct.h @@ -24,12 +24,17 @@ template struct product_type_selector; template struct product_size_category { - enum { is_large = MaxSize == Dynamic || - Size >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD || - (Size==Dynamic && MaxSize>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD), - value = is_large ? Large - : Size == 1 ? 1 - : Small + enum { + #ifndef EIGEN_CUDA_ARCH + is_large = MaxSize == Dynamic || + Size >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD || + (Size==Dynamic && MaxSize>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD), + #else + is_large = 0, + #endif + value = is_large ? Large + : Size == 1 ? 1 + : Small }; }; @@ -379,8 +384,6 @@ template<> struct gemv_dense_selector * * \sa lazyProduct(), operator*=(const MatrixBase&), Cwise::operator*() */ -#ifndef __CUDACC__ - template template inline const Product @@ -412,8 +415,6 @@ MatrixBase::operator*(const MatrixBase &other) const return Product(derived(), other.derived()); } -#endif // __CUDACC__ - /** \returns an expression of the matrix product of \c *this and \a other without implicit evaluation. * * The returned product will behave like any other expressions: the coefficients of the product will be diff --git a/xs/src/eigen/Eigen/src/Core/GenericPacketMath.h b/xs/src/eigen/Eigen/src/Core/GenericPacketMath.h index 27033a2dd..029f8ac36 100644 --- a/xs/src/eigen/Eigen/src/Core/GenericPacketMath.h +++ b/xs/src/eigen/Eigen/src/Core/GenericPacketMath.h @@ -230,7 +230,7 @@ pload1(const typename unpacket_traits::type *a) { return pset1( * duplicated to form: {from[0],from[0],from[1],from[1],from[2],from[2],from[3],from[3]} * Currently, this function is only used for scalar * complex products. */ -template EIGEN_DEVICE_FUNC inline Packet +template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet ploaddup(const typename unpacket_traits::type* from) { return *from; } /** \internal \returns a packet with elements of \a *from quadrupled. @@ -278,7 +278,7 @@ inline void pbroadcast2(const typename unpacket_traits::type *a, } /** \internal \brief Returns a packet with coefficients (a,a+1,...,a+packet_size-1). */ -template inline Packet +template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet plset(const typename unpacket_traits::type& a) { return a; } /** \internal copy the packet \a from to \a *to, \a to must be 16 bytes aligned */ @@ -482,7 +482,7 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pstoret(Scalar* to, const Packet& fro * by the current computation. */ template -inline Packet ploadt_ro(const typename unpacket_traits::type* from) +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet ploadt_ro(const typename unpacket_traits::type* from) { return ploadt(from); } diff --git a/xs/src/eigen/Eigen/src/Core/Map.h b/xs/src/eigen/Eigen/src/Core/Map.h index 06d196702..548bf9a2d 100644 --- a/xs/src/eigen/Eigen/src/Core/Map.h +++ b/xs/src/eigen/Eigen/src/Core/Map.h @@ -20,11 +20,17 @@ struct traits > { typedef traits TraitsBase; enum { + PlainObjectTypeInnerSize = ((traits::Flags&RowMajorBit)==RowMajorBit) + ? PlainObjectType::ColsAtCompileTime + : PlainObjectType::RowsAtCompileTime, + InnerStrideAtCompileTime = StrideType::InnerStrideAtCompileTime == 0 ? int(PlainObjectType::InnerStrideAtCompileTime) : int(StrideType::InnerStrideAtCompileTime), OuterStrideAtCompileTime = StrideType::OuterStrideAtCompileTime == 0 - ? int(PlainObjectType::OuterStrideAtCompileTime) + ? (InnerStrideAtCompileTime==Dynamic || PlainObjectTypeInnerSize==Dynamic + ? Dynamic + : int(InnerStrideAtCompileTime) * int(PlainObjectTypeInnerSize)) : int(StrideType::OuterStrideAtCompileTime), Alignment = int(MapOptions)&int(AlignedMask), Flags0 = TraitsBase::Flags & (~NestByRefBit), @@ -107,10 +113,11 @@ template class Ma EIGEN_DEVICE_FUNC inline Index outerStride() const { - return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer() - : IsVectorAtCompileTime ? this->size() - : int(Flags)&RowMajorBit ? this->cols() - : this->rows(); + return int(StrideType::OuterStrideAtCompileTime) != 0 ? m_stride.outer() + : int(internal::traits::OuterStrideAtCompileTime) != Dynamic ? Index(internal::traits::OuterStrideAtCompileTime) + : IsVectorAtCompileTime ? (this->size() * innerStride()) + : (int(Flags)&RowMajorBit) ? (this->cols() * innerStride()) + : (this->rows() * innerStride()); } /** Constructor in the fixed-size case. diff --git a/xs/src/eigen/Eigen/src/Core/MathFunctions.h b/xs/src/eigen/Eigen/src/Core/MathFunctions.h index 8d47fb8a4..6eb974d41 100644 --- a/xs/src/eigen/Eigen/src/Core/MathFunctions.h +++ b/xs/src/eigen/Eigen/src/Core/MathFunctions.h @@ -348,31 +348,7 @@ struct norm1_retval * Implementation of hypot * ****************************************************************************/ -template -struct hypot_impl -{ - typedef typename NumTraits::Real RealScalar; - static inline RealScalar run(const Scalar& x, const Scalar& y) - { - EIGEN_USING_STD_MATH(abs); - EIGEN_USING_STD_MATH(sqrt); - RealScalar _x = abs(x); - RealScalar _y = abs(y); - Scalar p, qp; - if(_x>_y) - { - p = _x; - qp = _y / p; - } - else - { - p = _y; - qp = _x / p; - } - if(p==RealScalar(0)) return RealScalar(0); - return p * sqrt(RealScalar(1) + qp*qp); - } -}; +template struct hypot_impl; template struct hypot_retval @@ -495,7 +471,7 @@ namespace std_fallback { typedef typename NumTraits::Real RealScalar; EIGEN_USING_STD_MATH(log); Scalar x1p = RealScalar(1) + x; - return ( x1p == Scalar(1) ) ? x : x * ( log(x1p) / (x1p - RealScalar(1)) ); + return numext::equal_strict(x1p, Scalar(1)) ? x : x * ( log(x1p) / (x1p - RealScalar(1)) ); } } @@ -1061,11 +1037,24 @@ double log(const double &x) { return ::log(x); } template EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE -typename NumTraits::Real abs(const T &x) { +typename internal::enable_if::IsSigned || NumTraits::IsComplex,typename NumTraits::Real>::type +abs(const T &x) { EIGEN_USING_STD_MATH(abs); return abs(x); } +template +EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE +typename internal::enable_if::IsSigned || NumTraits::IsComplex),typename NumTraits::Real>::type +abs(const T &x) { + return x; +} + +#if defined(__SYCL_DEVICE_ONLY__) +EIGEN_ALWAYS_INLINE float abs(float x) { return cl::sycl::fabs(x); } +EIGEN_ALWAYS_INLINE double abs(double x) { return cl::sycl::fabs(x); } +#endif // defined(__SYCL_DEVICE_ONLY__) + #ifdef __CUDACC__ template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float abs(const float &x) { return ::fabsf(x); } diff --git a/xs/src/eigen/Eigen/src/Core/MathFunctionsImpl.h b/xs/src/eigen/Eigen/src/Core/MathFunctionsImpl.h index 3c9ef22fa..9c1ceb0eb 100644 --- a/xs/src/eigen/Eigen/src/Core/MathFunctionsImpl.h +++ b/xs/src/eigen/Eigen/src/Core/MathFunctionsImpl.h @@ -71,6 +71,29 @@ T generic_fast_tanh_float(const T& a_x) return pdiv(p, q); } +template +EIGEN_STRONG_INLINE +RealScalar positive_real_hypot(const RealScalar& x, const RealScalar& y) +{ + EIGEN_USING_STD_MATH(sqrt); + RealScalar p, qp; + p = numext::maxi(x,y); + if(p==RealScalar(0)) return RealScalar(0); + qp = numext::mini(y,x) / p; + return p * sqrt(RealScalar(1) + qp*qp); +} + +template +struct hypot_impl +{ + typedef typename NumTraits::Real RealScalar; + static inline RealScalar run(const Scalar& x, const Scalar& y) + { + EIGEN_USING_STD_MATH(abs); + return positive_real_hypot(abs(x), abs(y)); + } +}; + } // end namespace internal } // end namespace Eigen diff --git a/xs/src/eigen/Eigen/src/Core/MatrixBase.h b/xs/src/eigen/Eigen/src/Core/MatrixBase.h index f7cf04cde..05db48813 100644 --- a/xs/src/eigen/Eigen/src/Core/MatrixBase.h +++ b/xs/src/eigen/Eigen/src/Core/MatrixBase.h @@ -160,20 +160,11 @@ template class MatrixBase EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator-=(const MatrixBase& other); -#ifdef __CUDACC__ template EIGEN_DEVICE_FUNC - const Product - operator*(const MatrixBase &other) const - { return this->lazyProduct(other); } -#else - - template const Product operator*(const MatrixBase &other) const; -#endif - template EIGEN_DEVICE_FUNC const Product @@ -294,7 +285,7 @@ template class MatrixBase * fuzzy comparison such as isApprox() * \sa isApprox(), operator!= */ template - inline bool operator==(const MatrixBase& other) const + EIGEN_DEVICE_FUNC inline bool operator==(const MatrixBase& other) const { return cwiseEqual(other).all(); } /** \returns true if at least one pair of coefficients of \c *this and \a other are not exactly equal to each other. @@ -302,7 +293,7 @@ template class MatrixBase * fuzzy comparison such as isApprox() * \sa isApprox(), operator== */ template - inline bool operator!=(const MatrixBase& other) const + EIGEN_DEVICE_FUNC inline bool operator!=(const MatrixBase& other) const { return cwiseNotEqual(other).any(); } NoAlias noalias(); diff --git a/xs/src/eigen/Eigen/src/Core/NumTraits.h b/xs/src/eigen/Eigen/src/Core/NumTraits.h index dd61195bc..daf489878 100644 --- a/xs/src/eigen/Eigen/src/Core/NumTraits.h +++ b/xs/src/eigen/Eigen/src/Core/NumTraits.h @@ -215,6 +215,8 @@ struct NumTraits > static inline RealScalar epsilon() { return NumTraits::epsilon(); } EIGEN_DEVICE_FUNC static inline RealScalar dummy_precision() { return NumTraits::dummy_precision(); } + + static inline int digits10() { return NumTraits::digits10(); } }; template<> struct NumTraits diff --git a/xs/src/eigen/Eigen/src/Core/PlainObjectBase.h b/xs/src/eigen/Eigen/src/Core/PlainObjectBase.h index 77f4f6066..1dc7e223a 100644 --- a/xs/src/eigen/Eigen/src/Core/PlainObjectBase.h +++ b/xs/src/eigen/Eigen/src/Core/PlainObjectBase.h @@ -577,6 +577,10 @@ class PlainObjectBase : public internal::dense_xpr_base::type * while the AlignedMap() functions return aligned Map objects and thus should be called only with 16-byte-aligned * \a data pointers. * + * Here is an example using strides: + * \include Matrix_Map_stride.cpp + * Output: \verbinclude Matrix_Map_stride.out + * * \see class Map */ //@{ diff --git a/xs/src/eigen/Eigen/src/Core/Product.h b/xs/src/eigen/Eigen/src/Core/Product.h index ae0c94b38..676c48027 100644 --- a/xs/src/eigen/Eigen/src/Core/Product.h +++ b/xs/src/eigen/Eigen/src/Core/Product.h @@ -97,8 +97,8 @@ class Product : public ProductImpl<_Lhs,_Rhs,Option, && "if you wanted a coeff-wise or a dot product use the respective explicit functions"); } - EIGEN_DEVICE_FUNC inline Index rows() const { return m_lhs.rows(); } - EIGEN_DEVICE_FUNC inline Index cols() const { return m_rhs.cols(); } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index rows() const { return m_lhs.rows(); } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index cols() const { return m_rhs.cols(); } EIGEN_DEVICE_FUNC const LhsNestedCleaned& lhs() const { return m_lhs; } EIGEN_DEVICE_FUNC const RhsNestedCleaned& rhs() const { return m_rhs; } @@ -127,7 +127,7 @@ public: using Base::derived; typedef typename Base::Scalar Scalar; - operator const Scalar() const + EIGEN_STRONG_INLINE operator const Scalar() const { return internal::evaluator(derived()).coeff(0,0); } @@ -162,7 +162,7 @@ class ProductImpl public: - EIGEN_DEVICE_FUNC Scalar coeff(Index row, Index col) const + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index row, Index col) const { EIGEN_STATIC_ASSERT(EnableCoeff, THIS_METHOD_IS_ONLY_FOR_INNER_OR_LAZY_PRODUCTS); eigen_assert( (Option==LazyProduct) || (this->rows() == 1 && this->cols() == 1) ); @@ -170,7 +170,7 @@ class ProductImpl return internal::evaluator(derived()).coeff(row,col); } - EIGEN_DEVICE_FUNC Scalar coeff(Index i) const + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index i) const { EIGEN_STATIC_ASSERT(EnableCoeff, THIS_METHOD_IS_ONLY_FOR_INNER_OR_LAZY_PRODUCTS); eigen_assert( (Option==LazyProduct) || (this->rows() == 1 && this->cols() == 1) ); diff --git a/xs/src/eigen/Eigen/src/Core/ProductEvaluators.h b/xs/src/eigen/Eigen/src/Core/ProductEvaluators.h index 583b7f59e..9b99bd769 100644 --- a/xs/src/eigen/Eigen/src/Core/ProductEvaluators.h +++ b/xs/src/eigen/Eigen/src/Core/ProductEvaluators.h @@ -32,7 +32,7 @@ struct evaluator > typedef Product XprType; typedef product_evaluator Base; - EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) : Base(xpr) {} + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& xpr) : Base(xpr) {} }; // Catch "scalar * ( A * B )" and transform it to "(A*scalar) * B" @@ -55,7 +55,7 @@ struct evaluator, const Product > XprType; typedef evaluator > Base; - EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& xpr) : Base(xpr.lhs().functor().m_other * xpr.rhs().lhs() * xpr.rhs().rhs()) {} }; @@ -68,7 +68,7 @@ struct evaluator, DiagIndex> > typedef Diagonal, DiagIndex> XprType; typedef evaluator, DiagIndex> > Base; - EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& xpr) : Base(Diagonal, DiagIndex>( Product(xpr.nestedExpression().lhs(), xpr.nestedExpression().rhs()), xpr.index() )) @@ -207,6 +207,12 @@ struct evaluator_assume_aliasing +struct evaluator_assume_aliasing::Scalar>, const OtherXpr, + const Product >, DenseShape > { + static const bool value = true; +}; + template struct assignment_from_xpr_op_product { @@ -240,19 +246,19 @@ template struct generic_product_impl { template - static inline void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) + static EIGEN_STRONG_INLINE void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { dst.coeffRef(0,0) = (lhs.transpose().cwiseProduct(rhs)).sum(); } template - static inline void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) + static EIGEN_STRONG_INLINE void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { dst.coeffRef(0,0) += (lhs.transpose().cwiseProduct(rhs)).sum(); } template - static void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) + static EIGEN_STRONG_INLINE void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { dst.coeffRef(0,0) -= (lhs.transpose().cwiseProduct(rhs)).sum(); } }; @@ -306,25 +312,25 @@ struct generic_product_impl }; template - static inline void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) + static EIGEN_STRONG_INLINE void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { internal::outer_product_selector_run(dst, lhs, rhs, set(), is_row_major()); } template - static inline void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) + static EIGEN_STRONG_INLINE void addTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { internal::outer_product_selector_run(dst, lhs, rhs, add(), is_row_major()); } template - static inline void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) + static EIGEN_STRONG_INLINE void subTo(Dst& dst, const Lhs& lhs, const Rhs& rhs) { internal::outer_product_selector_run(dst, lhs, rhs, sub(), is_row_major()); } template - static inline void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) + static EIGEN_STRONG_INLINE void scaleAndAddTo(Dst& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) { internal::outer_product_selector_run(dst, lhs, rhs, adds(alpha), is_row_major()); } @@ -779,7 +785,11 @@ public: _Vectorizable = bool(int(MatrixFlags)&PacketAccessBit) && _SameTypes && (_ScalarAccessOnDiag || (bool(int(DiagFlags)&PacketAccessBit))), _LinearAccessMask = (MatrixType::RowsAtCompileTime==1 || MatrixType::ColsAtCompileTime==1) ? LinearAccessBit : 0, Flags = ((HereditaryBits|_LinearAccessMask) & (unsigned int)(MatrixFlags)) | (_Vectorizable ? PacketAccessBit : 0), - Alignment = evaluator::Alignment + Alignment = evaluator::Alignment, + + AsScalarProduct = (DiagonalType::SizeAtCompileTime==1) + || (DiagonalType::SizeAtCompileTime==Dynamic && MatrixType::RowsAtCompileTime==1 && ProductOrder==OnTheLeft) + || (DiagonalType::SizeAtCompileTime==Dynamic && MatrixType::ColsAtCompileTime==1 && ProductOrder==OnTheRight) }; diagonal_product_evaluator_base(const MatrixType &mat, const DiagonalType &diag) @@ -791,7 +801,10 @@ public: EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar coeff(Index idx) const { - return m_diagImpl.coeff(idx) * m_matImpl.coeff(idx); + if(AsScalarProduct) + return m_diagImpl.coeff(0) * m_matImpl.coeff(idx); + else + return m_diagImpl.coeff(idx) * m_matImpl.coeff(idx); } protected: diff --git a/xs/src/eigen/Eigen/src/Core/Redux.h b/xs/src/eigen/Eigen/src/Core/Redux.h index b6e8f8887..760e9f861 100644 --- a/xs/src/eigen/Eigen/src/Core/Redux.h +++ b/xs/src/eigen/Eigen/src/Core/Redux.h @@ -407,7 +407,7 @@ protected: */ template template -typename internal::traits::Scalar +EIGEN_STRONG_INLINE typename internal::traits::Scalar DenseBase::redux(const Func& func) const { eigen_assert(this->rows()>0 && this->cols()>0 && "you are using an empty matrix"); diff --git a/xs/src/eigen/Eigen/src/Core/Ref.h b/xs/src/eigen/Eigen/src/Core/Ref.h index bdf24f52a..9c6e3c5d9 100644 --- a/xs/src/eigen/Eigen/src/Core/Ref.h +++ b/xs/src/eigen/Eigen/src/Core/Ref.h @@ -95,6 +95,8 @@ protected: template EIGEN_DEVICE_FUNC void construct(Expression& expr) { + EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(PlainObjectType,Expression); + if(PlainObjectType::RowsAtCompileTime==1) { eigen_assert(expr.rows()==1 || expr.cols()==1); diff --git a/xs/src/eigen/Eigen/src/Core/SelfAdjointView.h b/xs/src/eigen/Eigen/src/Core/SelfAdjointView.h index 504c98f0e..b2e51f37a 100644 --- a/xs/src/eigen/Eigen/src/Core/SelfAdjointView.h +++ b/xs/src/eigen/Eigen/src/Core/SelfAdjointView.h @@ -71,7 +71,9 @@ template class SelfAdjointView EIGEN_DEVICE_FUNC explicit inline SelfAdjointView(MatrixType& matrix) : m_matrix(matrix) - {} + { + EIGEN_STATIC_ASSERT(UpLo==Lower || UpLo==Upper,SELFADJOINTVIEW_ACCEPTS_UPPER_AND_LOWER_MODE_ONLY); + } EIGEN_DEVICE_FUNC inline Index rows() const { return m_matrix.rows(); } @@ -189,7 +191,7 @@ template class SelfAdjointView TriangularView >::type(tmp2); } - typedef SelfAdjointView ConjugateReturnType; + typedef SelfAdjointView ConjugateReturnType; /** \sa MatrixBase::conjugate() const */ EIGEN_DEVICE_FUNC inline const ConjugateReturnType conjugate() const diff --git a/xs/src/eigen/Eigen/src/Core/SelfCwiseBinaryOp.h b/xs/src/eigen/Eigen/src/Core/SelfCwiseBinaryOp.h index 719ed72a5..7c89c2e23 100644 --- a/xs/src/eigen/Eigen/src/Core/SelfCwiseBinaryOp.h +++ b/xs/src/eigen/Eigen/src/Core/SelfCwiseBinaryOp.h @@ -15,33 +15,29 @@ namespace Eigen { // TODO generalize the scalar type of 'other' template -EIGEN_STRONG_INLINE Derived& DenseBase::operator*=(const Scalar& other) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::operator*=(const Scalar& other) { - typedef typename Derived::PlainObject PlainObject; internal::call_assignment(this->derived(), PlainObject::Constant(rows(),cols(),other), internal::mul_assign_op()); return derived(); } template -EIGEN_STRONG_INLINE Derived& ArrayBase::operator+=(const Scalar& other) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& ArrayBase::operator+=(const Scalar& other) { - typedef typename Derived::PlainObject PlainObject; internal::call_assignment(this->derived(), PlainObject::Constant(rows(),cols(),other), internal::add_assign_op()); return derived(); } template -EIGEN_STRONG_INLINE Derived& ArrayBase::operator-=(const Scalar& other) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& ArrayBase::operator-=(const Scalar& other) { - typedef typename Derived::PlainObject PlainObject; internal::call_assignment(this->derived(), PlainObject::Constant(rows(),cols(),other), internal::sub_assign_op()); return derived(); } template -EIGEN_STRONG_INLINE Derived& DenseBase::operator/=(const Scalar& other) +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase::operator/=(const Scalar& other) { - typedef typename Derived::PlainObject PlainObject; internal::call_assignment(this->derived(), PlainObject::Constant(rows(),cols(),other), internal::div_assign_op()); return derived(); } diff --git a/xs/src/eigen/Eigen/src/Core/Solve.h b/xs/src/eigen/Eigen/src/Core/Solve.h index 960a58597..a8daea511 100644 --- a/xs/src/eigen/Eigen/src/Core/Solve.h +++ b/xs/src/eigen/Eigen/src/Core/Solve.h @@ -34,12 +34,12 @@ template struct s template struct solve_traits { - typedef Matrix PlainObject; + RhsType::MaxColsAtCompileTime>::type PlainObject; }; template diff --git a/xs/src/eigen/Eigen/src/Core/StableNorm.h b/xs/src/eigen/Eigen/src/Core/StableNorm.h index d2fe1e199..88c8d9890 100644 --- a/xs/src/eigen/Eigen/src/Core/StableNorm.h +++ b/xs/src/eigen/Eigen/src/Core/StableNorm.h @@ -165,12 +165,13 @@ MatrixBase::stableNorm() const typedef typename internal::nested_eval::type DerivedCopy; typedef typename internal::remove_all::type DerivedCopyClean; - DerivedCopy copy(derived()); + const DerivedCopy copy(derived()); enum { CanAlign = ( (int(DerivedCopyClean::Flags)&DirectAccessBit) || (int(internal::evaluator::Alignment)>0) // FIXME Alignment)>0 might not be enough - ) && (blockSize*sizeof(Scalar)*20) // if we cannot allocate on the stack, then let's not bother about this optimization }; typedef typename internal::conditional, internal::evaluator::Alignment>, typename DerivedCopyClean::ConstSegmentReturnType>::type SegmentWrapper; diff --git a/xs/src/eigen/Eigen/src/Core/Transpositions.h b/xs/src/eigen/Eigen/src/Core/Transpositions.h index 19c17bb4a..86da5af59 100644 --- a/xs/src/eigen/Eigen/src/Core/Transpositions.h +++ b/xs/src/eigen/Eigen/src/Core/Transpositions.h @@ -384,7 +384,7 @@ class Transpose > const Product operator*(const MatrixBase& matrix, const Transpose& trt) { - return Product(matrix.derived(), trt.derived()); + return Product(matrix.derived(), trt); } /** \returns the \a matrix with the inverse transpositions applied to the rows. diff --git a/xs/src/eigen/Eigen/src/Core/arch/AVX/Complex.h b/xs/src/eigen/Eigen/src/Core/arch/AVX/Complex.h index 99439c8aa..7fa61969d 100644 --- a/xs/src/eigen/Eigen/src/Core/arch/AVX/Complex.h +++ b/xs/src/eigen/Eigen/src/Core/arch/AVX/Complex.h @@ -204,23 +204,7 @@ template<> struct conj_helper } }; -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet4cf pmadd(const Packet8f& x, const Packet4cf& y, const Packet4cf& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet4cf pmul(const Packet8f& x, const Packet4cf& y) const - { return Packet4cf(Eigen::internal::pmul(x, y.v)); } -}; - -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet4cf pmadd(const Packet4cf& x, const Packet8f& y, const Packet4cf& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet4cf pmul(const Packet4cf& x, const Packet8f& y) const - { return Packet4cf(Eigen::internal::pmul(x.v, y)); } -}; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet4cf,Packet8f) template<> EIGEN_STRONG_INLINE Packet4cf pdiv(const Packet4cf& a, const Packet4cf& b) { @@ -400,23 +384,7 @@ template<> struct conj_helper } }; -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet2cd pmadd(const Packet4d& x, const Packet2cd& y, const Packet2cd& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet2cd pmul(const Packet4d& x, const Packet2cd& y) const - { return Packet2cd(Eigen::internal::pmul(x, y.v)); } -}; - -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet2cd pmadd(const Packet2cd& x, const Packet4d& y, const Packet2cd& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet2cd pmul(const Packet2cd& x, const Packet4d& y) const - { return Packet2cd(Eigen::internal::pmul(x.v, y)); } -}; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cd,Packet4d) template<> EIGEN_STRONG_INLINE Packet2cd pdiv(const Packet2cd& a, const Packet2cd& b) { diff --git a/xs/src/eigen/Eigen/src/Core/arch/AVX/PacketMath.h b/xs/src/eigen/Eigen/src/Core/arch/AVX/PacketMath.h index 195d40fb4..61c3dfcab 100644 --- a/xs/src/eigen/Eigen/src/Core/arch/AVX/PacketMath.h +++ b/xs/src/eigen/Eigen/src/Core/arch/AVX/PacketMath.h @@ -308,9 +308,9 @@ template<> EIGEN_STRONG_INLINE void pstore1(int* to, const int& a) } #ifndef EIGEN_VECTORIZE_AVX512 -template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } #endif template<> EIGEN_STRONG_INLINE float pfirst(const Packet8f& a) { @@ -333,9 +333,12 @@ template<> EIGEN_STRONG_INLINE Packet4d preverse(const Packet4d& a) { __m256d tmp = _mm256_shuffle_pd(a,a,5); return _mm256_permute2f128_pd(tmp, tmp, 1); - + #if 0 + // This version is unlikely to be faster as _mm256_shuffle_ps and _mm256_permute_pd + // exhibit the same latency/throughput, but it is here for future reference/benchmarking... __m256d swap_halves = _mm256_permute2f128_pd(a,a,1); return _mm256_permute_pd(swap_halves,5); + #endif } // pabs should be ok diff --git a/xs/src/eigen/Eigen/src/Core/arch/AVX512/MathFunctions.h b/xs/src/eigen/Eigen/src/Core/arch/AVX512/MathFunctions.h index 399be0ee4..9c1717f76 100644 --- a/xs/src/eigen/Eigen/src/Core/arch/AVX512/MathFunctions.h +++ b/xs/src/eigen/Eigen/src/Core/arch/AVX512/MathFunctions.h @@ -88,9 +88,9 @@ plog(const Packet16f& _x) { // x = x + x - 1.0; // } else { x = x - 1.0; } __mmask16 mask = _mm512_cmp_ps_mask(x, p16f_cephes_SQRTHF, _CMP_LT_OQ); - Packet16f tmp = _mm512_mask_blend_ps(mask, x, _mm512_setzero_ps()); + Packet16f tmp = _mm512_mask_blend_ps(mask, _mm512_setzero_ps(), x); x = psub(x, p16f_1); - e = psub(e, _mm512_mask_blend_ps(mask, p16f_1, _mm512_setzero_ps())); + e = psub(e, _mm512_mask_blend_ps(mask, _mm512_setzero_ps(), p16f_1)); x = padd(x, tmp); Packet16f x2 = pmul(x, x); @@ -119,8 +119,9 @@ plog(const Packet16f& _x) { x = padd(x, y2); // Filter out invalid inputs, i.e. negative arg will be NAN, 0 will be -INF. - return _mm512_mask_blend_ps(iszero_mask, p16f_minus_inf, - _mm512_mask_blend_ps(invalid_mask, p16f_nan, x)); + return _mm512_mask_blend_ps(iszero_mask, + _mm512_mask_blend_ps(invalid_mask, x, p16f_nan), + p16f_minus_inf); } #endif @@ -266,8 +267,7 @@ psqrt(const Packet16f& _x) { // select only the inverse sqrt of positive normal inputs (denormals are // flushed to zero and cause infs as well). __mmask16 non_zero_mask = _mm512_cmp_ps_mask(_x, p16f_flt_min, _CMP_GE_OQ); - Packet16f x = _mm512_mask_blend_ps(non_zero_mask, _mm512_rsqrt14_ps(_x), - _mm512_setzero_ps()); + Packet16f x = _mm512_mask_blend_ps(non_zero_mask, _mm512_setzero_ps(), _mm512_rsqrt14_ps(_x)); // Do a single step of Newton's iteration. x = pmul(x, pmadd(neg_half, pmul(x, x), p16f_one_point_five)); @@ -289,8 +289,7 @@ psqrt(const Packet8d& _x) { // select only the inverse sqrt of positive normal inputs (denormals are // flushed to zero and cause infs as well). __mmask8 non_zero_mask = _mm512_cmp_pd_mask(_x, p8d_dbl_min, _CMP_GE_OQ); - Packet8d x = _mm512_mask_blend_pd(non_zero_mask, _mm512_rsqrt14_pd(_x), - _mm512_setzero_pd()); + Packet8d x = _mm512_mask_blend_pd(non_zero_mask, _mm512_setzero_pd(), _mm512_rsqrt14_pd(_x)); // Do a first step of Newton's iteration. x = pmul(x, pmadd(neg_half, pmul(x, x), p8d_one_point_five)); @@ -333,20 +332,18 @@ prsqrt(const Packet16f& _x) { // select only the inverse sqrt of positive normal inputs (denormals are // flushed to zero and cause infs as well). __mmask16 le_zero_mask = _mm512_cmp_ps_mask(_x, p16f_flt_min, _CMP_LT_OQ); - Packet16f x = _mm512_mask_blend_ps(le_zero_mask, _mm512_setzero_ps(), - _mm512_rsqrt14_ps(_x)); + Packet16f x = _mm512_mask_blend_ps(le_zero_mask, _mm512_rsqrt14_ps(_x), _mm512_setzero_ps()); // Fill in NaNs and Infs for the negative/zero entries. __mmask16 neg_mask = _mm512_cmp_ps_mask(_x, _mm512_setzero_ps(), _CMP_LT_OQ); Packet16f infs_and_nans = _mm512_mask_blend_ps( - neg_mask, p16f_nan, - _mm512_mask_blend_ps(le_zero_mask, p16f_inf, _mm512_setzero_ps())); + neg_mask, _mm512_mask_blend_ps(le_zero_mask, _mm512_setzero_ps(), p16f_inf), p16f_nan); // Do a single step of Newton's iteration. x = pmul(x, pmadd(neg_half, pmul(x, x), p16f_one_point_five)); // Insert NaNs and Infs in all the right places. - return _mm512_mask_blend_ps(le_zero_mask, infs_and_nans, x); + return _mm512_mask_blend_ps(le_zero_mask, x, infs_and_nans); } template <> @@ -363,14 +360,12 @@ prsqrt(const Packet8d& _x) { // select only the inverse sqrt of positive normal inputs (denormals are // flushed to zero and cause infs as well). __mmask8 le_zero_mask = _mm512_cmp_pd_mask(_x, p8d_dbl_min, _CMP_LT_OQ); - Packet8d x = _mm512_mask_blend_pd(le_zero_mask, _mm512_setzero_pd(), - _mm512_rsqrt14_pd(_x)); + Packet8d x = _mm512_mask_blend_pd(le_zero_mask, _mm512_rsqrt14_pd(_x), _mm512_setzero_pd()); // Fill in NaNs and Infs for the negative/zero entries. __mmask8 neg_mask = _mm512_cmp_pd_mask(_x, _mm512_setzero_pd(), _CMP_LT_OQ); Packet8d infs_and_nans = _mm512_mask_blend_pd( - neg_mask, p8d_nan, - _mm512_mask_blend_pd(le_zero_mask, p8d_inf, _mm512_setzero_pd())); + neg_mask, _mm512_mask_blend_pd(le_zero_mask, _mm512_setzero_pd(), p8d_inf), p8d_nan); // Do a first step of Newton's iteration. x = pmul(x, pmadd(neg_half, pmul(x, x), p8d_one_point_five)); @@ -379,9 +374,9 @@ prsqrt(const Packet8d& _x) { x = pmul(x, pmadd(neg_half, pmul(x, x), p8d_one_point_five)); // Insert NaNs and Infs in all the right places. - return _mm512_mask_blend_pd(le_zero_mask, infs_and_nans, x); + return _mm512_mask_blend_pd(le_zero_mask, x, infs_and_nans); } -#else +#elif defined(EIGEN_VECTORIZE_AVX512ER) template <> EIGEN_STRONG_INLINE Packet16f prsqrt(const Packet16f& x) { return _mm512_rsqrt28_ps(x); diff --git a/xs/src/eigen/Eigen/src/Core/arch/AVX512/PacketMath.h b/xs/src/eigen/Eigen/src/Core/arch/AVX512/PacketMath.h index f6500a16e..89705248a 100644 --- a/xs/src/eigen/Eigen/src/Core/arch/AVX512/PacketMath.h +++ b/xs/src/eigen/Eigen/src/Core/arch/AVX512/PacketMath.h @@ -618,9 +618,9 @@ EIGEN_STRONG_INLINE void pstore1(int* to, const int& a) { pstore(to, pa); } -template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } template <> EIGEN_STRONG_INLINE float pfirst(const Packet16f& a) { diff --git a/xs/src/eigen/Eigen/src/Core/arch/AltiVec/Complex.h b/xs/src/eigen/Eigen/src/Core/arch/AltiVec/Complex.h index 67db2f8ee..3e665730c 100644 --- a/xs/src/eigen/Eigen/src/Core/arch/AltiVec/Complex.h +++ b/xs/src/eigen/Eigen/src/Core/arch/AltiVec/Complex.h @@ -224,23 +224,7 @@ template<> struct conj_helper } }; -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet4f& x, const Packet2cf& y, const Packet2cf& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet2cf pmul(const Packet4f& x, const Packet2cf& y) const - { return Packet2cf(internal::pmul(x, y.v)); } -}; - -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet4f& y, const Packet2cf& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& x, const Packet4f& y) const - { return Packet2cf(internal::pmul(x.v, y)); } -}; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf,Packet4f) template<> EIGEN_STRONG_INLINE Packet2cf pdiv(const Packet2cf& a, const Packet2cf& b) { @@ -416,23 +400,8 @@ template<> struct conj_helper return pconj(internal::pmul(a, b)); } }; -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet2d& x, const Packet1cd& y, const Packet1cd& c) const - { return padd(c, pmul(x,y)); } - EIGEN_STRONG_INLINE Packet1cd pmul(const Packet2d& x, const Packet1cd& y) const - { return Packet1cd(internal::pmul(x, y.v)); } -}; - -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet2d& y, const Packet1cd& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& x, const Packet2d& y) const - { return Packet1cd(internal::pmul(x.v, y)); } -}; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd,Packet2d) template<> EIGEN_STRONG_INLINE Packet1cd pdiv(const Packet1cd& a, const Packet1cd& b) { diff --git a/xs/src/eigen/Eigen/src/Core/arch/AltiVec/PacketMath.h b/xs/src/eigen/Eigen/src/Core/arch/AltiVec/PacketMath.h index b3f1ea199..08a27d153 100644 --- a/xs/src/eigen/Eigen/src/Core/arch/AltiVec/PacketMath.h +++ b/xs/src/eigen/Eigen/src/Core/arch/AltiVec/PacketMath.h @@ -103,7 +103,7 @@ static Packet16uc p16uc_PSET32_WODD = vec_sld((Packet16uc) vec_splat((Packet4u static Packet16uc p16uc_PSET32_WEVEN = vec_sld(p16uc_DUPLICATE32_HI, (Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 3), 8);//{ 4,5,6,7, 4,5,6,7, 12,13,14,15, 12,13,14,15 }; static Packet16uc p16uc_HALF64_0_16 = vec_sld((Packet16uc)p4i_ZERO, vec_splat((Packet16uc) vec_abs(p4i_MINUS16), 3), 8); //{ 0,0,0,0, 0,0,0,0, 16,16,16,16, 16,16,16,16}; #else -static Packet16uc p16uc_FORWARD = p16uc_REVERSE32; +static Packet16uc p16uc_FORWARD = p16uc_REVERSE32; static Packet16uc p16uc_REVERSE64 = { 8,9,10,11, 12,13,14,15, 0,1,2,3, 4,5,6,7 }; static Packet16uc p16uc_PSET32_WODD = vec_sld((Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 1), (Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 3), 8);//{ 0,1,2,3, 0,1,2,3, 8,9,10,11, 8,9,10,11 }; static Packet16uc p16uc_PSET32_WEVEN = vec_sld((Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 0), (Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 2), 8);//{ 4,5,6,7, 4,5,6,7, 12,13,14,15, 12,13,14,15 }; @@ -388,10 +388,28 @@ template<> EIGEN_STRONG_INLINE Packet4i pdiv(const Packet4i& /*a*/, co template<> EIGEN_STRONG_INLINE Packet4f pmadd(const Packet4f& a, const Packet4f& b, const Packet4f& c) { return vec_madd(a,b,c); } template<> EIGEN_STRONG_INLINE Packet4i pmadd(const Packet4i& a, const Packet4i& b, const Packet4i& c) { return a*b + c; } -template<> EIGEN_STRONG_INLINE Packet4f pmin(const Packet4f& a, const Packet4f& b) { return vec_min(a, b); } +template<> EIGEN_STRONG_INLINE Packet4f pmin(const Packet4f& a, const Packet4f& b) +{ + #ifdef __VSX__ + Packet4f ret; + __asm__ ("xvcmpgesp %x0,%x1,%x2\n\txxsel %x0,%x1,%x2,%x0" : "=&wa" (ret) : "wa" (a), "wa" (b)); + return ret; + #else + return vec_min(a, b); + #endif +} template<> EIGEN_STRONG_INLINE Packet4i pmin(const Packet4i& a, const Packet4i& b) { return vec_min(a, b); } -template<> EIGEN_STRONG_INLINE Packet4f pmax(const Packet4f& a, const Packet4f& b) { return vec_max(a, b); } +template<> EIGEN_STRONG_INLINE Packet4f pmax(const Packet4f& a, const Packet4f& b) +{ + #ifdef __VSX__ + Packet4f ret; + __asm__ ("xvcmpgtsp %x0,%x2,%x1\n\txxsel %x0,%x1,%x2,%x0" : "=&wa" (ret) : "wa" (a), "wa" (b)); + return ret; + #else + return vec_max(a, b); + #endif +} template<> EIGEN_STRONG_INLINE Packet4i pmax(const Packet4i& a, const Packet4i& b) { return vec_max(a, b); } template<> EIGEN_STRONG_INLINE Packet4f pand(const Packet4f& a, const Packet4f& b) { return vec_and(a, b); } @@ -764,7 +782,7 @@ typedef __vector __bool long Packet2bl; static Packet2l p2l_ONE = { 1, 1 }; static Packet2l p2l_ZERO = reinterpret_cast(p4i_ZERO); -static Packet2d p2d_ONE = { 1.0, 1.0 }; +static Packet2d p2d_ONE = { 1.0, 1.0 }; static Packet2d p2d_ZERO = reinterpret_cast(p4f_ZERO); static Packet2d p2d_MZERO = { -0.0, -0.0 }; @@ -910,9 +928,19 @@ template<> EIGEN_STRONG_INLINE Packet2d pdiv(const Packet2d& a, const // for some weird raisons, it has to be overloaded for packet of integers template<> EIGEN_STRONG_INLINE Packet2d pmadd(const Packet2d& a, const Packet2d& b, const Packet2d& c) { return vec_madd(a, b, c); } -template<> EIGEN_STRONG_INLINE Packet2d pmin(const Packet2d& a, const Packet2d& b) { return vec_min(a, b); } +template<> EIGEN_STRONG_INLINE Packet2d pmin(const Packet2d& a, const Packet2d& b) +{ + Packet2d ret; + __asm__ ("xvcmpgedp %x0,%x1,%x2\n\txxsel %x0,%x1,%x2,%x0" : "=&wa" (ret) : "wa" (a), "wa" (b)); + return ret; + } -template<> EIGEN_STRONG_INLINE Packet2d pmax(const Packet2d& a, const Packet2d& b) { return vec_max(a, b); } +template<> EIGEN_STRONG_INLINE Packet2d pmax(const Packet2d& a, const Packet2d& b) +{ + Packet2d ret; + __asm__ ("xvcmpgtdp %x0,%x2,%x1\n\txxsel %x0,%x1,%x2,%x0" : "=&wa" (ret) : "wa" (a), "wa" (b)); + return ret; +} template<> EIGEN_STRONG_INLINE Packet2d pand(const Packet2d& a, const Packet2d& b) { return vec_and(a, b); } @@ -969,7 +997,7 @@ template<> EIGEN_STRONG_INLINE Packet2d preduxp(const Packet2d* vecs) Packet2d v[2], sum; v[0] = vecs[0] + reinterpret_cast(vec_sld(reinterpret_cast(vecs[0]), reinterpret_cast(vecs[0]), 8)); v[1] = vecs[1] + reinterpret_cast(vec_sld(reinterpret_cast(vecs[1]), reinterpret_cast(vecs[1]), 8)); - + #ifdef _BIG_ENDIAN sum = reinterpret_cast(vec_sld(reinterpret_cast(v[0]), reinterpret_cast(v[1]), 8)); #else @@ -1022,7 +1050,7 @@ ptranspose(PacketBlock& kernel) { template<> EIGEN_STRONG_INLINE Packet2d pblend(const Selector<2>& ifPacket, const Packet2d& thenPacket, const Packet2d& elsePacket) { Packet2l select = { ifPacket.select[0], ifPacket.select[1] }; - Packet2bl mask = vec_cmpeq(reinterpret_cast(select), reinterpret_cast(p2l_ONE)); + Packet2bl mask = reinterpret_cast( vec_cmpeq(reinterpret_cast(select), reinterpret_cast(p2l_ONE)) ); return vec_sel(elsePacket, thenPacket, mask); } #endif // __VSX__ diff --git a/xs/src/eigen/Eigen/src/Core/arch/CUDA/Half.h b/xs/src/eigen/Eigen/src/Core/arch/CUDA/Half.h index 52892db38..02ac0c23a 100644 --- a/xs/src/eigen/Eigen/src/Core/arch/CUDA/Half.h +++ b/xs/src/eigen/Eigen/src/Core/arch/CUDA/Half.h @@ -13,7 +13,7 @@ // Redistribution and use in source and binary forms, with or without // modification, are permitted. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, @@ -147,55 +147,55 @@ namespace half_impl { // versions to get the ALU speed increased), but you do save the // conversion steps back and forth. -__device__ half operator + (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half operator + (const half& a, const half& b) { return __hadd(a, b); } -__device__ half operator * (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half operator * (const half& a, const half& b) { return __hmul(a, b); } -__device__ half operator - (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half operator - (const half& a, const half& b) { return __hsub(a, b); } -__device__ half operator / (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half operator / (const half& a, const half& b) { float num = __half2float(a); float denom = __half2float(b); return __float2half(num / denom); } -__device__ half operator - (const half& a) { +EIGEN_STRONG_INLINE __device__ half operator - (const half& a) { return __hneg(a); } -__device__ half& operator += (half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half& operator += (half& a, const half& b) { a = a + b; return a; } -__device__ half& operator *= (half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half& operator *= (half& a, const half& b) { a = a * b; return a; } -__device__ half& operator -= (half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half& operator -= (half& a, const half& b) { a = a - b; return a; } -__device__ half& operator /= (half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ half& operator /= (half& a, const half& b) { a = a / b; return a; } -__device__ bool operator == (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ bool operator == (const half& a, const half& b) { return __heq(a, b); } -__device__ bool operator != (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ bool operator != (const half& a, const half& b) { return __hne(a, b); } -__device__ bool operator < (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ bool operator < (const half& a, const half& b) { return __hlt(a, b); } -__device__ bool operator <= (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ bool operator <= (const half& a, const half& b) { return __hle(a, b); } -__device__ bool operator > (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ bool operator > (const half& a, const half& b) { return __hgt(a, b); } -__device__ bool operator >= (const half& a, const half& b) { +EIGEN_STRONG_INLINE __device__ bool operator >= (const half& a, const half& b) { return __hge(a, b); } @@ -238,10 +238,10 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half& operator /= (half& a, const half& b) return a; } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool operator == (const half& a, const half& b) { - return float(a) == float(b); + return numext::equal_strict(float(a),float(b)); } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool operator != (const half& a, const half& b) { - return float(a) != float(b); + return numext::not_equal_strict(float(a), float(b)); } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool operator < (const half& a, const half& b) { return float(a) < float(b); @@ -386,11 +386,15 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half abs(const half& a) { return result; } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half exp(const half& a) { - return half(::expf(float(a))); +#if EIGEN_CUDACC_VER >= 80000 && defined EIGEN_CUDA_ARCH && EIGEN_CUDA_ARCH >= 530 + return half(hexp(a)); +#else + return half(::expf(float(a))); +#endif } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half log(const half& a) { -#if defined(EIGEN_HAS_CUDA_FP16) && defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000 && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530 - return Eigen::half(::hlog(a)); +#if defined(EIGEN_HAS_CUDA_FP16) && EIGEN_CUDACC_VER >= 80000 && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 530 + return half(::hlog(a)); #else return half(::logf(float(a))); #endif @@ -402,7 +406,11 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half log10(const half& a) { return half(::log10f(float(a))); } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half sqrt(const half& a) { - return half(::sqrtf(float(a))); +#if EIGEN_CUDACC_VER >= 80000 && defined EIGEN_CUDA_ARCH && EIGEN_CUDA_ARCH >= 530 + return half(hsqrt(a)); +#else + return half(::sqrtf(float(a))); +#endif } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half pow(const half& a, const half& b) { return half(::powf(float(a), float(b))); @@ -420,10 +428,18 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half tanh(const half& a) { return half(::tanhf(float(a))); } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half floor(const half& a) { +#if EIGEN_CUDACC_VER >= 80000 && defined EIGEN_CUDA_ARCH && EIGEN_CUDA_ARCH >= 300 + return half(hfloor(a)); +#else return half(::floorf(float(a))); +#endif } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half ceil(const half& a) { +#if EIGEN_CUDACC_VER >= 80000 && defined EIGEN_CUDA_ARCH && EIGEN_CUDA_ARCH >= 300 + return half(hceil(a)); +#else return half(::ceilf(float(a))); +#endif } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half (min)(const half& a, const half& b) { @@ -474,9 +490,59 @@ template<> struct is_arithmetic { enum { value = true }; }; } // end namespace internal +} // end namespace Eigen + +namespace std { +template<> +struct numeric_limits { + static const bool is_specialized = true; + static const bool is_signed = true; + static const bool is_integer = false; + static const bool is_exact = false; + static const bool has_infinity = true; + static const bool has_quiet_NaN = true; + static const bool has_signaling_NaN = true; + static const float_denorm_style has_denorm = denorm_present; + static const bool has_denorm_loss = false; + static const std::float_round_style round_style = std::round_to_nearest; + static const bool is_iec559 = false; + static const bool is_bounded = false; + static const bool is_modulo = false; + static const int digits = 11; + static const int digits10 = 3; // according to http://half.sourceforge.net/structstd_1_1numeric__limits_3_01half__float_1_1half_01_4.html + static const int max_digits10 = 5; // according to http://half.sourceforge.net/structstd_1_1numeric__limits_3_01half__float_1_1half_01_4.html + static const int radix = 2; + static const int min_exponent = -13; + static const int min_exponent10 = -4; + static const int max_exponent = 16; + static const int max_exponent10 = 4; + static const bool traps = true; + static const bool tinyness_before = false; + + static Eigen::half (min)() { return Eigen::half_impl::raw_uint16_to_half(0x400); } + static Eigen::half lowest() { return Eigen::half_impl::raw_uint16_to_half(0xfbff); } + static Eigen::half (max)() { return Eigen::half_impl::raw_uint16_to_half(0x7bff); } + static Eigen::half epsilon() { return Eigen::half_impl::raw_uint16_to_half(0x0800); } + static Eigen::half round_error() { return Eigen::half(0.5); } + static Eigen::half infinity() { return Eigen::half_impl::raw_uint16_to_half(0x7c00); } + static Eigen::half quiet_NaN() { return Eigen::half_impl::raw_uint16_to_half(0x7e00); } + static Eigen::half signaling_NaN() { return Eigen::half_impl::raw_uint16_to_half(0x7e00); } + static Eigen::half denorm_min() { return Eigen::half_impl::raw_uint16_to_half(0x1); } +}; +} + +namespace Eigen { + template<> struct NumTraits : GenericNumTraits { + enum { + IsSigned = true, + IsInteger = false, + IsComplex = false, + RequireInitialization = false + }; + EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Eigen::half epsilon() { return half_impl::raw_uint16_to_half(0x0800); } @@ -507,7 +573,7 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half exph(const Eigen::half& a) { return Eigen::half(::expf(float(a))); } EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half logh(const Eigen::half& a) { -#if defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000 && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530 +#if EIGEN_CUDACC_VER >= 80000 && defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 530 return Eigen::half(::hlog(a)); #else return Eigen::half(::logf(float(a))); diff --git a/xs/src/eigen/Eigen/src/Core/arch/CUDA/PacketMath.h b/xs/src/eigen/Eigen/src/Core/arch/CUDA/PacketMath.h index ad66399e0..4dda63188 100644 --- a/xs/src/eigen/Eigen/src/Core/arch/CUDA/PacketMath.h +++ b/xs/src/eigen/Eigen/src/Core/arch/CUDA/PacketMath.h @@ -291,7 +291,7 @@ template<> EIGEN_DEVICE_FUNC inline double2 pabs(const double2& a) { EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock& kernel) { - double tmp = kernel.packet[0].y; + float tmp = kernel.packet[0].y; kernel.packet[0].y = kernel.packet[1].x; kernel.packet[1].x = tmp; diff --git a/xs/src/eigen/Eigen/src/Core/arch/CUDA/PacketMathHalf.h b/xs/src/eigen/Eigen/src/Core/arch/CUDA/PacketMathHalf.h index ae54225f8..943e0b06d 100644 --- a/xs/src/eigen/Eigen/src/Core/arch/CUDA/PacketMathHalf.h +++ b/xs/src/eigen/Eigen/src/Core/arch/CUDA/PacketMathHalf.h @@ -275,7 +275,7 @@ template<> __device__ EIGEN_STRONG_INLINE half2 plog1p(const half2& a) { return __floats2half2_rn(r1, r2); } -#if defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000 && defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 530 +#if EIGEN_CUDACC_VER >= 80000 && defined EIGEN_CUDA_ARCH && EIGEN_CUDA_ARCH >= 530 template<> __device__ EIGEN_STRONG_INLINE half2 plog(const half2& a) { diff --git a/xs/src/eigen/Eigen/src/Core/arch/Default/ConjHelper.h b/xs/src/eigen/Eigen/src/Core/arch/Default/ConjHelper.h new file mode 100644 index 000000000..4cfe34e05 --- /dev/null +++ b/xs/src/eigen/Eigen/src/Core/arch/Default/ConjHelper.h @@ -0,0 +1,29 @@ + +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2017 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_ARCH_CONJ_HELPER_H +#define EIGEN_ARCH_CONJ_HELPER_H + +#define EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(PACKET_CPLX, PACKET_REAL) \ + template<> struct conj_helper { \ + EIGEN_STRONG_INLINE PACKET_CPLX pmadd(const PACKET_REAL& x, const PACKET_CPLX& y, const PACKET_CPLX& c) const \ + { return padd(c, pmul(x,y)); } \ + EIGEN_STRONG_INLINE PACKET_CPLX pmul(const PACKET_REAL& x, const PACKET_CPLX& y) const \ + { return PACKET_CPLX(Eigen::internal::pmul(x, y.v)); } \ + }; \ + \ + template<> struct conj_helper { \ + EIGEN_STRONG_INLINE PACKET_CPLX pmadd(const PACKET_CPLX& x, const PACKET_REAL& y, const PACKET_CPLX& c) const \ + { return padd(c, pmul(x,y)); } \ + EIGEN_STRONG_INLINE PACKET_CPLX pmul(const PACKET_CPLX& x, const PACKET_REAL& y) const \ + { return PACKET_CPLX(Eigen::internal::pmul(x.v, y)); } \ + }; + +#endif // EIGEN_ARCH_CONJ_HELPER_H diff --git a/xs/src/eigen/Eigen/src/Core/arch/NEON/Complex.h b/xs/src/eigen/Eigen/src/Core/arch/NEON/Complex.h index 57e9b431f..306a309be 100644 --- a/xs/src/eigen/Eigen/src/Core/arch/NEON/Complex.h +++ b/xs/src/eigen/Eigen/src/Core/arch/NEON/Complex.h @@ -67,7 +67,7 @@ template<> struct unpacket_traits { typedef std::complex type; template<> EIGEN_STRONG_INLINE Packet2cf pset1(const std::complex& from) { float32x2_t r64; - r64 = vld1_f32((float *)&from); + r64 = vld1_f32((const float *)&from); return Packet2cf(vcombine_f32(r64, r64)); } @@ -142,7 +142,7 @@ template<> EIGEN_DEVICE_FUNC inline void pscatter, Packet2cf to[stride*1] = std::complex(vgetq_lane_f32(from.v, 2), vgetq_lane_f32(from.v, 3)); } -template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { EIGEN_ARM_PREFETCH((float *)addr); } +template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { EIGEN_ARM_PREFETCH((const float *)addr); } template<> EIGEN_STRONG_INLINE std::complex pfirst(const Packet2cf& a) { @@ -265,6 +265,8 @@ template<> struct conj_helper } }; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf,Packet4f) + template<> EIGEN_STRONG_INLINE Packet2cf pdiv(const Packet2cf& a, const Packet2cf& b) { // TODO optimize it for NEON @@ -275,7 +277,7 @@ template<> EIGEN_STRONG_INLINE Packet2cf pdiv(const Packet2cf& a, con s = vmulq_f32(b.v, b.v); rev_s = vrev64q_f32(s); - return Packet2cf(pdiv(res.v, vaddq_f32(s,rev_s))); + return Packet2cf(pdiv(res.v, vaddq_f32(s,rev_s))); } EIGEN_DEVICE_FUNC inline void @@ -381,7 +383,7 @@ template<> EIGEN_STRONG_INLINE Packet1cd ploaddup(const std::complex< template<> EIGEN_STRONG_INLINE void pstore >(std::complex * to, const Packet1cd& from) { EIGEN_DEBUG_ALIGNED_STORE pstore((double*)to, from.v); } template<> EIGEN_STRONG_INLINE void pstoreu >(std::complex * to, const Packet1cd& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu((double*)to, from.v); } -template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { EIGEN_ARM_PREFETCH((double *)addr); } +template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { EIGEN_ARM_PREFETCH((const double *)addr); } template<> EIGEN_DEVICE_FUNC inline Packet1cd pgather, Packet1cd>(const std::complex* from, Index stride) { @@ -456,6 +458,8 @@ template<> struct conj_helper } }; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd,Packet2d) + template<> EIGEN_STRONG_INLINE Packet1cd pdiv(const Packet1cd& a, const Packet1cd& b) { // TODO optimize it for NEON diff --git a/xs/src/eigen/Eigen/src/Core/arch/NEON/PacketMath.h b/xs/src/eigen/Eigen/src/Core/arch/NEON/PacketMath.h index 84a56bdcc..3d5ed0d24 100644 --- a/xs/src/eigen/Eigen/src/Core/arch/NEON/PacketMath.h +++ b/xs/src/eigen/Eigen/src/Core/arch/NEON/PacketMath.h @@ -36,12 +36,43 @@ namespace internal { #endif #endif +#if EIGEN_COMP_MSVC + +// In MSVC's arm_neon.h header file, all NEON vector types +// are aliases to the same underlying type __n128. +// We thus have to wrap them to make them different C++ types. +// (See also bug 1428) + +template +struct eigen_packet_wrapper +{ + operator T&() { return m_val; } + operator const T&() const { return m_val; } + eigen_packet_wrapper() {} + eigen_packet_wrapper(const T &v) : m_val(v) {} + eigen_packet_wrapper& operator=(const T &v) { + m_val = v; + return *this; + } + + T m_val; +}; +typedef eigen_packet_wrapper Packet2f; +typedef eigen_packet_wrapper Packet4f; +typedef eigen_packet_wrapper Packet4i; +typedef eigen_packet_wrapper Packet2i; +typedef eigen_packet_wrapper Packet4ui; + +#else + typedef float32x2_t Packet2f; typedef float32x4_t Packet4f; typedef int32x4_t Packet4i; typedef int32x2_t Packet2i; typedef uint32x4_t Packet4ui; +#endif // EIGEN_COMP_MSVC + #define _EIGEN_DECLARE_CONST_Packet4f(NAME,X) \ const Packet4f p4f_##NAME = pset1(X) @@ -51,14 +82,17 @@ typedef uint32x4_t Packet4ui; #define _EIGEN_DECLARE_CONST_Packet4i(NAME,X) \ const Packet4i p4i_##NAME = pset1(X) -// arm64 does have the pld instruction. If available, let's trust the __builtin_prefetch built-in function -// which available on LLVM and GCC (at least) -#if EIGEN_HAS_BUILTIN(__builtin_prefetch) || EIGEN_COMP_GNUC +#if EIGEN_ARCH_ARM64 + // __builtin_prefetch tends to do nothing on ARM64 compilers because the + // prefetch instructions there are too detailed for __builtin_prefetch to map + // meaningfully to them. + #define EIGEN_ARM_PREFETCH(ADDR) __asm__ __volatile__("prfm pldl1keep, [%[addr]]\n" ::[addr] "r"(ADDR) : ); +#elif EIGEN_HAS_BUILTIN(__builtin_prefetch) || EIGEN_COMP_GNUC #define EIGEN_ARM_PREFETCH(ADDR) __builtin_prefetch(ADDR); #elif defined __pld #define EIGEN_ARM_PREFETCH(ADDR) __pld(ADDR) -#elif !EIGEN_ARCH_ARM64 - #define EIGEN_ARM_PREFETCH(ADDR) __asm__ __volatile__ ( " pld [%[addr]]\n" :: [addr] "r" (ADDR) : "cc" ); +#elif EIGEN_ARCH_ARM32 + #define EIGEN_ARM_PREFETCH(ADDR) __asm__ __volatile__ ("pld [%[addr]]\n" :: [addr] "r" (ADDR) : ); #else // by default no explicit prefetching #define EIGEN_ARM_PREFETCH(ADDR) @@ -113,7 +147,7 @@ template<> EIGEN_STRONG_INLINE Packet4i pset1(const int32_t& from) template<> EIGEN_STRONG_INLINE Packet4f plset(const float& a) { - const float32_t f[] = {0, 1, 2, 3}; + const float f[] = {0, 1, 2, 3}; Packet4f countdown = vld1q_f32(f); return vaddq_f32(pset1(a), countdown); } diff --git a/xs/src/eigen/Eigen/src/Core/arch/SSE/Complex.h b/xs/src/eigen/Eigen/src/Core/arch/SSE/Complex.h index 5607fe0ab..d075043ce 100644 --- a/xs/src/eigen/Eigen/src/Core/arch/SSE/Complex.h +++ b/xs/src/eigen/Eigen/src/Core/arch/SSE/Complex.h @@ -128,7 +128,7 @@ template<> EIGEN_DEVICE_FUNC inline void pscatter, Packet2cf _mm_cvtss_f32(_mm_shuffle_ps(from.v, from.v, 3))); } -template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } template<> EIGEN_STRONG_INLINE std::complex pfirst(const Packet2cf& a) { @@ -229,23 +229,7 @@ template<> struct conj_helper } }; -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet4f& x, const Packet2cf& y, const Packet2cf& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet2cf pmul(const Packet4f& x, const Packet2cf& y) const - { return Packet2cf(Eigen::internal::pmul(x, y.v)); } -}; - -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet4f& y, const Packet2cf& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& x, const Packet4f& y) const - { return Packet2cf(Eigen::internal::pmul(x.v, y)); } -}; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf,Packet4f) template<> EIGEN_STRONG_INLINE Packet2cf pdiv(const Packet2cf& a, const Packet2cf& b) { @@ -340,7 +324,7 @@ template<> EIGEN_STRONG_INLINE Packet1cd ploaddup(const std::complex< template<> EIGEN_STRONG_INLINE void pstore >(std::complex * to, const Packet1cd& from) { EIGEN_DEBUG_ALIGNED_STORE pstore((double*)to, Packet2d(from.v)); } template<> EIGEN_STRONG_INLINE void pstoreu >(std::complex * to, const Packet1cd& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu((double*)to, Packet2d(from.v)); } -template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch >(const std::complex * addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } template<> EIGEN_STRONG_INLINE std::complex pfirst(const Packet1cd& a) { @@ -430,23 +414,7 @@ template<> struct conj_helper } }; -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet2d& x, const Packet1cd& y, const Packet1cd& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet1cd pmul(const Packet2d& x, const Packet1cd& y) const - { return Packet1cd(Eigen::internal::pmul(x, y.v)); } -}; - -template<> struct conj_helper -{ - EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet2d& y, const Packet1cd& c) const - { return padd(c, pmul(x,y)); } - - EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& x, const Packet2d& y) const - { return Packet1cd(Eigen::internal::pmul(x.v, y)); } -}; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd,Packet2d) template<> EIGEN_STRONG_INLINE Packet1cd pdiv(const Packet1cd& a, const Packet1cd& b) { diff --git a/xs/src/eigen/Eigen/src/Core/arch/SSE/PacketMath.h b/xs/src/eigen/Eigen/src/Core/arch/SSE/PacketMath.h index 3832de147..5e652cc79 100644 --- a/xs/src/eigen/Eigen/src/Core/arch/SSE/PacketMath.h +++ b/xs/src/eigen/Eigen/src/Core/arch/SSE/PacketMath.h @@ -409,10 +409,16 @@ template<> EIGEN_STRONG_INLINE void pstore1(double* to, const double& pstore(to, Packet2d(vec2d_swizzle1(pa,0,0))); } +#if EIGEN_COMP_PGI +typedef const void * SsePrefetchPtrType; +#else +typedef const char * SsePrefetchPtrType; +#endif + #ifndef EIGEN_VECTORIZE_AVX -template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } -template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const float* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const double* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } +template<> EIGEN_STRONG_INLINE void prefetch(const int* addr) { _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } #endif #if EIGEN_COMP_MSVC_STRICT && EIGEN_OS_WIN64 @@ -876,4 +882,14 @@ template<> EIGEN_STRONG_INLINE double pmadd(const double& a, const double& b, co } // end namespace Eigen +#if EIGEN_COMP_PGI +// PGI++ does not define the following intrinsics in C++ mode. +static inline __m128 _mm_castpd_ps (__m128d x) { return reinterpret_cast<__m128&>(x); } +static inline __m128i _mm_castpd_si128(__m128d x) { return reinterpret_cast<__m128i&>(x); } +static inline __m128d _mm_castps_pd (__m128 x) { return reinterpret_cast<__m128d&>(x); } +static inline __m128i _mm_castps_si128(__m128 x) { return reinterpret_cast<__m128i&>(x); } +static inline __m128 _mm_castsi128_ps(__m128i x) { return reinterpret_cast<__m128&>(x); } +static inline __m128d _mm_castsi128_pd(__m128i x) { return reinterpret_cast<__m128d&>(x); } +#endif + #endif // EIGEN_PACKET_MATH_SSE_H diff --git a/xs/src/eigen/Eigen/src/Core/arch/SSE/TypeCasting.h b/xs/src/eigen/Eigen/src/Core/arch/SSE/TypeCasting.h index c84893230..c6ca8c716 100644 --- a/xs/src/eigen/Eigen/src/Core/arch/SSE/TypeCasting.h +++ b/xs/src/eigen/Eigen/src/Core/arch/SSE/TypeCasting.h @@ -14,6 +14,7 @@ namespace Eigen { namespace internal { +#ifndef EIGEN_VECTORIZE_AVX template <> struct type_casting_traits { enum { @@ -23,11 +24,6 @@ struct type_casting_traits { }; }; -template<> EIGEN_STRONG_INLINE Packet4i pcast(const Packet4f& a) { - return _mm_cvttps_epi32(a); -} - - template <> struct type_casting_traits { enum { @@ -37,11 +33,6 @@ struct type_casting_traits { }; }; -template<> EIGEN_STRONG_INLINE Packet4f pcast(const Packet4i& a) { - return _mm_cvtepi32_ps(a); -} - - template <> struct type_casting_traits { enum { @@ -51,10 +42,6 @@ struct type_casting_traits { }; }; -template<> EIGEN_STRONG_INLINE Packet4f pcast(const Packet2d& a, const Packet2d& b) { - return _mm_shuffle_ps(_mm_cvtpd_ps(a), _mm_cvtpd_ps(b), (1 << 2) | (1 << 6)); -} - template <> struct type_casting_traits { enum { @@ -63,6 +50,19 @@ struct type_casting_traits { TgtCoeffRatio = 2 }; }; +#endif + +template<> EIGEN_STRONG_INLINE Packet4i pcast(const Packet4f& a) { + return _mm_cvttps_epi32(a); +} + +template<> EIGEN_STRONG_INLINE Packet4f pcast(const Packet4i& a) { + return _mm_cvtepi32_ps(a); +} + +template<> EIGEN_STRONG_INLINE Packet4f pcast(const Packet2d& a, const Packet2d& b) { + return _mm_shuffle_ps(_mm_cvtpd_ps(a), _mm_cvtpd_ps(b), (1 << 2) | (1 << 6)); +} template<> EIGEN_STRONG_INLINE Packet2d pcast(const Packet4f& a) { // Simply discard the second half of the input diff --git a/xs/src/eigen/Eigen/src/Core/arch/ZVector/Complex.h b/xs/src/eigen/Eigen/src/Core/arch/ZVector/Complex.h index d39d2d105..1bfb73397 100644 --- a/xs/src/eigen/Eigen/src/Core/arch/ZVector/Complex.h +++ b/xs/src/eigen/Eigen/src/Core/arch/ZVector/Complex.h @@ -336,6 +336,9 @@ template<> struct conj_helper } }; +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf,Packet4f) +EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd,Packet2d) + template<> EIGEN_STRONG_INLINE Packet1cd pdiv(const Packet1cd& a, const Packet1cd& b) { // TODO optimize it for AltiVec diff --git a/xs/src/eigen/Eigen/src/Core/functors/BinaryFunctors.h b/xs/src/eigen/Eigen/src/Core/functors/BinaryFunctors.h index 96747bac7..3eae6b8ca 100644 --- a/xs/src/eigen/Eigen/src/Core/functors/BinaryFunctors.h +++ b/xs/src/eigen/Eigen/src/Core/functors/BinaryFunctors.h @@ -255,7 +255,7 @@ struct scalar_cmp_op : binary_op_base struct scalar_hypot_op : binary_op_base { EIGEN_EMPTY_STRUCT_CTOR(scalar_hypot_op) -// typedef typename NumTraits::Real result_type; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& _x, const Scalar& _y) const + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar &x, const Scalar &y) const { - EIGEN_USING_STD_MATH(sqrt) - Scalar p, qp; - if(_x>_y) - { - p = _x; - qp = _y / p; - } - else - { - p = _y; - qp = _x / p; - } - return p * sqrt(Scalar(1) + qp*qp); + // This functor is used by hypotNorm only for which it is faster to first apply abs + // on all coefficients prior to reduction through hypot. + // This way we avoid calling abs on positive and real entries, and this also permits + // to seamlessly handle complexes. Otherwise we would have to handle both real and complexes + // through the same functor... + return internal::positive_real_hypot(x,y); } }; template diff --git a/xs/src/eigen/Eigen/src/Core/functors/NullaryFunctors.h b/xs/src/eigen/Eigen/src/Core/functors/NullaryFunctors.h index 6a30466fb..b03be0269 100644 --- a/xs/src/eigen/Eigen/src/Core/functors/NullaryFunctors.h +++ b/xs/src/eigen/Eigen/src/Core/functors/NullaryFunctors.h @@ -44,16 +44,16 @@ struct linspaced_op_impl { linspaced_op_impl(const Scalar& low, const Scalar& high, Index num_steps) : m_low(low), m_high(high), m_size1(num_steps==1 ? 1 : num_steps-1), m_step(num_steps==1 ? Scalar() : (high-low)/Scalar(num_steps-1)), - m_interPacket(plset(0)), m_flip(numext::abs(high) EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (IndexType i) const { + typedef typename NumTraits::Real RealScalar; if(m_flip) - return (i==0)? m_low : (m_high - (m_size1-i)*m_step); + return (i==0)? m_low : (m_high - RealScalar(m_size1-i)*m_step); else - return (i==m_size1)? m_high : (m_low + i*m_step); + return (i==m_size1)? m_high : (m_low + RealScalar(i)*m_step); } template @@ -63,7 +63,7 @@ struct linspaced_op_impl // [low, ..., low] + ( [step, ..., step] * ( [i, ..., i] + [0, ..., size] ) ) if(m_flip) { - Packet pi = padd(pset1(Scalar(i-m_size1)),m_interPacket); + Packet pi = plset(Scalar(i-m_size1)); Packet res = padd(pset1(m_high), pmul(pset1(m_step), pi)); if(i==0) res = pinsertfirst(res, m_low); @@ -71,7 +71,7 @@ struct linspaced_op_impl } else { - Packet pi = padd(pset1(Scalar(i)),m_interPacket); + Packet pi = plset(Scalar(i)); Packet res = padd(pset1(m_low), pmul(pset1(m_step), pi)); if(i==m_size1-unpacket_traits::size+1) res = pinsertlast(res, m_high); @@ -83,7 +83,6 @@ struct linspaced_op_impl const Scalar m_high; const Index m_size1; const Scalar m_step; - const Packet m_interPacket; const bool m_flip; }; diff --git a/xs/src/eigen/Eigen/src/Core/functors/StlFunctors.h b/xs/src/eigen/Eigen/src/Core/functors/StlFunctors.h index 6df3fa501..9c1d75850 100644 --- a/xs/src/eigen/Eigen/src/Core/functors/StlFunctors.h +++ b/xs/src/eigen/Eigen/src/Core/functors/StlFunctors.h @@ -83,13 +83,17 @@ struct functor_traits > { enum { Cost = functor_traits::Cost, PacketAccess = false }; }; #endif +#if (__cplusplus < 201703L) && (EIGEN_COMP_MSVC < 1910) +// std::unary_negate is deprecated since c++17 and will be removed in c++20 template struct functor_traits > { enum { Cost = 1 + functor_traits::Cost, PacketAccess = false }; }; +// std::binary_negate is deprecated since c++17 and will be removed in c++20 template struct functor_traits > { enum { Cost = 1 + functor_traits::Cost, PacketAccess = false }; }; +#endif #ifdef EIGEN_STDEXT_SUPPORT diff --git a/xs/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h b/xs/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h index 7122efa60..e844e37d1 100644 --- a/xs/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h +++ b/xs/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h @@ -269,10 +269,13 @@ struct general_product_to_triangular_selector enum { IsRowMajor = (internal::traits::Flags&RowMajorBit) ? 1 : 0, LhsIsRowMajor = _ActualLhs::Flags&RowMajorBit ? 1 : 0, - RhsIsRowMajor = _ActualRhs::Flags&RowMajorBit ? 1 : 0 + RhsIsRowMajor = _ActualRhs::Flags&RowMajorBit ? 1 : 0, + SkipDiag = (UpLo&(UnitDiag|ZeroDiag))!=0 }; Index size = mat.cols(); + if(SkipDiag) + size--; Index depth = actualLhs.cols(); typedef internal::gemm_blocking_space internal::general_matrix_matrix_triangular_product + IsRowMajor ? RowMajor : ColMajor, UpLo&(Lower|Upper)> ::run(size, depth, - &actualLhs.coeffRef(0,0), actualLhs.outerStride(), &actualRhs.coeffRef(0,0), actualRhs.outerStride(), - mat.data(), mat.outerStride(), actualAlpha, blocking); + &actualLhs.coeffRef(SkipDiag&&(UpLo&Lower)==Lower ? 1 : 0,0), actualLhs.outerStride(), + &actualRhs.coeffRef(0,SkipDiag&&(UpLo&Upper)==Upper ? 1 : 0), actualRhs.outerStride(), + mat.data() + (SkipDiag ? (bool(IsRowMajor) != ((UpLo&Lower)==Lower) ? 1 : mat.outerStride() ) : 0), mat.outerStride(), actualAlpha, blocking); } }; @@ -294,6 +298,7 @@ template template TriangularView& TriangularViewImpl::_assignProduct(const ProductType& prod, const Scalar& alpha, bool beta) { + EIGEN_STATIC_ASSERT((UpLo&UnitDiag)==0, WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED); eigen_assert(derived().nestedExpression().rows() == prod.rows() && derived().cols() == prod.cols()); general_product_to_triangular_selector::InnerSize==1>::run(derived().nestedExpression().const_cast_derived(), prod, alpha, beta); diff --git a/xs/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h b/xs/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h index 5b7c15cca..9176a1382 100644 --- a/xs/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h +++ b/xs/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h @@ -52,7 +52,7 @@ struct general_matrix_matrix_triangular_product& blocking) \ { \ - if (lhs==rhs) { \ + if ( lhs==rhs && ((UpLo&(Lower|Upper)==UpLo)) ) { \ general_matrix_matrix_rankupdate \ ::run(size,depth,lhs,lhsStride,rhs,rhsStride,res,resStride,alpha,blocking); \ } else { \ @@ -88,7 +88,7 @@ struct general_matrix_matrix_rankupdate(lhsStride), ldc=convert_index(resStride), n=convert_index(size), k=convert_index(depth); \ char uplo=((IsLower) ? 'L' : 'U'), trans=((AStorageOrder==RowMajor) ? 'T':'N'); \ EIGTYPE beta(1); \ - BLASFUNC(&uplo, &trans, &n, &k, &numext::real_ref(alpha), lhs, &lda, &numext::real_ref(beta), res, &ldc); \ + BLASFUNC(&uplo, &trans, &n, &k, (const BLASTYPE*)&numext::real_ref(alpha), lhs, &lda, (const BLASTYPE*)&numext::real_ref(beta), res, &ldc); \ } \ }; @@ -125,9 +125,13 @@ struct general_matrix_matrix_rankupdate(b_tmp.outerStride()); \ } else b = _rhs; \ \ - BLASPREFIX##gemm_(&transa, &transb, &m, &n, &k, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, &numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ + BLASFUNC(&transa, &transb, &m, &n, &k, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ }}; -GEMM_SPECIALIZATION(double, d, double, d) -GEMM_SPECIALIZATION(float, f, float, s) -GEMM_SPECIALIZATION(dcomplex, cd, double, z) -GEMM_SPECIALIZATION(scomplex, cf, float, c) +#ifdef EIGEN_USE_MKL +GEMM_SPECIALIZATION(double, d, double, dgemm) +GEMM_SPECIALIZATION(float, f, float, sgemm) +GEMM_SPECIALIZATION(dcomplex, cd, MKL_Complex16, zgemm) +GEMM_SPECIALIZATION(scomplex, cf, MKL_Complex8, cgemm) +#else +GEMM_SPECIALIZATION(double, d, double, dgemm_) +GEMM_SPECIALIZATION(float, f, float, sgemm_) +GEMM_SPECIALIZATION(dcomplex, cd, double, zgemm_) +GEMM_SPECIALIZATION(scomplex, cf, float, cgemm_) +#endif } // end namespase internal diff --git a/xs/src/eigen/Eigen/src/Core/products/GeneralMatrixVector.h b/xs/src/eigen/Eigen/src/Core/products/GeneralMatrixVector.h index 3c1a7fc40..a597c1f4e 100644 --- a/xs/src/eigen/Eigen/src/Core/products/GeneralMatrixVector.h +++ b/xs/src/eigen/Eigen/src/Core/products/GeneralMatrixVector.h @@ -183,8 +183,8 @@ EIGEN_DONT_INLINE void general_matrix_vector_product \ struct general_matrix_vector_product_gemv \ { \ @@ -113,14 +113,21 @@ static void run( \ x_ptr=x_tmp.data(); \ incx=1; \ } else x_ptr=rhs; \ - BLASPREFIX##gemv_(&trans, &m, &n, &numext::real_ref(alpha), (const BLASTYPE*)lhs, &lda, (const BLASTYPE*)x_ptr, &incx, &numext::real_ref(beta), (BLASTYPE*)res, &incy); \ + BLASFUNC(&trans, &m, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)lhs, &lda, (const BLASTYPE*)x_ptr, &incx, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &incy); \ }\ }; -EIGEN_BLAS_GEMV_SPECIALIZATION(double, double, d) -EIGEN_BLAS_GEMV_SPECIALIZATION(float, float, s) -EIGEN_BLAS_GEMV_SPECIALIZATION(dcomplex, double, z) -EIGEN_BLAS_GEMV_SPECIALIZATION(scomplex, float, c) +#ifdef EIGEN_USE_MKL +EIGEN_BLAS_GEMV_SPECIALIZATION(double, double, dgemv) +EIGEN_BLAS_GEMV_SPECIALIZATION(float, float, sgemv) +EIGEN_BLAS_GEMV_SPECIALIZATION(dcomplex, MKL_Complex16, zgemv) +EIGEN_BLAS_GEMV_SPECIALIZATION(scomplex, MKL_Complex8 , cgemv) +#else +EIGEN_BLAS_GEMV_SPECIALIZATION(double, double, dgemv_) +EIGEN_BLAS_GEMV_SPECIALIZATION(float, float, sgemv_) +EIGEN_BLAS_GEMV_SPECIALIZATION(dcomplex, double, zgemv_) +EIGEN_BLAS_GEMV_SPECIALIZATION(scomplex, float, cgemv_) +#endif } // end namespase internal diff --git a/xs/src/eigen/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h b/xs/src/eigen/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h index a45238d69..9a5318507 100644 --- a/xs/src/eigen/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h +++ b/xs/src/eigen/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h @@ -40,7 +40,7 @@ namespace internal { /* Optimized selfadjoint matrix * matrix (?SYMM/?HEMM) product */ -#define EIGEN_BLAS_SYMM_L(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_SYMM_L(EIGTYPE, BLASTYPE, EIGPREFIX, BLASFUNC) \ template \ @@ -81,13 +81,13 @@ struct product_selfadjoint_matrix(b_tmp.outerStride()); \ } else b = _rhs; \ \ - BLASPREFIX##symm_(&side, &uplo, &m, &n, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, &numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ + BLASFUNC(&side, &uplo, &m, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ \ } \ }; -#define EIGEN_BLAS_HEMM_L(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_HEMM_L(EIGTYPE, BLASTYPE, EIGPREFIX, BLASFUNC) \ template \ @@ -144,20 +144,26 @@ struct product_selfadjoint_matrix(b_tmp.outerStride()); \ } \ \ - BLASPREFIX##hemm_(&side, &uplo, &m, &n, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, &numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ + BLASFUNC(&side, &uplo, &m, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ \ } \ }; -EIGEN_BLAS_SYMM_L(double, double, d, d) -EIGEN_BLAS_SYMM_L(float, float, f, s) -EIGEN_BLAS_HEMM_L(dcomplex, double, cd, z) -EIGEN_BLAS_HEMM_L(scomplex, float, cf, c) - +#ifdef EIGEN_USE_MKL +EIGEN_BLAS_SYMM_L(double, double, d, dsymm) +EIGEN_BLAS_SYMM_L(float, float, f, ssymm) +EIGEN_BLAS_HEMM_L(dcomplex, MKL_Complex16, cd, zhemm) +EIGEN_BLAS_HEMM_L(scomplex, MKL_Complex8, cf, chemm) +#else +EIGEN_BLAS_SYMM_L(double, double, d, dsymm_) +EIGEN_BLAS_SYMM_L(float, float, f, ssymm_) +EIGEN_BLAS_HEMM_L(dcomplex, double, cd, zhemm_) +EIGEN_BLAS_HEMM_L(scomplex, float, cf, chemm_) +#endif /* Optimized matrix * selfadjoint matrix (?SYMM/?HEMM) product */ -#define EIGEN_BLAS_SYMM_R(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_SYMM_R(EIGTYPE, BLASTYPE, EIGPREFIX, BLASFUNC) \ template \ @@ -197,13 +203,13 @@ struct product_selfadjoint_matrix(b_tmp.outerStride()); \ } else b = _lhs; \ \ - BLASPREFIX##symm_(&side, &uplo, &m, &n, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, &numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ + BLASFUNC(&side, &uplo, &m, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ \ } \ }; -#define EIGEN_BLAS_HEMM_R(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_HEMM_R(EIGTYPE, BLASTYPE, EIGPREFIX, BLASFUNC) \ template \ @@ -259,15 +265,21 @@ struct product_selfadjoint_matrix(b_tmp.outerStride()); \ } \ \ - BLASPREFIX##hemm_(&side, &uplo, &m, &n, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, &numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ + BLASFUNC(&side, &uplo, &m, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)b, &ldb, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &ldc); \ } \ }; -EIGEN_BLAS_SYMM_R(double, double, d, d) -EIGEN_BLAS_SYMM_R(float, float, f, s) -EIGEN_BLAS_HEMM_R(dcomplex, double, cd, z) -EIGEN_BLAS_HEMM_R(scomplex, float, cf, c) - +#ifdef EIGEN_USE_MKL +EIGEN_BLAS_SYMM_R(double, double, d, dsymm) +EIGEN_BLAS_SYMM_R(float, float, f, ssymm) +EIGEN_BLAS_HEMM_R(dcomplex, MKL_Complex16, cd, zhemm) +EIGEN_BLAS_HEMM_R(scomplex, MKL_Complex8, cf, chemm) +#else +EIGEN_BLAS_SYMM_R(double, double, d, dsymm_) +EIGEN_BLAS_SYMM_R(float, float, f, ssymm_) +EIGEN_BLAS_HEMM_R(dcomplex, double, cd, zhemm_) +EIGEN_BLAS_HEMM_R(scomplex, float, cf, chemm_) +#endif } // end namespace internal } // end namespace Eigen diff --git a/xs/src/eigen/Eigen/src/Core/products/SelfadjointMatrixVector_BLAS.h b/xs/src/eigen/Eigen/src/Core/products/SelfadjointMatrixVector_BLAS.h index 38f23accf..1238345e3 100644 --- a/xs/src/eigen/Eigen/src/Core/products/SelfadjointMatrixVector_BLAS.h +++ b/xs/src/eigen/Eigen/src/Core/products/SelfadjointMatrixVector_BLAS.h @@ -95,14 +95,21 @@ const EIGTYPE* _rhs, EIGTYPE* res, EIGTYPE alpha) \ x_tmp=map_x.conjugate(); \ x_ptr=x_tmp.data(); \ } else x_ptr=_rhs; \ - BLASFUNC(&uplo, &n, &numext::real_ref(alpha), (const BLASTYPE*)lhs, &lda, (const BLASTYPE*)x_ptr, &incx, &numext::real_ref(beta), (BLASTYPE*)res, &incy); \ + BLASFUNC(&uplo, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)lhs, &lda, (const BLASTYPE*)x_ptr, &incx, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)res, &incy); \ }\ }; +#ifdef EIGEN_USE_MKL +EIGEN_BLAS_SYMV_SPECIALIZATION(double, double, dsymv) +EIGEN_BLAS_SYMV_SPECIALIZATION(float, float, ssymv) +EIGEN_BLAS_SYMV_SPECIALIZATION(dcomplex, MKL_Complex16, zhemv) +EIGEN_BLAS_SYMV_SPECIALIZATION(scomplex, MKL_Complex8, chemv) +#else EIGEN_BLAS_SYMV_SPECIALIZATION(double, double, dsymv_) EIGEN_BLAS_SYMV_SPECIALIZATION(float, float, ssymv_) EIGEN_BLAS_SYMV_SPECIALIZATION(dcomplex, double, zhemv_) EIGEN_BLAS_SYMV_SPECIALIZATION(scomplex, float, chemv_) +#endif } // end namespace internal diff --git a/xs/src/eigen/Eigen/src/Core/products/TriangularMatrixMatrix.h b/xs/src/eigen/Eigen/src/Core/products/TriangularMatrixMatrix.h index 6ec5a8a0b..f784507e7 100644 --- a/xs/src/eigen/Eigen/src/Core/products/TriangularMatrixMatrix.h +++ b/xs/src/eigen/Eigen/src/Core/products/TriangularMatrixMatrix.h @@ -137,7 +137,13 @@ EIGEN_DONT_INLINE void product_triangular_matrix_matrix triangularBuffer((internal::constructor_without_unaligned_array_assert())); + // To work around an "error: member reference base type 'Matrix<...> + // (Eigen::internal::constructor_without_unaligned_array_assert (*)())' is + // not a structure or union" compilation error in nvcc (tested V8.0.61), + // create a dummy internal::constructor_without_unaligned_array_assert + // object to pass to the Matrix constructor. + internal::constructor_without_unaligned_array_assert a; + Matrix triangularBuffer(a); triangularBuffer.setZero(); if((Mode&ZeroDiag)==ZeroDiag) triangularBuffer.diagonal().setZero(); @@ -284,7 +290,8 @@ EIGEN_DONT_INLINE void product_triangular_matrix_matrix triangularBuffer((internal::constructor_without_unaligned_array_assert())); + internal::constructor_without_unaligned_array_assert a; + Matrix triangularBuffer(a); triangularBuffer.setZero(); if((Mode&ZeroDiag)==ZeroDiag) triangularBuffer.diagonal().setZero(); @@ -393,7 +400,9 @@ struct triangular_product_impl { template static void run(Dest& dst, const Lhs &a_lhs, const Rhs &a_rhs, const typename Dest::Scalar& alpha) { - typedef typename Dest::Scalar Scalar; + typedef typename Lhs::Scalar LhsScalar; + typedef typename Rhs::Scalar RhsScalar; + typedef typename Dest::Scalar Scalar; typedef internal::blas_traits LhsBlasTraits; typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhsType; @@ -405,8 +414,9 @@ struct triangular_product_impl typename internal::add_const_on_value_type::type lhs = LhsBlasTraits::extract(a_lhs); typename internal::add_const_on_value_type::type rhs = RhsBlasTraits::extract(a_rhs); - Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(a_lhs) - * RhsBlasTraits::extractScalarFactor(a_rhs); + LhsScalar lhs_alpha = LhsBlasTraits::extractScalarFactor(a_lhs); + RhsScalar rhs_alpha = RhsBlasTraits::extractScalarFactor(a_rhs); + Scalar actualAlpha = alpha * lhs_alpha * rhs_alpha; typedef internal::gemm_blocking_space<(Dest::Flags&RowMajorBit) ? RowMajor : ColMajor,Scalar,Scalar, Lhs::MaxRowsAtCompileTime, Rhs::MaxColsAtCompileTime, Lhs::MaxColsAtCompileTime,4> BlockingType; @@ -431,6 +441,21 @@ struct triangular_product_impl &dst.coeffRef(0,0), dst.outerStride(), // result info actualAlpha, blocking ); + + // Apply correction if the diagonal is unit and a scalar factor was nested: + if ((Mode&UnitDiag)==UnitDiag) + { + if (LhsIsTriangular && lhs_alpha!=LhsScalar(1)) + { + Index diagSize = (std::min)(lhs.rows(),lhs.cols()); + dst.topRows(diagSize) -= ((lhs_alpha-LhsScalar(1))*a_rhs).topRows(diagSize); + } + else if ((!LhsIsTriangular) && rhs_alpha!=RhsScalar(1)) + { + Index diagSize = (std::min)(rhs.rows(),rhs.cols()); + dst.leftCols(diagSize) -= (rhs_alpha-RhsScalar(1))*a_lhs.leftCols(diagSize); + } + } } }; diff --git a/xs/src/eigen/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h b/xs/src/eigen/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h index aecded6bb..a25197ab0 100644 --- a/xs/src/eigen/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h +++ b/xs/src/eigen/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h @@ -75,7 +75,7 @@ EIGEN_BLAS_TRMM_SPECIALIZE(scomplex, true) EIGEN_BLAS_TRMM_SPECIALIZE(scomplex, false) // implements col-major += alpha * op(triangular) * op(general) -#define EIGEN_BLAS_TRMM_L(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_TRMM_L(EIGTYPE, BLASTYPE, EIGPREFIX, BLASFUNC) \ template \ @@ -172,7 +172,7 @@ struct product_triangular_matrix_matrix_trmm > res_tmp(res,rows,cols,OuterStride<>(resStride)); \ @@ -180,13 +180,20 @@ struct product_triangular_matrix_matrix_trmm \ @@ -282,7 +289,7 @@ struct product_triangular_matrix_matrix_trmm > res_tmp(res,rows,cols,OuterStride<>(resStride)); \ @@ -290,11 +297,17 @@ struct product_triangular_matrix_matrix_trmm struct trmv_selector typename internal::add_const_on_value_type::type actualLhs = LhsBlasTraits::extract(lhs); typename internal::add_const_on_value_type::type actualRhs = RhsBlasTraits::extract(rhs); - ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(lhs) - * RhsBlasTraits::extractScalarFactor(rhs); + LhsScalar lhs_alpha = LhsBlasTraits::extractScalarFactor(lhs); + RhsScalar rhs_alpha = RhsBlasTraits::extractScalarFactor(rhs); + ResScalar actualAlpha = alpha * lhs_alpha * rhs_alpha; enum { // FIXME find a way to allow an inner stride on the result if packet_traits::size==1 @@ -274,6 +275,12 @@ template struct trmv_selector else dest = MappedDest(actualDestPtr, dest.size()); } + + if ( ((Mode&UnitDiag)==UnitDiag) && (lhs_alpha!=LhsScalar(1)) ) + { + Index diagSize = (std::min)(lhs.rows(),lhs.cols()); + dest.head(diagSize) -= (lhs_alpha-LhsScalar(1))*rhs.head(diagSize); + } } }; @@ -295,8 +302,9 @@ template struct trmv_selector typename add_const::type actualLhs = LhsBlasTraits::extract(lhs); typename add_const::type actualRhs = RhsBlasTraits::extract(rhs); - ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(lhs) - * RhsBlasTraits::extractScalarFactor(rhs); + LhsScalar lhs_alpha = LhsBlasTraits::extractScalarFactor(lhs); + RhsScalar rhs_alpha = RhsBlasTraits::extractScalarFactor(rhs); + ResScalar actualAlpha = alpha * lhs_alpha * rhs_alpha; enum { DirectlyUseRhs = ActualRhsTypeCleaned::InnerStrideAtCompileTime==1 @@ -326,6 +334,12 @@ template struct trmv_selector actualRhsPtr,1, dest.data(),dest.innerStride(), actualAlpha); + + if ( ((Mode&UnitDiag)==UnitDiag) && (lhs_alpha!=LhsScalar(1)) ) + { + Index diagSize = (std::min)(lhs.rows(),lhs.cols()); + dest.head(diagSize) -= (lhs_alpha-LhsScalar(1))*rhs.head(diagSize); + } } }; diff --git a/xs/src/eigen/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h b/xs/src/eigen/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h index 07bf26ce5..3d47a2b94 100644 --- a/xs/src/eigen/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h +++ b/xs/src/eigen/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h @@ -71,7 +71,7 @@ EIGEN_BLAS_TRMV_SPECIALIZE(dcomplex) EIGEN_BLAS_TRMV_SPECIALIZE(scomplex) // implements col-major: res += alpha * op(triangular) * vector -#define EIGEN_BLAS_TRMV_CM(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_TRMV_CM(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX, BLASPOSTFIX) \ template \ struct triangular_matrix_vector_product_trmv { \ enum { \ @@ -121,10 +121,10 @@ struct triangular_matrix_vector_product_trmv(size); \ n = convert_index(cols-size); \ } \ - BLASPREFIX##gemv_(&trans, &m, &n, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)x, &incx, &numext::real_ref(beta), (BLASTYPE*)y, &incy); \ + BLASPREFIX##gemv##BLASPOSTFIX(&trans, &m, &n, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)x, &incx, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)y, &incy); \ } \ } \ }; -EIGEN_BLAS_TRMV_CM(double, double, d, d) -EIGEN_BLAS_TRMV_CM(dcomplex, double, cd, z) -EIGEN_BLAS_TRMV_CM(float, float, f, s) -EIGEN_BLAS_TRMV_CM(scomplex, float, cf, c) +#ifdef EIGEN_USE_MKL +EIGEN_BLAS_TRMV_CM(double, double, d, d,) +EIGEN_BLAS_TRMV_CM(dcomplex, MKL_Complex16, cd, z,) +EIGEN_BLAS_TRMV_CM(float, float, f, s,) +EIGEN_BLAS_TRMV_CM(scomplex, MKL_Complex8, cf, c,) +#else +EIGEN_BLAS_TRMV_CM(double, double, d, d, _) +EIGEN_BLAS_TRMV_CM(dcomplex, double, cd, z, _) +EIGEN_BLAS_TRMV_CM(float, float, f, s, _) +EIGEN_BLAS_TRMV_CM(scomplex, float, cf, c, _) +#endif // implements row-major: res += alpha * op(triangular) * vector -#define EIGEN_BLAS_TRMV_RM(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX) \ +#define EIGEN_BLAS_TRMV_RM(EIGTYPE, BLASTYPE, EIGPREFIX, BLASPREFIX, BLASPOSTFIX) \ template \ struct triangular_matrix_vector_product_trmv { \ enum { \ @@ -203,10 +210,10 @@ struct triangular_matrix_vector_product_trmv(size); \ n = convert_index(cols-size); \ } \ - BLASPREFIX##gemv_(&trans, &n, &m, &numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)x, &incx, &numext::real_ref(beta), (BLASTYPE*)y, &incy); \ + BLASPREFIX##gemv##BLASPOSTFIX(&trans, &n, &m, (const BLASTYPE*)&numext::real_ref(alpha), (const BLASTYPE*)a, &lda, (const BLASTYPE*)x, &incx, (const BLASTYPE*)&numext::real_ref(beta), (BLASTYPE*)y, &incy); \ } \ } \ }; -EIGEN_BLAS_TRMV_RM(double, double, d, d) -EIGEN_BLAS_TRMV_RM(dcomplex, double, cd, z) -EIGEN_BLAS_TRMV_RM(float, float, f, s) -EIGEN_BLAS_TRMV_RM(scomplex, float, cf, c) +#ifdef EIGEN_USE_MKL +EIGEN_BLAS_TRMV_RM(double, double, d, d,) +EIGEN_BLAS_TRMV_RM(dcomplex, MKL_Complex16, cd, z,) +EIGEN_BLAS_TRMV_RM(float, float, f, s,) +EIGEN_BLAS_TRMV_RM(scomplex, MKL_Complex8, cf, c,) +#else +EIGEN_BLAS_TRMV_RM(double, double, d, d,_) +EIGEN_BLAS_TRMV_RM(dcomplex, double, cd, z,_) +EIGEN_BLAS_TRMV_RM(float, float, f, s,_) +EIGEN_BLAS_TRMV_RM(scomplex, float, cf, c,_) +#endif } // end namespase internal diff --git a/xs/src/eigen/Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h b/xs/src/eigen/Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h index 88c0fb794..f0775116a 100644 --- a/xs/src/eigen/Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h +++ b/xs/src/eigen/Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h @@ -38,7 +38,7 @@ namespace Eigen { namespace internal { // implements LeftSide op(triangular)^-1 * general -#define EIGEN_BLAS_TRSM_L(EIGTYPE, BLASTYPE, BLASPREFIX) \ +#define EIGEN_BLAS_TRSM_L(EIGTYPE, BLASTYPE, BLASFUNC) \ template \ struct triangular_solve_matrix \ { \ @@ -80,18 +80,24 @@ struct triangular_solve_matrix \ struct triangular_solve_matrix \ { \ @@ -133,16 +139,22 @@ struct triangular_solve_matrix /*Check IMKL version for compatibility: < 10.3 is not usable with Eigen*/ @@ -108,6 +109,10 @@ #endif #endif +#if defined(EIGEN_USE_BLAS) && !defined(EIGEN_USE_MKL) +#include "../../misc/blas.h" +#endif + namespace Eigen { typedef std::complex dcomplex; @@ -121,8 +126,5 @@ typedef int BlasIndex; } // end namespace Eigen -#if defined(EIGEN_USE_BLAS) -#include "../../misc/blas.h" -#endif #endif // EIGEN_MKL_SUPPORT_H diff --git a/xs/src/eigen/Eigen/src/Core/util/Macros.h b/xs/src/eigen/Eigen/src/Core/util/Macros.h index 427d3cd6b..02d21d2cd 100644 --- a/xs/src/eigen/Eigen/src/Core/util/Macros.h +++ b/xs/src/eigen/Eigen/src/Core/util/Macros.h @@ -13,7 +13,7 @@ #define EIGEN_WORLD_VERSION 3 #define EIGEN_MAJOR_VERSION 3 -#define EIGEN_MINOR_VERSION 3 +#define EIGEN_MINOR_VERSION 5 #define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \ (EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \ @@ -399,7 +399,7 @@ // Does the compiler support variadic templates? #ifndef EIGEN_HAS_VARIADIC_TEMPLATES #if EIGEN_MAX_CPP_VER>=11 && (__cplusplus > 199711L || EIGEN_COMP_MSVC >= 1900) \ - && ( !defined(__NVCC__) || !EIGEN_ARCH_ARM_OR_ARM64 || (defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000) ) + && (!defined(__NVCC__) || !EIGEN_ARCH_ARM_OR_ARM64 || (EIGEN_CUDACC_VER >= 80000) ) // ^^ Disable the use of variadic templates when compiling with versions of nvcc older than 8.0 on ARM devices: // this prevents nvcc from crashing when compiling Eigen on Tegra X1 #define EIGEN_HAS_VARIADIC_TEMPLATES 1 @@ -413,7 +413,7 @@ #ifdef __CUDACC__ // Const expressions are supported provided that c++11 is enabled and we're using either clang or nvcc 7.5 or above -#if EIGEN_MAX_CPP_VER>=14 && (__cplusplus > 199711L && defined(__CUDACC_VER__) && (EIGEN_COMP_CLANG || __CUDACC_VER__ >= 70500)) +#if EIGEN_MAX_CPP_VER>=14 && (__cplusplus > 199711L && (EIGEN_COMP_CLANG || EIGEN_CUDACC_VER >= 70500)) #define EIGEN_HAS_CONSTEXPR 1 #endif #elif EIGEN_MAX_CPP_VER>=14 && (__has_feature(cxx_relaxed_constexpr) || (defined(__cplusplus) && __cplusplus >= 201402L) || \ @@ -487,11 +487,13 @@ // EIGEN_STRONG_INLINE is a stronger version of the inline, using __forceinline on MSVC, // but it still doesn't use GCC's always_inline. This is useful in (common) situations where MSVC needs forceinline // but GCC is still doing fine with just inline. +#ifndef EIGEN_STRONG_INLINE #if EIGEN_COMP_MSVC || EIGEN_COMP_ICC #define EIGEN_STRONG_INLINE __forceinline #else #define EIGEN_STRONG_INLINE inline #endif +#endif // EIGEN_ALWAYS_INLINE is the stronget, it has the effect of making the function inline and adding every possible // attribute to maximize inlining. This should only be used when really necessary: in particular, @@ -812,7 +814,8 @@ namespace Eigen { // just an empty macro ! #define EIGEN_EMPTY -#if EIGEN_COMP_MSVC_STRICT && (EIGEN_COMP_MSVC < 1900 || defined(__CUDACC_VER__)) // for older MSVC versions, as well as 1900 && CUDA 8, using the base operator is sufficient (cf Bugs 1000, 1324) +#if EIGEN_COMP_MSVC_STRICT && (EIGEN_COMP_MSVC < 1900 || EIGEN_CUDACC_VER>0) + // for older MSVC versions, as well as 1900 && CUDA 8, using the base operator is sufficient (cf Bugs 1000, 1324) #define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \ using Base::operator =; #elif EIGEN_COMP_CLANG // workaround clang bug (see http://forum.kde.org/viewtopic.php?f=74&t=102653) @@ -986,7 +989,13 @@ namespace Eigen { # define EIGEN_NOEXCEPT # define EIGEN_NOEXCEPT_IF(x) # define EIGEN_NO_THROW throw() -# define EIGEN_EXCEPTION_SPEC(X) throw(X) +# if EIGEN_COMP_MSVC + // MSVC does not support exception specifications (warning C4290), + // and they are deprecated in c++11 anyway. +# define EIGEN_EXCEPTION_SPEC(X) throw() +# else +# define EIGEN_EXCEPTION_SPEC(X) throw(X) +# endif #endif #endif // EIGEN_MACROS_H diff --git a/xs/src/eigen/Eigen/src/Core/util/Memory.h b/xs/src/eigen/Eigen/src/Core/util/Memory.h index c634d7ea0..66cdbd8dd 100644 --- a/xs/src/eigen/Eigen/src/Core/util/Memory.h +++ b/xs/src/eigen/Eigen/src/Core/util/Memory.h @@ -70,7 +70,7 @@ inline void throw_std_bad_alloc() throw std::bad_alloc(); #else std::size_t huge = static_cast(-1); - new int[huge]; + ::operator new(huge); #endif } @@ -493,7 +493,7 @@ template struct smart_copy_helper { IntPtr size = IntPtr(end)-IntPtr(start); if(size==0) return; eigen_internal_assert(start!=0 && end!=0 && target!=0); - memcpy(target, start, size); + std::memcpy(target, start, size); } }; @@ -696,7 +696,15 @@ template void swap(scoped_array &a,scoped_array &b) /** \class aligned_allocator * \ingroup Core_Module * -* \brief STL compatible allocator to use with with 16 byte aligned types +* \brief STL compatible allocator to use with types requiring a non standrad alignment. +* +* The memory is aligned as for dynamically aligned matrix/array types such as MatrixXd. +* By default, it will thus provide at least 16 bytes alignment and more in following cases: +* - 32 bytes alignment if AVX is enabled. +* - 64 bytes alignment if AVX512 is enabled. +* +* This can be controled using the \c EIGEN_MAX_ALIGN_BYTES macro as documented +* \link TopicPreprocessorDirectivesPerformance there \endlink. * * Example: * \code diff --git a/xs/src/eigen/Eigen/src/Core/util/Meta.h b/xs/src/eigen/Eigen/src/Core/util/Meta.h index 7f6370755..1d73f05d6 100644 --- a/xs/src/eigen/Eigen/src/Core/util/Meta.h +++ b/xs/src/eigen/Eigen/src/Core/util/Meta.h @@ -485,6 +485,26 @@ T div_ceil(const T &a, const T &b) return (a+b-1) / b; } +// The aim of the following functions is to bypass -Wfloat-equal warnings +// when we really want a strict equality comparison on floating points. +template EIGEN_STRONG_INLINE +bool equal_strict(const X& x,const Y& y) { return x == y; } + +template<> EIGEN_STRONG_INLINE +bool equal_strict(const float& x,const float& y) { return std::equal_to()(x,y); } + +template<> EIGEN_STRONG_INLINE +bool equal_strict(const double& x,const double& y) { return std::equal_to()(x,y); } + +template EIGEN_STRONG_INLINE +bool not_equal_strict(const X& x,const Y& y) { return x != y; } + +template<> EIGEN_STRONG_INLINE +bool not_equal_strict(const float& x,const float& y) { return std::not_equal_to()(x,y); } + +template<> EIGEN_STRONG_INLINE +bool not_equal_strict(const double& x,const double& y) { return std::not_equal_to()(x,y); } + } // end namespace numext } // end namespace Eigen diff --git a/xs/src/eigen/Eigen/src/Core/util/StaticAssert.h b/xs/src/eigen/Eigen/src/Core/util/StaticAssert.h index 983361a45..500e47792 100644 --- a/xs/src/eigen/Eigen/src/Core/util/StaticAssert.h +++ b/xs/src/eigen/Eigen/src/Core/util/StaticAssert.h @@ -24,6 +24,7 @@ * */ +#ifndef EIGEN_STATIC_ASSERT #ifndef EIGEN_NO_STATIC_ASSERT #if EIGEN_MAX_CPP_VER>=11 && (__has_feature(cxx_static_assert) || (defined(__cplusplus) && __cplusplus >= 201103L) || (EIGEN_COMP_MSVC >= 1600)) @@ -44,64 +45,65 @@ struct static_assertion { enum { - YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX, - YOU_MIXED_VECTORS_OF_DIFFERENT_SIZES, - YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES, - THIS_METHOD_IS_ONLY_FOR_VECTORS_OF_A_SPECIFIC_SIZE, - THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE, - THIS_METHOD_IS_ONLY_FOR_OBJECTS_OF_A_SPECIFIC_SIZE, - OUT_OF_RANGE_ACCESS, - YOU_MADE_A_PROGRAMMING_MISTAKE, - EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT, - EIGEN_INTERNAL_COMPILATION_ERROR_OR_YOU_MADE_A_PROGRAMMING_MISTAKE, - YOU_CALLED_A_FIXED_SIZE_METHOD_ON_A_DYNAMIC_SIZE_MATRIX_OR_VECTOR, - YOU_CALLED_A_DYNAMIC_SIZE_METHOD_ON_A_FIXED_SIZE_MATRIX_OR_VECTOR, - UNALIGNED_LOAD_AND_STORE_OPERATIONS_UNIMPLEMENTED_ON_ALTIVEC, - THIS_FUNCTION_IS_NOT_FOR_INTEGER_NUMERIC_TYPES, - FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED, - NUMERIC_TYPE_MUST_BE_REAL, - COEFFICIENT_WRITE_ACCESS_TO_SELFADJOINT_NOT_SUPPORTED, - WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED, - THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE, - INVALID_MATRIX_PRODUCT, - INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS, - INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION, - YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY, - THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES, - THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES, - INVALID_MATRIX_TEMPLATE_PARAMETERS, - INVALID_MATRIXBASE_TEMPLATE_PARAMETERS, - BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER, - THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX, - THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE, - THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES, - YOU_ALREADY_SPECIFIED_THIS_STRIDE, - INVALID_STORAGE_ORDER_FOR_THIS_VECTOR_EXPRESSION, - THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD, - PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1, - THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS, - YOU_CANNOT_MIX_ARRAYS_AND_MATRICES, - YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION, - THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY, - YOU_ARE_TRYING_TO_USE_AN_INDEX_BASED_ACCESSOR_ON_AN_EXPRESSION_THAT_DOES_NOT_SUPPORT_THAT, - THIS_METHOD_IS_ONLY_FOR_1x1_EXPRESSIONS, - THIS_METHOD_IS_ONLY_FOR_INNER_OR_LAZY_PRODUCTS, - THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL, - THIS_METHOD_IS_ONLY_FOR_ARRAYS_NOT_MATRICES, - YOU_PASSED_A_ROW_VECTOR_BUT_A_COLUMN_VECTOR_WAS_EXPECTED, - YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED, - THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE, - THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH, - OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG, - IMPLICIT_CONVERSION_TO_SCALAR_IS_FOR_INNER_PRODUCT_ONLY, - STORAGE_LAYOUT_DOES_NOT_MATCH, - EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT__INVALID_COST_VALUE, - THIS_COEFFICIENT_ACCESSOR_TAKING_ONE_ACCESS_IS_ONLY_FOR_EXPRESSIONS_ALLOWING_LINEAR_ACCESS, - MATRIX_FREE_CONJUGATE_GRADIENT_IS_COMPATIBLE_WITH_UPPER_UNION_LOWER_MODE_ONLY, - THIS_TYPE_IS_NOT_SUPPORTED, - STORAGE_KIND_MUST_MATCH, - STORAGE_INDEX_MUST_MATCH, - CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY + YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX=1, + YOU_MIXED_VECTORS_OF_DIFFERENT_SIZES=1, + YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES=1, + THIS_METHOD_IS_ONLY_FOR_VECTORS_OF_A_SPECIFIC_SIZE=1, + THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE=1, + THIS_METHOD_IS_ONLY_FOR_OBJECTS_OF_A_SPECIFIC_SIZE=1, + OUT_OF_RANGE_ACCESS=1, + YOU_MADE_A_PROGRAMMING_MISTAKE=1, + EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT=1, + EIGEN_INTERNAL_COMPILATION_ERROR_OR_YOU_MADE_A_PROGRAMMING_MISTAKE=1, + YOU_CALLED_A_FIXED_SIZE_METHOD_ON_A_DYNAMIC_SIZE_MATRIX_OR_VECTOR=1, + YOU_CALLED_A_DYNAMIC_SIZE_METHOD_ON_A_FIXED_SIZE_MATRIX_OR_VECTOR=1, + UNALIGNED_LOAD_AND_STORE_OPERATIONS_UNIMPLEMENTED_ON_ALTIVEC=1, + THIS_FUNCTION_IS_NOT_FOR_INTEGER_NUMERIC_TYPES=1, + FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED=1, + NUMERIC_TYPE_MUST_BE_REAL=1, + COEFFICIENT_WRITE_ACCESS_TO_SELFADJOINT_NOT_SUPPORTED=1, + WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED=1, + THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE=1, + INVALID_MATRIX_PRODUCT=1, + INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS=1, + INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION=1, + YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY=1, + THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES=1, + THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES=1, + INVALID_MATRIX_TEMPLATE_PARAMETERS=1, + INVALID_MATRIXBASE_TEMPLATE_PARAMETERS=1, + BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER=1, + THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX=1, + THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE=1, + THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES=1, + YOU_ALREADY_SPECIFIED_THIS_STRIDE=1, + INVALID_STORAGE_ORDER_FOR_THIS_VECTOR_EXPRESSION=1, + THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD=1, + PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1=1, + THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS=1, + YOU_CANNOT_MIX_ARRAYS_AND_MATRICES=1, + YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION=1, + THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY=1, + YOU_ARE_TRYING_TO_USE_AN_INDEX_BASED_ACCESSOR_ON_AN_EXPRESSION_THAT_DOES_NOT_SUPPORT_THAT=1, + THIS_METHOD_IS_ONLY_FOR_1x1_EXPRESSIONS=1, + THIS_METHOD_IS_ONLY_FOR_INNER_OR_LAZY_PRODUCTS=1, + THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL=1, + THIS_METHOD_IS_ONLY_FOR_ARRAYS_NOT_MATRICES=1, + YOU_PASSED_A_ROW_VECTOR_BUT_A_COLUMN_VECTOR_WAS_EXPECTED=1, + YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED=1, + THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE=1, + THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH=1, + OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG=1, + IMPLICIT_CONVERSION_TO_SCALAR_IS_FOR_INNER_PRODUCT_ONLY=1, + STORAGE_LAYOUT_DOES_NOT_MATCH=1, + EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT__INVALID_COST_VALUE=1, + THIS_COEFFICIENT_ACCESSOR_TAKING_ONE_ACCESS_IS_ONLY_FOR_EXPRESSIONS_ALLOWING_LINEAR_ACCESS=1, + MATRIX_FREE_CONJUGATE_GRADIENT_IS_COMPATIBLE_WITH_UPPER_UNION_LOWER_MODE_ONLY=1, + THIS_TYPE_IS_NOT_SUPPORTED=1, + STORAGE_KIND_MUST_MATCH=1, + STORAGE_INDEX_MUST_MATCH=1, + CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY=1, + SELFADJOINTVIEW_ACCEPTS_UPPER_AND_LOWER_MODE_ONLY=1 }; }; @@ -131,7 +133,7 @@ #define EIGEN_STATIC_ASSERT(CONDITION,MSG) eigen_assert((CONDITION) && #MSG); #endif // EIGEN_NO_STATIC_ASSERT - +#endif // EIGEN_STATIC_ASSERT // static assertion failing if the type \a TYPE is not a vector type #define EIGEN_STATIC_ASSERT_VECTOR_ONLY(TYPE) \ diff --git a/xs/src/eigen/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h b/xs/src/eigen/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h index 36a91dffc..87d789b3f 100644 --- a/xs/src/eigen/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h +++ b/xs/src/eigen/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h @@ -311,7 +311,6 @@ GeneralizedEigenSolver::compute(const MatrixType& A, const MatrixTyp // Aliases: Map v(reinterpret_cast(m_tmp.data()), size); ComplexVectorType &cv = m_tmp; - const MatrixType &mZ = m_realQZ.matrixZ(); const MatrixType &mS = m_realQZ.matrixS(); const MatrixType &mT = m_realQZ.matrixT(); @@ -351,7 +350,7 @@ GeneralizedEigenSolver::compute(const MatrixType& A, const MatrixTyp } } } - m_eivec.col(i).real().noalias() = mZ.transpose() * v; + m_eivec.col(i).real().noalias() = m_realQZ.matrixZ().transpose() * v; m_eivec.col(i).real().normalize(); m_eivec.col(i).imag().setConstant(0); } @@ -400,7 +399,7 @@ GeneralizedEigenSolver::compute(const MatrixType& A, const MatrixTyp / (alpha*mT.coeffRef(j,j) - static_cast(beta*mS.coeffRef(j,j))); } } - m_eivec.col(i+1).noalias() = (mZ.transpose() * cv); + m_eivec.col(i+1).noalias() = (m_realQZ.matrixZ().transpose() * cv); m_eivec.col(i+1).normalize(); m_eivec.col(i) = m_eivec.col(i+1).conjugate(); } diff --git a/xs/src/eigen/Eigen/src/Eigenvalues/RealSchur.h b/xs/src/eigen/Eigen/src/Eigenvalues/RealSchur.h index f5c86041d..17ea903f5 100644 --- a/xs/src/eigen/Eigen/src/Eigenvalues/RealSchur.h +++ b/xs/src/eigen/Eigen/src/Eigenvalues/RealSchur.h @@ -303,7 +303,7 @@ RealSchur& RealSchur::computeFromHessenberg(const HessMa Scalar exshift(0); // sum of exceptional shifts Scalar norm = computeNormOfT(); - if(norm!=0) + if(norm!=Scalar(0)) { while (iu >= 0) { @@ -327,7 +327,7 @@ RealSchur& RealSchur::computeFromHessenberg(const HessMa else // No convergence yet { // The firstHouseholderVector vector has to be initialized to something to get rid of a silly GCC warning (-O1 -Wall -DNDEBUG ) - Vector3s firstHouseholderVector(0,0,0), shiftInfo; + Vector3s firstHouseholderVector = Vector3s::Zero(), shiftInfo; computeShift(iu, iter, exshift, shiftInfo); iter = iter + 1; totalIter = totalIter + 1; diff --git a/xs/src/eigen/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h b/xs/src/eigen/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h index 3891cf883..b0c947dc0 100644 --- a/xs/src/eigen/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h +++ b/xs/src/eigen/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h @@ -37,7 +37,7 @@ namespace Eigen { /** \internal Specialization for the data types supported by LAPACKe */ -#define EIGEN_LAPACKE_EIG_SELFADJ(EIGTYPE, LAPACKE_TYPE, LAPACKE_RTYPE, LAPACKE_NAME, EIGCOLROW, LAPACKE_COLROW ) \ +#define EIGEN_LAPACKE_EIG_SELFADJ_2(EIGTYPE, LAPACKE_TYPE, LAPACKE_RTYPE, LAPACKE_NAME, EIGCOLROW ) \ template<> template inline \ SelfAdjointEigenSolver >& \ SelfAdjointEigenSolver >::compute(const EigenBase& matrix, int options) \ @@ -47,7 +47,7 @@ SelfAdjointEigenSolver >::compute(c && (options&EigVecMask)!=EigVecMask \ && "invalid option parameter"); \ bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors; \ - lapack_int n = internal::convert_index(matrix.cols()), lda, matrix_order, info; \ + lapack_int n = internal::convert_index(matrix.cols()), lda, info; \ m_eivalues.resize(n,1); \ m_subdiag.resize(n-1); \ m_eivec = matrix; \ @@ -63,27 +63,24 @@ SelfAdjointEigenSolver >::compute(c } \ \ lda = internal::convert_index(m_eivec.outerStride()); \ - matrix_order=LAPACKE_COLROW; \ char jobz, uplo='L'/*, range='A'*/; \ jobz = computeEigenvectors ? 'V' : 'N'; \ \ - info = LAPACKE_##LAPACKE_NAME( matrix_order, jobz, uplo, n, (LAPACKE_TYPE*)m_eivec.data(), lda, (LAPACKE_RTYPE*)m_eivalues.data() ); \ + info = LAPACKE_##LAPACKE_NAME( LAPACK_COL_MAJOR, jobz, uplo, n, (LAPACKE_TYPE*)m_eivec.data(), lda, (LAPACKE_RTYPE*)m_eivalues.data() ); \ m_info = (info==0) ? Success : NoConvergence; \ m_isInitialized = true; \ m_eigenvectorsOk = computeEigenvectors; \ return *this; \ } +#define EIGEN_LAPACKE_EIG_SELFADJ(EIGTYPE, LAPACKE_TYPE, LAPACKE_RTYPE, LAPACKE_NAME ) \ + EIGEN_LAPACKE_EIG_SELFADJ_2(EIGTYPE, LAPACKE_TYPE, LAPACKE_RTYPE, LAPACKE_NAME, ColMajor ) \ + EIGEN_LAPACKE_EIG_SELFADJ_2(EIGTYPE, LAPACKE_TYPE, LAPACKE_RTYPE, LAPACKE_NAME, RowMajor ) -EIGEN_LAPACKE_EIG_SELFADJ(double, double, double, dsyev, ColMajor, LAPACK_COL_MAJOR) -EIGEN_LAPACKE_EIG_SELFADJ(float, float, float, ssyev, ColMajor, LAPACK_COL_MAJOR) -EIGEN_LAPACKE_EIG_SELFADJ(dcomplex, lapack_complex_double, double, zheev, ColMajor, LAPACK_COL_MAJOR) -EIGEN_LAPACKE_EIG_SELFADJ(scomplex, lapack_complex_float, float, cheev, ColMajor, LAPACK_COL_MAJOR) - -EIGEN_LAPACKE_EIG_SELFADJ(double, double, double, dsyev, RowMajor, LAPACK_ROW_MAJOR) -EIGEN_LAPACKE_EIG_SELFADJ(float, float, float, ssyev, RowMajor, LAPACK_ROW_MAJOR) -EIGEN_LAPACKE_EIG_SELFADJ(dcomplex, lapack_complex_double, double, zheev, RowMajor, LAPACK_ROW_MAJOR) -EIGEN_LAPACKE_EIG_SELFADJ(scomplex, lapack_complex_float, float, cheev, RowMajor, LAPACK_ROW_MAJOR) +EIGEN_LAPACKE_EIG_SELFADJ(double, double, double, dsyev) +EIGEN_LAPACKE_EIG_SELFADJ(float, float, float, ssyev) +EIGEN_LAPACKE_EIG_SELFADJ(dcomplex, lapack_complex_double, double, zheev) +EIGEN_LAPACKE_EIG_SELFADJ(scomplex, lapack_complex_float, float, cheev) } // end namespace Eigen diff --git a/xs/src/eigen/Eigen/src/Geometry/AngleAxis.h b/xs/src/eigen/Eigen/src/Geometry/AngleAxis.h index 0af3c1b08..83ee1be46 100644 --- a/xs/src/eigen/Eigen/src/Geometry/AngleAxis.h +++ b/xs/src/eigen/Eigen/src/Geometry/AngleAxis.h @@ -178,7 +178,7 @@ EIGEN_DEVICE_FUNC AngleAxis& AngleAxis::operator=(const Quaterni if (n != Scalar(0)) { m_angle = Scalar(2)*atan2(n, abs(q.w())); - if(q.w() < 0) + if(q.w() < Scalar(0)) n = -n; m_axis = q.vec() / n; } diff --git a/xs/src/eigen/Eigen/src/Geometry/Quaternion.h b/xs/src/eigen/Eigen/src/Geometry/Quaternion.h index f6ef1bcf6..c3fd8c3e0 100644 --- a/xs/src/eigen/Eigen/src/Geometry/Quaternion.h +++ b/xs/src/eigen/Eigen/src/Geometry/Quaternion.h @@ -43,6 +43,11 @@ class QuaternionBase : public RotationBase typedef typename internal::traits::Scalar Scalar; typedef typename NumTraits::Real RealScalar; typedef typename internal::traits::Coefficients Coefficients; + typedef typename Coefficients::CoeffReturnType CoeffReturnType; + typedef typename internal::conditional::Flags&LvalueBit), + Scalar&, CoeffReturnType>::type NonConstCoeffReturnType; + + enum { Flags = Eigen::internal::traits::Flags }; @@ -58,22 +63,22 @@ class QuaternionBase : public RotationBase /** \returns the \c x coefficient */ - EIGEN_DEVICE_FUNC inline Scalar x() const { return this->derived().coeffs().coeff(0); } + EIGEN_DEVICE_FUNC inline CoeffReturnType x() const { return this->derived().coeffs().coeff(0); } /** \returns the \c y coefficient */ - EIGEN_DEVICE_FUNC inline Scalar y() const { return this->derived().coeffs().coeff(1); } + EIGEN_DEVICE_FUNC inline CoeffReturnType y() const { return this->derived().coeffs().coeff(1); } /** \returns the \c z coefficient */ - EIGEN_DEVICE_FUNC inline Scalar z() const { return this->derived().coeffs().coeff(2); } + EIGEN_DEVICE_FUNC inline CoeffReturnType z() const { return this->derived().coeffs().coeff(2); } /** \returns the \c w coefficient */ - EIGEN_DEVICE_FUNC inline Scalar w() const { return this->derived().coeffs().coeff(3); } + EIGEN_DEVICE_FUNC inline CoeffReturnType w() const { return this->derived().coeffs().coeff(3); } - /** \returns a reference to the \c x coefficient */ - EIGEN_DEVICE_FUNC inline Scalar& x() { return this->derived().coeffs().coeffRef(0); } - /** \returns a reference to the \c y coefficient */ - EIGEN_DEVICE_FUNC inline Scalar& y() { return this->derived().coeffs().coeffRef(1); } - /** \returns a reference to the \c z coefficient */ - EIGEN_DEVICE_FUNC inline Scalar& z() { return this->derived().coeffs().coeffRef(2); } - /** \returns a reference to the \c w coefficient */ - EIGEN_DEVICE_FUNC inline Scalar& w() { return this->derived().coeffs().coeffRef(3); } + /** \returns a reference to the \c x coefficient (if Derived is a non-const lvalue) */ + EIGEN_DEVICE_FUNC inline NonConstCoeffReturnType x() { return this->derived().coeffs().x(); } + /** \returns a reference to the \c y coefficient (if Derived is a non-const lvalue) */ + EIGEN_DEVICE_FUNC inline NonConstCoeffReturnType y() { return this->derived().coeffs().y(); } + /** \returns a reference to the \c z coefficient (if Derived is a non-const lvalue) */ + EIGEN_DEVICE_FUNC inline NonConstCoeffReturnType z() { return this->derived().coeffs().z(); } + /** \returns a reference to the \c w coefficient (if Derived is a non-const lvalue) */ + EIGEN_DEVICE_FUNC inline NonConstCoeffReturnType w() { return this->derived().coeffs().w(); } /** \returns a read-only vector expression of the imaginary part (x,y,z) */ EIGEN_DEVICE_FUNC inline const VectorBlock vec() const { return coeffs().template head<3>(); } @@ -423,7 +428,7 @@ typedef Map, Aligned> QuaternionMapAlignedd; // Generic Quaternion * Quaternion product // This product can be specialized for a given architecture via the Arch template argument. namespace internal { -template struct quat_product +template struct quat_product { EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Quaternion run(const QuaternionBase& a, const QuaternionBase& b){ return Quaternion @@ -446,8 +451,7 @@ QuaternionBase::operator* (const QuaternionBase& other) c EIGEN_STATIC_ASSERT((internal::is_same::value), YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) return internal::quat_product::Scalar, - EIGEN_PLAIN_ENUM_MIN(internal::traits::Alignment, internal::traits::Alignment)>::run(*this, other); + typename internal::traits::Scalar>::run(*this, other); } /** \sa operator*(Quaternion) */ @@ -672,7 +676,7 @@ EIGEN_DEVICE_FUNC inline Quaternion::Scalar> // Generic conjugate of a Quaternion namespace internal { -template struct quat_conj +template struct quat_conj { EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Quaternion run(const QuaternionBase& q){ return Quaternion(q.w(),-q.x(),-q.y(),-q.z()); @@ -691,8 +695,7 @@ EIGEN_DEVICE_FUNC inline Quaternion::Scalar> QuaternionBase::conjugate() const { return internal::quat_conj::Scalar, - internal::traits::Alignment>::run(*this); + typename internal::traits::Scalar>::run(*this); } diff --git a/xs/src/eigen/Eigen/src/Geometry/arch/Geometry_SSE.h b/xs/src/eigen/Eigen/src/Geometry/arch/Geometry_SSE.h index 1a86ff837..f68cab583 100644 --- a/xs/src/eigen/Eigen/src/Geometry/arch/Geometry_SSE.h +++ b/xs/src/eigen/Eigen/src/Geometry/arch/Geometry_SSE.h @@ -16,17 +16,23 @@ namespace Eigen { namespace internal { template -struct quat_product +struct quat_product { + enum { + AAlignment = traits::Alignment, + BAlignment = traits::Alignment, + ResAlignment = traits >::Alignment + }; static inline Quaternion run(const QuaternionBase& _a, const QuaternionBase& _b) { Quaternion res; const __m128 mask = _mm_setr_ps(0.f,0.f,0.f,-0.f); - __m128 a = _a.coeffs().template packet(0); - __m128 b = _b.coeffs().template packet(0); + __m128 a = _a.coeffs().template packet(0); + __m128 b = _b.coeffs().template packet(0); __m128 s1 = _mm_mul_ps(vec4f_swizzle1(a,1,2,0,2),vec4f_swizzle1(b,2,0,1,2)); __m128 s2 = _mm_mul_ps(vec4f_swizzle1(a,3,3,3,1),vec4f_swizzle1(b,0,1,2,1)); - pstore(&res.x(), + pstoret( + &res.x(), _mm_add_ps(_mm_sub_ps(_mm_mul_ps(a,vec4f_swizzle1(b,3,3,3,3)), _mm_mul_ps(vec4f_swizzle1(a,2,0,1,0), vec4f_swizzle1(b,1,2,0,0))), @@ -36,14 +42,17 @@ struct quat_product } }; -template -struct quat_conj +template +struct quat_conj { + enum { + ResAlignment = traits >::Alignment + }; static inline Quaternion run(const QuaternionBase& q) { Quaternion res; const __m128 mask = _mm_setr_ps(-0.f,-0.f,-0.f,0.f); - pstore(&res.x(), _mm_xor_ps(mask, q.coeffs().template packet(0))); + pstoret(&res.x(), _mm_xor_ps(mask, q.coeffs().template packet::Alignment>(0))); return res; } }; @@ -52,6 +61,9 @@ struct quat_conj template struct cross3_impl { + enum { + ResAlignment = traits::type>::Alignment + }; static inline typename plain_matrix_type::type run(const VectorLhs& lhs, const VectorRhs& rhs) { @@ -60,7 +72,7 @@ struct cross3_impl __m128 mul1=_mm_mul_ps(vec4f_swizzle1(a,1,2,0,3),vec4f_swizzle1(b,2,0,1,3)); __m128 mul2=_mm_mul_ps(vec4f_swizzle1(a,2,0,1,3),vec4f_swizzle1(b,1,2,0,3)); typename plain_matrix_type::type res; - pstore(&res.x(),_mm_sub_ps(mul1,mul2)); + pstoret(&res.x(),_mm_sub_ps(mul1,mul2)); return res; } }; @@ -68,9 +80,14 @@ struct cross3_impl -template -struct quat_product +template +struct quat_product { + enum { + BAlignment = traits::Alignment, + ResAlignment = traits >::Alignment + }; + static inline Quaternion run(const QuaternionBase& _a, const QuaternionBase& _b) { const Packet2d mask = _mm_castsi128_pd(_mm_set_epi32(0x0,0x0,0x80000000,0x0)); @@ -78,8 +95,8 @@ struct quat_product Quaternion res; const double* a = _a.coeffs().data(); - Packet2d b_xy = _b.coeffs().template packet(0); - Packet2d b_zw = _b.coeffs().template packet(2); + Packet2d b_xy = _b.coeffs().template packet(0); + Packet2d b_zw = _b.coeffs().template packet(2); Packet2d a_xx = pset1(a[0]); Packet2d a_yy = pset1(a[1]); Packet2d a_zz = pset1(a[2]); @@ -97,9 +114,9 @@ struct quat_product t2 = psub(pmul(a_zz, b_xy), pmul(a_xx, b_zw)); #ifdef EIGEN_VECTORIZE_SSE3 EIGEN_UNUSED_VARIABLE(mask) - pstore(&res.x(), _mm_addsub_pd(t1, preverse(t2))); + pstoret(&res.x(), _mm_addsub_pd(t1, preverse(t2))); #else - pstore(&res.x(), padd(t1, pxor(mask,preverse(t2)))); + pstoret(&res.x(), padd(t1, pxor(mask,preverse(t2)))); #endif /* @@ -111,25 +128,28 @@ struct quat_product t2 = padd(pmul(a_zz, b_zw), pmul(a_xx, b_xy)); #ifdef EIGEN_VECTORIZE_SSE3 EIGEN_UNUSED_VARIABLE(mask) - pstore(&res.z(), preverse(_mm_addsub_pd(preverse(t1), t2))); + pstoret(&res.z(), preverse(_mm_addsub_pd(preverse(t1), t2))); #else - pstore(&res.z(), psub(t1, pxor(mask,preverse(t2)))); + pstoret(&res.z(), psub(t1, pxor(mask,preverse(t2)))); #endif return res; } }; -template -struct quat_conj +template +struct quat_conj { + enum { + ResAlignment = traits >::Alignment + }; static inline Quaternion run(const QuaternionBase& q) { Quaternion res; const __m128d mask0 = _mm_setr_pd(-0.,-0.); const __m128d mask2 = _mm_setr_pd(-0.,0.); - pstore(&res.x(), _mm_xor_pd(mask0, q.coeffs().template packet(0))); - pstore(&res.z(), _mm_xor_pd(mask2, q.coeffs().template packet(2))); + pstoret(&res.x(), _mm_xor_pd(mask0, q.coeffs().template packet::Alignment>(0))); + pstoret(&res.z(), _mm_xor_pd(mask2, q.coeffs().template packet::Alignment>(2))); return res; } }; diff --git a/xs/src/eigen/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h b/xs/src/eigen/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h index 358444aff..f66c846ef 100644 --- a/xs/src/eigen/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h +++ b/xs/src/eigen/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h @@ -152,13 +152,28 @@ class LeastSquareDiagonalPreconditioner : public DiagonalPreconditioner<_Scalar> { // Compute the inverse squared-norm of each column of mat m_invdiag.resize(mat.cols()); - for(Index j=0; j0) - m_invdiag(j) = RealScalar(1)/sum; - else - m_invdiag(j) = RealScalar(1); + m_invdiag.setZero(); + for(Index j=0; jRealScalar(0)) + m_invdiag(j) = RealScalar(1)/numext::real(m_invdiag(j)); + } + else + { + for(Index j=0; jRealScalar(0)) + m_invdiag(j) = RealScalar(1)/sum; + else + m_invdiag(j) = RealScalar(1); + } } Base::m_isInitialized = true; return *this; diff --git a/xs/src/eigen/Eigen/src/Jacobi/Jacobi.h b/xs/src/eigen/Eigen/src/Jacobi/Jacobi.h index d25af8e90..437e666a3 100644 --- a/xs/src/eigen/Eigen/src/Jacobi/Jacobi.h +++ b/xs/src/eigen/Eigen/src/Jacobi/Jacobi.h @@ -298,12 +298,144 @@ inline void MatrixBase::applyOnTheRight(Index p, Index q, const JacobiR } namespace internal { + +template +struct apply_rotation_in_the_plane_selector +{ + static inline void run(Scalar *x, Index incrx, Scalar *y, Index incry, Index size, OtherScalar c, OtherScalar s) + { + for(Index i=0; i +struct apply_rotation_in_the_plane_selector +{ + static inline void run(Scalar *x, Index incrx, Scalar *y, Index incry, Index size, OtherScalar c, OtherScalar s) + { + enum { + PacketSize = packet_traits::size, + OtherPacketSize = packet_traits::size + }; + typedef typename packet_traits::type Packet; + typedef typename packet_traits::type OtherPacket; + + /*** dynamic-size vectorized paths ***/ + if(SizeAtCompileTime == Dynamic && ((incrx==1 && incry==1) || PacketSize == 1)) + { + // both vectors are sequentially stored in memory => vectorization + enum { Peeling = 2 }; + + Index alignedStart = internal::first_default_aligned(y, size); + Index alignedEnd = alignedStart + ((size-alignedStart)/PacketSize)*PacketSize; + + const OtherPacket pc = pset1(c); + const OtherPacket ps = pset1(s); + conj_helper::IsComplex,false> pcj; + conj_helper pm; + + for(Index i=0; i(px); + Packet yi = pload(py); + pstore(px, padd(pm.pmul(pc,xi),pcj.pmul(ps,yi))); + pstore(py, psub(pcj.pmul(pc,yi),pm.pmul(ps,xi))); + px += PacketSize; + py += PacketSize; + } + } + else + { + Index peelingEnd = alignedStart + ((size-alignedStart)/(Peeling*PacketSize))*(Peeling*PacketSize); + for(Index i=alignedStart; i(px); + Packet xi1 = ploadu(px+PacketSize); + Packet yi = pload (py); + Packet yi1 = pload (py+PacketSize); + pstoreu(px, padd(pm.pmul(pc,xi),pcj.pmul(ps,yi))); + pstoreu(px+PacketSize, padd(pm.pmul(pc,xi1),pcj.pmul(ps,yi1))); + pstore (py, psub(pcj.pmul(pc,yi),pm.pmul(ps,xi))); + pstore (py+PacketSize, psub(pcj.pmul(pc,yi1),pm.pmul(ps,xi1))); + px += Peeling*PacketSize; + py += Peeling*PacketSize; + } + if(alignedEnd!=peelingEnd) + { + Packet xi = ploadu(x+peelingEnd); + Packet yi = pload (y+peelingEnd); + pstoreu(x+peelingEnd, padd(pm.pmul(pc,xi),pcj.pmul(ps,yi))); + pstore (y+peelingEnd, psub(pcj.pmul(pc,yi),pm.pmul(ps,xi))); + } + } + + for(Index i=alignedEnd; i0) // FIXME should be compared to the required alignment + { + const OtherPacket pc = pset1(c); + const OtherPacket ps = pset1(s); + conj_helper::IsComplex,false> pcj; + conj_helper pm; + Scalar* EIGEN_RESTRICT px = x; + Scalar* EIGEN_RESTRICT py = y; + for(Index i=0; i(px); + Packet yi = pload(py); + pstore(px, padd(pm.pmul(pc,xi),pcj.pmul(ps,yi))); + pstore(py, psub(pcj.pmul(pc,yi),pm.pmul(ps,xi))); + px += PacketSize; + py += PacketSize; + } + } + + /*** non-vectorized path ***/ + else + { + apply_rotation_in_the_plane_selector::run(x,incrx,y,incry,size,c,s); + } + } +}; + template void /*EIGEN_DONT_INLINE*/ apply_rotation_in_the_plane(DenseBase& xpr_x, DenseBase& xpr_y, const JacobiRotation& j) { typedef typename VectorX::Scalar Scalar; - enum { PacketSize = packet_traits::size }; - typedef typename packet_traits::type Packet; + const bool Vectorizable = (VectorX::Flags & VectorY::Flags & PacketAccessBit) + && (int(packet_traits::size) == int(packet_traits::size)); + eigen_assert(xpr_x.size() == xpr_y.size()); Index size = xpr_x.size(); Index incrx = xpr_x.derived().innerStride(); @@ -317,113 +449,11 @@ void /*EIGEN_DONT_INLINE*/ apply_rotation_in_the_plane(DenseBase& xpr_x if (c==OtherScalar(1) && s==OtherScalar(0)) return; - /*** dynamic-size vectorized paths ***/ - - if(VectorX::SizeAtCompileTime == Dynamic && - (VectorX::Flags & VectorY::Flags & PacketAccessBit) && - ((incrx==1 && incry==1) || PacketSize == 1)) - { - // both vectors are sequentially stored in memory => vectorization - enum { Peeling = 2 }; - - Index alignedStart = internal::first_default_aligned(y, size); - Index alignedEnd = alignedStart + ((size-alignedStart)/PacketSize)*PacketSize; - - const Packet pc = pset1(c); - const Packet ps = pset1(s); - conj_helper::IsComplex,false> pcj; - - for(Index i=0; i(px); - Packet yi = pload(py); - pstore(px, padd(pmul(pc,xi),pcj.pmul(ps,yi))); - pstore(py, psub(pcj.pmul(pc,yi),pmul(ps,xi))); - px += PacketSize; - py += PacketSize; - } - } - else - { - Index peelingEnd = alignedStart + ((size-alignedStart)/(Peeling*PacketSize))*(Peeling*PacketSize); - for(Index i=alignedStart; i(px); - Packet xi1 = ploadu(px+PacketSize); - Packet yi = pload (py); - Packet yi1 = pload (py+PacketSize); - pstoreu(px, padd(pmul(pc,xi),pcj.pmul(ps,yi))); - pstoreu(px+PacketSize, padd(pmul(pc,xi1),pcj.pmul(ps,yi1))); - pstore (py, psub(pcj.pmul(pc,yi),pmul(ps,xi))); - pstore (py+PacketSize, psub(pcj.pmul(pc,yi1),pmul(ps,xi1))); - px += Peeling*PacketSize; - py += Peeling*PacketSize; - } - if(alignedEnd!=peelingEnd) - { - Packet xi = ploadu(x+peelingEnd); - Packet yi = pload (y+peelingEnd); - pstoreu(x+peelingEnd, padd(pmul(pc,xi),pcj.pmul(ps,yi))); - pstore (y+peelingEnd, psub(pcj.pmul(pc,yi),pmul(ps,xi))); - } - } - - for(Index i=alignedEnd; i::Alignment, evaluator::Alignment)>0)) // FIXME should be compared to the required alignment - { - const Packet pc = pset1(c); - const Packet ps = pset1(s); - conj_helper::IsComplex,false> pcj; - Scalar* EIGEN_RESTRICT px = x; - Scalar* EIGEN_RESTRICT py = y; - for(Index i=0; i(px); - Packet yi = pload(py); - pstore(px, padd(pmul(pc,xi),pcj.pmul(ps,yi))); - pstore(py, psub(pcj.pmul(pc,yi),pmul(ps,xi))); - px += PacketSize; - py += PacketSize; - } - } - - /*** non-vectorized path ***/ - else - { - for(Index i=0; i::Alignment, evaluator::Alignment), + Vectorizable>::run(x,incrx,y,incry,size,c,s); } } // end namespace internal diff --git a/xs/src/eigen/Eigen/src/LU/InverseImpl.h b/xs/src/eigen/Eigen/src/LU/InverseImpl.h index 018f99b58..f49f23360 100644 --- a/xs/src/eigen/Eigen/src/LU/InverseImpl.h +++ b/xs/src/eigen/Eigen/src/LU/InverseImpl.h @@ -404,7 +404,7 @@ inline void MatrixBase::computeInverseWithCheck( const RealScalar& absDeterminantThreshold ) const { - RealScalar determinant; + Scalar determinant; // i'd love to put some static assertions there, but SFINAE means that they have no effect... eigen_assert(rows() == cols()); computeInverseAndDetWithCheck(inverse,determinant,invertible,absDeterminantThreshold); diff --git a/xs/src/eigen/Eigen/src/OrderingMethods/Eigen_Colamd.h b/xs/src/eigen/Eigen/src/OrderingMethods/Eigen_Colamd.h index 933cd564b..da85b4d6e 100644 --- a/xs/src/eigen/Eigen/src/OrderingMethods/Eigen_Colamd.h +++ b/xs/src/eigen/Eigen/src/OrderingMethods/Eigen_Colamd.h @@ -1004,7 +1004,7 @@ static IndexType find_ordering /* return the number of garbage collections */ COLAMD_ASSERT (head [min_score] >= COLAMD_EMPTY) ; /* get pivot column from head of minimum degree list */ - while (head [min_score] == COLAMD_EMPTY && min_score < n_col) + while (min_score < n_col && head [min_score] == COLAMD_EMPTY) { min_score++ ; } diff --git a/xs/src/eigen/Eigen/src/PaStiXSupport/PaStiXSupport.h b/xs/src/eigen/Eigen/src/PaStiXSupport/PaStiXSupport.h index d2ebfd7bb..160d8a523 100644 --- a/xs/src/eigen/Eigen/src/PaStiXSupport/PaStiXSupport.h +++ b/xs/src/eigen/Eigen/src/PaStiXSupport/PaStiXSupport.h @@ -64,28 +64,28 @@ namespace internal typedef typename _MatrixType::StorageIndex StorageIndex; }; - void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, float *vals, int *perm, int * invp, float *x, int nbrhs, int *iparm, double *dparm) + inline void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, float *vals, int *perm, int * invp, float *x, int nbrhs, int *iparm, double *dparm) { if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; } if (nbrhs == 0) {x = NULL; nbrhs=1;} s_pastix(pastix_data, pastix_comm, n, ptr, idx, vals, perm, invp, x, nbrhs, iparm, dparm); } - void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, double *vals, int *perm, int * invp, double *x, int nbrhs, int *iparm, double *dparm) + inline void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, double *vals, int *perm, int * invp, double *x, int nbrhs, int *iparm, double *dparm) { if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; } if (nbrhs == 0) {x = NULL; nbrhs=1;} d_pastix(pastix_data, pastix_comm, n, ptr, idx, vals, perm, invp, x, nbrhs, iparm, dparm); } - void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex *vals, int *perm, int * invp, std::complex *x, int nbrhs, int *iparm, double *dparm) + inline void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex *vals, int *perm, int * invp, std::complex *x, int nbrhs, int *iparm, double *dparm) { if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; } if (nbrhs == 0) {x = NULL; nbrhs=1;} c_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast(vals), perm, invp, reinterpret_cast(x), nbrhs, iparm, dparm); } - void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex *vals, int *perm, int * invp, std::complex *x, int nbrhs, int *iparm, double *dparm) + inline void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex *vals, int *perm, int * invp, std::complex *x, int nbrhs, int *iparm, double *dparm) { if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; } if (nbrhs == 0) {x = NULL; nbrhs=1;} diff --git a/xs/src/eigen/Eigen/src/QR/ColPivHouseholderQR.h b/xs/src/eigen/Eigen/src/QR/ColPivHouseholderQR.h index 0e47c8332..a7b47d55d 100644 --- a/xs/src/eigen/Eigen/src/QR/ColPivHouseholderQR.h +++ b/xs/src/eigen/Eigen/src/QR/ColPivHouseholderQR.h @@ -506,8 +506,8 @@ void ColPivHouseholderQR::computeInPlace() m_colNormsUpdated.coeffRef(k) = m_colNormsDirect.coeffRef(k); } - RealScalar threshold_helper = numext::abs2(m_colNormsUpdated.maxCoeff() * NumTraits::epsilon()) / RealScalar(rows); - RealScalar norm_downdate_threshold = numext::sqrt(NumTraits::epsilon()); + RealScalar threshold_helper = numext::abs2(m_colNormsUpdated.maxCoeff() * NumTraits::epsilon()) / RealScalar(rows); + RealScalar norm_downdate_threshold = numext::sqrt(NumTraits::epsilon()); m_nonzero_pivots = size; // the generic case is that in which all pivots are nonzero (invertible case) m_maxpivot = RealScalar(0); @@ -553,12 +553,12 @@ void ColPivHouseholderQR::computeInPlace() // http://www.netlib.org/lapack/lawnspdf/lawn176.pdf // and used in LAPACK routines xGEQPF and xGEQP3. // See lines 278-297 in http://www.netlib.org/lapack/explore-html/dc/df4/sgeqpf_8f_source.html - if (m_colNormsUpdated.coeffRef(j) != 0) { + if (m_colNormsUpdated.coeffRef(j) != RealScalar(0)) { RealScalar temp = abs(m_qr.coeffRef(k, j)) / m_colNormsUpdated.coeffRef(j); temp = (RealScalar(1) + temp) * (RealScalar(1) - temp); - temp = temp < 0 ? 0 : temp; - RealScalar temp2 = temp * numext::abs2(m_colNormsUpdated.coeffRef(j) / - m_colNormsDirect.coeffRef(j)); + temp = temp < RealScalar(0) ? RealScalar(0) : temp; + RealScalar temp2 = temp * numext::abs2(m_colNormsUpdated.coeffRef(j) / + m_colNormsDirect.coeffRef(j)); if (temp2 <= norm_downdate_threshold) { // The updated norm has become too inaccurate so re-compute the column // norm directly. diff --git a/xs/src/eigen/Eigen/src/SVD/BDCSVD.h b/xs/src/eigen/Eigen/src/SVD/BDCSVD.h index 25fca6f4d..1134d66e7 100644 --- a/xs/src/eigen/Eigen/src/SVD/BDCSVD.h +++ b/xs/src/eigen/Eigen/src/SVD/BDCSVD.h @@ -11,7 +11,7 @@ // Copyright (C) 2013 Jean Ceccato // Copyright (C) 2013 Pierre Zoppitelli // Copyright (C) 2013 Jitse Niesen -// Copyright (C) 2014-2016 Gael Guennebaud +// Copyright (C) 2014-2017 Gael Guennebaud // // Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed @@ -77,6 +77,7 @@ public: typedef _MatrixType MatrixType; typedef typename MatrixType::Scalar Scalar; typedef typename NumTraits::Real RealScalar; + typedef typename NumTraits::Literal Literal; enum { RowsAtCompileTime = MatrixType::RowsAtCompileTime, ColsAtCompileTime = MatrixType::ColsAtCompileTime, @@ -259,7 +260,7 @@ BDCSVD& BDCSVD::compute(const MatrixType& matrix, unsign //**** step 0 - Copy the input matrix and apply scaling to reduce over/under-flows RealScalar scale = matrix.cwiseAbs().maxCoeff(); - if(scale==RealScalar(0)) scale = RealScalar(1); + if(scale==Literal(0)) scale = Literal(1); MatrixX copy; if (m_isTranspose) copy = matrix.adjoint()/scale; else copy = matrix/scale; @@ -351,13 +352,13 @@ void BDCSVD::structured_update(Block A, co Index k1=0, k2=0; for(Index j=0; j::divide (Index firstCol, Index lastCol, Index firstRowW, l = m_naiveU.row(1).segment(firstCol, k); f = m_naiveU.row(0).segment(firstCol + k + 1, n - k - 1); } - if (m_compV) m_naiveV(firstRowW+k, firstColW) = 1; + if (m_compV) m_naiveV(firstRowW+k, firstColW) = Literal(1); if (r0::computeSVDofM(Index firstCol, Index n, MatrixXr& U, Vec ArrayRef col0 = m_computed.col(firstCol).segment(firstCol, n); m_workspace.head(n) = m_computed.block(firstCol, firstCol, n, n).diagonal(); ArrayRef diag = m_workspace.head(n); - diag(0) = 0; + diag(0) = Literal(0); // Allocate space for singular values and vectors singVals.resize(n); @@ -590,7 +591,7 @@ void BDCSVD::computeSVDofM(Index firstCol, Index n, MatrixXr& U, Vec // but others are interleaved and we must ignore them at this stage. // To this end, let's compute a permutation skipping them: Index actual_n = n; - while(actual_n>1 && diag(actual_n-1)==0) --actual_n; + while(actual_n>1 && diag(actual_n-1)==Literal(0)) --actual_n; Index m = 0; // size of the deflated problem for(Index k=0;kconsiderZero) @@ -691,11 +692,13 @@ template typename BDCSVD::RealScalar BDCSVD::secularEq(RealScalar mu, const ArrayRef& col0, const ArrayRef& diag, const IndicesRef &perm, const ArrayRef& diagShifted, RealScalar shift) { Index m = perm.size(); - RealScalar res = 1; + RealScalar res = Literal(1); for(Index i=0; i::computeSingVals(const ArrayRef& col0, const ArrayRef& d { using std::abs; using std::swap; + using std::sqrt; Index n = col0.size(); Index actual_n = n; - while(actual_n>1 && col0(actual_n-1)==0) --actual_n; + // Note that here actual_n is computed based on col0(i)==0 instead of diag(i)==0 as above + // because 1) we have diag(i)==0 => col0(i)==0 and 2) if col0(i)==0, then diag(i) is already a singular value. + while(actual_n>1 && col0(actual_n-1)==Literal(0)) --actual_n; for (Index k = 0; k < n; ++k) { - if (col0(k) == 0 || actual_n==1) + if (col0(k) == Literal(0) || actual_n==1) { // if col0(k) == 0, then entry is deflated, so singular value is on diagonal // if actual_n==1, then the deflated problem is already diagonalized singVals(k) = k==0 ? col0(0) : diag(k); - mus(k) = 0; + mus(k) = Literal(0); shifts(k) = k==0 ? col0(0) : diag(k); continue; } @@ -731,15 +737,17 @@ void BDCSVD::computeSingVals(const ArrayRef& col0, const ArrayRef& d right = (diag(actual_n-1) + col0.matrix().norm()); else { - // Skip deflated singular values + // Skip deflated singular values, + // recall that at this stage we assume that z[j]!=0 and all entries for which z[j]==0 have been put aside. + // This should be equivalent to using perm[] Index l = k+1; - while(col0(l)==0) { ++l; eigen_internal_assert(l::computeSingVals(const ArrayRef& col0, const ArrayRef& d << " " << secularEq(0.8*(left+right), col0, diag, perm, diag, 0) << " " << secularEq(0.9*(left+right), col0, diag, perm, diag, 0) << "\n"; #endif - RealScalar shift = (k == actual_n-1 || fMid > 0) ? left : right; + RealScalar shift = (k == actual_n-1 || fMid > Literal(0)) ? left : right; // measure everything relative to shift Map diagShifted(m_workspace.data()+4*n, n); @@ -785,13 +793,13 @@ void BDCSVD::computeSingVals(const ArrayRef& col0, const ArrayRef& d // rational interpolation: fit a function of the form a / mu + b through the two previous // iterates and use its zero to compute the next iterate - bool useBisection = fPrev*fCur>0; - while (fCur!=0 && abs(muCur - muPrev) > 8 * NumTraits::epsilon() * numext::maxi(abs(muCur), abs(muPrev)) && abs(fCur - fPrev)>NumTraits::epsilon() && !useBisection) + bool useBisection = fPrev*fCur>Literal(0); + while (fCur!=Literal(0) && abs(muCur - muPrev) > Literal(8) * NumTraits::epsilon() * numext::maxi(abs(muCur), abs(muPrev)) && abs(fCur - fPrev)>NumTraits::epsilon() && !useBisection) { ++m_numIters; // Find a and b such that the function f(mu) = a / mu + b matches the current and previous samples. - RealScalar a = (fCur - fPrev) / (1/muCur - 1/muPrev); + RealScalar a = (fCur - fPrev) / (Literal(1)/muCur - Literal(1)/muPrev); RealScalar b = fCur - a / muCur; // And find mu such that f(mu)==0: RealScalar muZero = -a/b; @@ -803,8 +811,8 @@ void BDCSVD::computeSingVals(const ArrayRef& col0, const ArrayRef& d fCur = fZero; - if (shift == left && (muCur < 0 || muCur > right - left)) useBisection = true; - if (shift == right && (muCur < -(right - left) || muCur > 0)) useBisection = true; + if (shift == left && (muCur < Literal(0) || muCur > right - left)) useBisection = true; + if (shift == right && (muCur < -(right - left) || muCur > Literal(0))) useBisection = true; if (abs(fCur)>abs(fPrev)) useBisection = true; } @@ -817,15 +825,23 @@ void BDCSVD::computeSingVals(const ArrayRef& col0, const ArrayRef& d RealScalar leftShifted, rightShifted; if (shift == left) { - leftShifted = (std::numeric_limits::min)(); + // to avoid overflow, we must have mu > max(real_min, |z(k)|/sqrt(real_max)), + // the factor 2 is to be more conservative + leftShifted = numext::maxi( (std::numeric_limits::min)(), Literal(2) * abs(col0(k)) / sqrt((std::numeric_limits::max)()) ); + + // check that we did it right: + eigen_internal_assert( (numext::isfinite)( (col0(k)/leftShifted)*(col0(k)/(diag(k)+shift+leftShifted)) ) ); // I don't understand why the case k==0 would be special there: - // if (k == 0) rightShifted = right - left; else - rightShifted = (k==actual_n-1) ? right : ((right - left) * RealScalar(0.6)); // theoretically we can take 0.5, but let's be safe + // if (k == 0) rightShifted = right - left; else + rightShifted = (k==actual_n-1) ? right : ((right - left) * RealScalar(0.51)); // theoretically we can take 0.5, but let's be safe } else { - leftShifted = -(right - left) * RealScalar(0.6); - rightShifted = -(std::numeric_limits::min)(); + leftShifted = -(right - left) * RealScalar(0.51); + if(k+1( (std::numeric_limits::min)(), abs(col0(k+1)) / sqrt((std::numeric_limits::max)()) ); + else + rightShifted = -(std::numeric_limits::min)(); } RealScalar fLeft = secularEq(leftShifted, col0, diag, perm, diagShifted, shift); @@ -841,13 +857,13 @@ void BDCSVD::computeSingVals(const ArrayRef& col0, const ArrayRef& d std::cout << k << " : " << fLeft << " * " << fRight << " == " << fLeft * fRight << " ; " << left << " - " << right << " -> " << leftShifted << " " << rightShifted << " shift=" << shift << "\n"; } #endif - eigen_internal_assert(fLeft * fRight < 0); + eigen_internal_assert(fLeft * fRight < Literal(0)); - while (rightShifted - leftShifted > 2 * NumTraits::epsilon() * numext::maxi(abs(leftShifted), abs(rightShifted))) + while (rightShifted - leftShifted > Literal(2) * NumTraits::epsilon() * numext::maxi(abs(leftShifted), abs(rightShifted))) { - RealScalar midShifted = (leftShifted + rightShifted) / 2; + RealScalar midShifted = (leftShifted + rightShifted) / Literal(2); fMid = secularEq(midShifted, col0, diag, perm, diagShifted, shift); - if (fLeft * fMid < 0) + if (fLeft * fMid < Literal(0)) { rightShifted = midShifted; } @@ -858,7 +874,7 @@ void BDCSVD::computeSingVals(const ArrayRef& col0, const ArrayRef& d } } - muCur = (leftShifted + rightShifted) / 2; + muCur = (leftShifted + rightShifted) / Literal(2); } singVals[k] = shift + muCur; @@ -892,8 +908,8 @@ void BDCSVD::perturbCol0 // The offset permits to skip deflated entries while computing zhat for (Index k = 0; k < n; ++k) { - if (col0(k) == 0) // deflated - zhat(k) = 0; + if (col0(k) == Literal(0)) // deflated + zhat(k) = Literal(0); else { // see equation (3.6) @@ -918,7 +934,7 @@ void BDCSVD::perturbCol0 std::cout << "zhat(" << k << ") = sqrt( " << prod << ") ; " << (singVals(last) + dk) << " * " << mus(last) + shifts(last) << " - " << dk << "\n"; #endif RealScalar tmp = sqrt(prod); - zhat(k) = col0(k) > 0 ? tmp : -tmp; + zhat(k) = col0(k) > Literal(0) ? tmp : -tmp; } } } @@ -934,7 +950,7 @@ void BDCSVD::computeSingVecs for (Index k = 0; k < n; ++k) { - if (zhat(k) == 0) + if (zhat(k) == Literal(0)) { U.col(k) = VectorType::Unit(n+1, k); if (m_compV) V.col(k) = VectorType::Unit(n, k); @@ -947,7 +963,7 @@ void BDCSVD::computeSingVecs Index i = perm(l); U(i,k) = zhat(i)/(((diag(i) - shifts(k)) - mus(k)) )/( (diag(i) + singVals[k])); } - U(n,k) = 0; + U(n,k) = Literal(0); U.col(k).normalize(); if (m_compV) @@ -958,7 +974,7 @@ void BDCSVD::computeSingVecs Index i = perm(l); V(i,k) = diag(i) * zhat(i) / (((diag(i) - shifts(k)) - mus(k)) )/( (diag(i) + singVals[k])); } - V(0,k) = -1; + V(0,k) = Literal(-1); V.col(k).normalize(); } } @@ -979,15 +995,15 @@ void BDCSVD::deflation43(Index firstCol, Index shift, Index i, Index Index start = firstCol + shift; RealScalar c = m_computed(start, start); RealScalar s = m_computed(start+i, start); - RealScalar r = sqrt(numext::abs2(c) + numext::abs2(s)); - if (r == 0) + RealScalar r = numext::hypot(c,s); + if (r == Literal(0)) { - m_computed(start+i, start+i) = 0; + m_computed(start+i, start+i) = Literal(0); return; } m_computed(start,start) = r; - m_computed(start+i, start) = 0; - m_computed(start+i, start+i) = 0; + m_computed(start+i, start) = Literal(0); + m_computed(start+i, start+i) = Literal(0); JacobiRotation J(c/r,-s/r); if (m_compU) m_naiveU.middleRows(firstCol, size+1).applyOnTheRight(firstCol, firstCol+i, J); @@ -1020,7 +1036,7 @@ void BDCSVD::deflation44(Index firstColu , Index firstColm, Index fi << m_computed(firstColm + i+1, firstColm+i+1) << " " << m_computed(firstColm + i+2, firstColm+i+2) << "\n"; #endif - if (r==0) + if (r==Literal(0)) { m_computed(firstColm + i, firstColm + i) = m_computed(firstColm + j, firstColm + j); return; @@ -1029,7 +1045,7 @@ void BDCSVD::deflation44(Index firstColu , Index firstColm, Index fi s/=r; m_computed(firstColm + i, firstColm) = r; m_computed(firstColm + j, firstColm + j) = m_computed(firstColm + i, firstColm + i); - m_computed(firstColm + j, firstColm) = 0; + m_computed(firstColm + j, firstColm) = Literal(0); JacobiRotation J(c,-s); if (m_compU) m_naiveU.middleRows(firstColu, size+1).applyOnTheRight(firstColu + i, firstColu + j, J); @@ -1053,7 +1069,7 @@ void BDCSVD::deflation(Index firstCol, Index lastCol, Index k, Index const RealScalar considerZero = (std::numeric_limits::min)(); RealScalar maxDiag = diag.tail((std::max)(Index(1),length-1)).cwiseAbs().maxCoeff(); RealScalar epsilon_strict = numext::maxi(considerZero,NumTraits::epsilon() * maxDiag); - RealScalar epsilon_coarse = 8 * NumTraits::epsilon() * numext::maxi(col0.cwiseAbs().maxCoeff(), maxDiag); + RealScalar epsilon_coarse = Literal(8) * NumTraits::epsilon() * numext::maxi(col0.cwiseAbs().maxCoeff(), maxDiag); #ifdef EIGEN_BDCSVD_SANITY_CHECKS assert(m_naiveU.allFinite()); @@ -1081,7 +1097,7 @@ void BDCSVD::deflation(Index firstCol, Index lastCol, Index k, Index #ifdef EIGEN_BDCSVD_DEBUG_VERBOSE std::cout << "deflation 4.2, set z(" << i << ") to zero because " << abs(col0(i)) << " < " << epsilon_strict << " (diag(" << i << ")=" << diag(i) << ")\n"; #endif - col0(i) = 0; + col0(i) = Literal(0); } //condition 4.3 diff --git a/xs/src/eigen/Eigen/src/SVD/JacobiSVD_LAPACKE.h b/xs/src/eigen/Eigen/src/SVD/JacobiSVD_LAPACKE.h index 50272154f..ff0516f61 100644 --- a/xs/src/eigen/Eigen/src/SVD/JacobiSVD_LAPACKE.h +++ b/xs/src/eigen/Eigen/src/SVD/JacobiSVD_LAPACKE.h @@ -61,9 +61,10 @@ JacobiSVD, ColPiv u = (LAPACKE_TYPE*)m_matrixU.data(); \ } else { ldu=1; u=&dummy; }\ MatrixType localV; \ - ldvt = (m_computeFullV) ? internal::convert_index(m_cols) : (m_computeThinV) ? internal::convert_index(m_diagSize) : 1; \ + lapack_int vt_rows = (m_computeFullV) ? internal::convert_index(m_cols) : (m_computeThinV) ? internal::convert_index(m_diagSize) : 1; \ if (computeV()) { \ - localV.resize(ldvt, m_cols); \ + localV.resize(vt_rows, m_cols); \ + ldvt = internal::convert_index(localV.outerStride()); \ vt = (LAPACKE_TYPE*)localV.data(); \ } else { ldvt=1; vt=&dummy; }\ Matrix superb; superb.resize(m_diagSize, 1); \ diff --git a/xs/src/eigen/Eigen/src/SVD/UpperBidiagonalization.h b/xs/src/eigen/Eigen/src/SVD/UpperBidiagonalization.h index 0b1460894..11ac847e1 100644 --- a/xs/src/eigen/Eigen/src/SVD/UpperBidiagonalization.h +++ b/xs/src/eigen/Eigen/src/SVD/UpperBidiagonalization.h @@ -159,6 +159,8 @@ void upperbidiagonalization_blocked_helper(MatrixType& A, traits::Flags & RowMajorBit> > Y) { typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef typename NumTraits::Literal Literal; enum { StorageOrder = traits::Flags & RowMajorBit }; typedef InnerStride ColInnerStride; typedef InnerStride RowInnerStride; @@ -263,7 +265,7 @@ void upperbidiagonalization_blocked_helper(MatrixType& A, SubMatType A10( A.block(bs,0, brows-bs,bs) ); SubMatType A01( A.block(0,bs, bs,bcols-bs) ); Scalar tmp = A01(bs-1,0); - A01(bs-1,0) = 1; + A01(bs-1,0) = Literal(1); A11.noalias() -= A10 * Y.topLeftCorner(bcols,bs).bottomRows(bcols-bs).adjoint(); A11.noalias() -= X.topLeftCorner(brows,bs).bottomRows(brows-bs) * A01; A01(bs-1,0) = tmp; diff --git a/xs/src/eigen/Eigen/src/SparseCore/AmbiVector.h b/xs/src/eigen/Eigen/src/SparseCore/AmbiVector.h index 8a5cc91f2..e0295f2af 100644 --- a/xs/src/eigen/Eigen/src/SparseCore/AmbiVector.h +++ b/xs/src/eigen/Eigen/src/SparseCore/AmbiVector.h @@ -94,7 +94,7 @@ class AmbiVector Index allocSize = m_allocatedElements * sizeof(ListEl); allocSize = (allocSize + sizeof(Scalar) - 1)/sizeof(Scalar); Scalar* newBuffer = new Scalar[allocSize]; - memcpy(newBuffer, m_buffer, copyElements * sizeof(ListEl)); + std::memcpy(newBuffer, m_buffer, copyElements * sizeof(ListEl)); delete[] m_buffer; m_buffer = newBuffer; } diff --git a/xs/src/eigen/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h b/xs/src/eigen/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h index 492eb0a29..9db119b67 100644 --- a/xs/src/eigen/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h +++ b/xs/src/eigen/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h @@ -17,7 +17,9 @@ namespace internal { template static void conservative_sparse_sparse_product_impl(const Lhs& lhs, const Rhs& rhs, ResultType& res, bool sortedInsertion = false) { - typedef typename remove_all::type::Scalar Scalar; + typedef typename remove_all::type::Scalar LhsScalar; + typedef typename remove_all::type::Scalar RhsScalar; + typedef typename remove_all::type::Scalar ResScalar; // make sure to call innerSize/outerSize since we fake the storage order. Index rows = lhs.innerSize(); @@ -25,7 +27,7 @@ static void conservative_sparse_sparse_product_impl(const Lhs& lhs, const Rhs& r eigen_assert(lhs.outerSize() == rhs.innerSize()); ei_declare_aligned_stack_constructed_variable(bool, mask, rows, 0); - ei_declare_aligned_stack_constructed_variable(Scalar, values, rows, 0); + ei_declare_aligned_stack_constructed_variable(ResScalar, values, rows, 0); ei_declare_aligned_stack_constructed_variable(Index, indices, rows, 0); std::memset(mask,0,sizeof(bool)*rows); @@ -51,12 +53,12 @@ static void conservative_sparse_sparse_product_impl(const Lhs& lhs, const Rhs& r Index nnz = 0; for (typename evaluator::InnerIterator rhsIt(rhsEval, j); rhsIt; ++rhsIt) { - Scalar y = rhsIt.value(); + RhsScalar y = rhsIt.value(); Index k = rhsIt.index(); for (typename evaluator::InnerIterator lhsIt(lhsEval, k); lhsIt; ++lhsIt) { Index i = lhsIt.index(); - Scalar x = lhsIt.value(); + LhsScalar x = lhsIt.value(); if(!mask[i]) { mask[i] = true; @@ -166,11 +168,12 @@ struct conservative_sparse_sparse_product_selector RowMajorMatrix; - RowMajorMatrix rhsRow = rhs; - RowMajorMatrix resRow(lhs.rows(), rhs.cols()); - internal::conservative_sparse_sparse_product_impl(rhsRow, lhs, resRow); - res = resRow; + typedef SparseMatrix RowMajorRhs; + typedef SparseMatrix RowMajorRes; + RowMajorRhs rhsRow = rhs; + RowMajorRes resRow(lhs.rows(), rhs.cols()); + internal::conservative_sparse_sparse_product_impl(rhsRow, lhs, resRow); + res = resRow; } }; @@ -179,10 +182,11 @@ struct conservative_sparse_sparse_product_selector RowMajorMatrix; - RowMajorMatrix lhsRow = lhs; - RowMajorMatrix resRow(lhs.rows(), rhs.cols()); - internal::conservative_sparse_sparse_product_impl(rhs, lhsRow, resRow); + typedef SparseMatrix RowMajorLhs; + typedef SparseMatrix RowMajorRes; + RowMajorLhs lhsRow = lhs; + RowMajorRes resRow(lhs.rows(), rhs.cols()); + internal::conservative_sparse_sparse_product_impl(rhs, lhsRow, resRow); res = resRow; } }; @@ -219,10 +223,11 @@ struct conservative_sparse_sparse_product_selector ColMajorMatrix; - ColMajorMatrix lhsCol = lhs; - ColMajorMatrix resCol(lhs.rows(), rhs.cols()); - internal::conservative_sparse_sparse_product_impl(lhsCol, rhs, resCol); + typedef SparseMatrix ColMajorLhs; + typedef SparseMatrix ColMajorRes; + ColMajorLhs lhsCol = lhs; + ColMajorRes resCol(lhs.rows(), rhs.cols()); + internal::conservative_sparse_sparse_product_impl(lhsCol, rhs, resCol); res = resCol; } }; @@ -232,10 +237,11 @@ struct conservative_sparse_sparse_product_selector ColMajorMatrix; - ColMajorMatrix rhsCol = rhs; - ColMajorMatrix resCol(lhs.rows(), rhs.cols()); - internal::conservative_sparse_sparse_product_impl(lhs, rhsCol, resCol); + typedef SparseMatrix ColMajorRhs; + typedef SparseMatrix ColMajorRes; + ColMajorRhs rhsCol = rhs; + ColMajorRes resCol(lhs.rows(), rhs.cols()); + internal::conservative_sparse_sparse_product_impl(lhs, rhsCol, resCol); res = resCol; } }; @@ -263,7 +269,8 @@ namespace internal { template static void sparse_sparse_to_dense_product_impl(const Lhs& lhs, const Rhs& rhs, ResultType& res) { - typedef typename remove_all::type::Scalar Scalar; + typedef typename remove_all::type::Scalar LhsScalar; + typedef typename remove_all::type::Scalar RhsScalar; Index cols = rhs.outerSize(); eigen_assert(lhs.outerSize() == rhs.innerSize()); @@ -274,12 +281,12 @@ static void sparse_sparse_to_dense_product_impl(const Lhs& lhs, const Rhs& rhs, { for (typename evaluator::InnerIterator rhsIt(rhsEval, j); rhsIt; ++rhsIt) { - Scalar y = rhsIt.value(); + RhsScalar y = rhsIt.value(); Index k = rhsIt.index(); for (typename evaluator::InnerIterator lhsIt(lhsEval, k); lhsIt; ++lhsIt) { Index i = lhsIt.index(); - Scalar x = lhsIt.value(); + LhsScalar x = lhsIt.value(); res.coeffRef(i,j) += x * y; } } @@ -310,9 +317,9 @@ struct sparse_sparse_to_dense_product_selector ColMajorMatrix; - ColMajorMatrix lhsCol(lhs); - internal::sparse_sparse_to_dense_product_impl(lhsCol, rhs, res); + typedef SparseMatrix ColMajorLhs; + ColMajorLhs lhsCol(lhs); + internal::sparse_sparse_to_dense_product_impl(lhsCol, rhs, res); } }; @@ -321,9 +328,9 @@ struct sparse_sparse_to_dense_product_selector ColMajorMatrix; - ColMajorMatrix rhsCol(rhs); - internal::sparse_sparse_to_dense_product_impl(lhs, rhsCol, res); + typedef SparseMatrix ColMajorRhs; + ColMajorRhs rhsCol(rhs); + internal::sparse_sparse_to_dense_product_impl(lhs, rhsCol, res); } }; diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseSelfAdjointView.h b/xs/src/eigen/Eigen/src/SparseCore/SparseSelfAdjointView.h index 9e39be738..65611b3d4 100644 --- a/xs/src/eigen/Eigen/src/SparseCore/SparseSelfAdjointView.h +++ b/xs/src/eigen/Eigen/src/SparseCore/SparseSelfAdjointView.h @@ -47,6 +47,7 @@ template class SparseSelfAdjointView enum { Mode = _Mode, + TransposeMode = ((Mode & Upper) ? Lower : 0) | ((Mode & Lower) ? Upper : 0), RowsAtCompileTime = internal::traits::RowsAtCompileTime, ColsAtCompileTime = internal::traits::ColsAtCompileTime }; @@ -310,7 +311,7 @@ inline void sparse_selfadjoint_time_dense_product(const SparseLhsType& lhs, cons while (i && i.index() dstT(dst); - internal::sparse_selfadjoint_time_dense_product(rhsNested.transpose(), lhsNested.transpose(), dstT, alpha); + internal::sparse_selfadjoint_time_dense_product(rhsNested.transpose(), lhsNested.transpose(), dstT, alpha); } }; diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseSparseProductWithPruning.h b/xs/src/eigen/Eigen/src/SparseCore/SparseSparseProductWithPruning.h index 21c419002..88820a48f 100644 --- a/xs/src/eigen/Eigen/src/SparseCore/SparseSparseProductWithPruning.h +++ b/xs/src/eigen/Eigen/src/SparseCore/SparseSparseProductWithPruning.h @@ -21,7 +21,8 @@ static void sparse_sparse_product_with_pruning_impl(const Lhs& lhs, const Rhs& r { // return sparse_sparse_product_with_pruning_impl2(lhs,rhs,res); - typedef typename remove_all::type::Scalar Scalar; + typedef typename remove_all::type::Scalar RhsScalar; + typedef typename remove_all::type::Scalar ResScalar; typedef typename remove_all::type::StorageIndex StorageIndex; // make sure to call innerSize/outerSize since we fake the storage order. @@ -31,7 +32,7 @@ static void sparse_sparse_product_with_pruning_impl(const Lhs& lhs, const Rhs& r eigen_assert(lhs.outerSize() == rhs.innerSize()); // allocate a temporary buffer - AmbiVector tempVector(rows); + AmbiVector tempVector(rows); // mimics a resizeByInnerOuter: if(ResultType::IsRowMajor) @@ -63,14 +64,14 @@ static void sparse_sparse_product_with_pruning_impl(const Lhs& lhs, const Rhs& r { // FIXME should be written like this: tmp += rhsIt.value() * lhs.col(rhsIt.index()) tempVector.restart(); - Scalar x = rhsIt.value(); + RhsScalar x = rhsIt.value(); for (typename evaluator::InnerIterator lhsIt(lhsEval, rhsIt.index()); lhsIt; ++lhsIt) { tempVector.coeffRef(lhsIt.index()) += lhsIt.value() * x; } } res.startVec(j); - for (typename AmbiVector::Iterator it(tempVector,tolerance); it; ++it) + for (typename AmbiVector::Iterator it(tempVector,tolerance); it; ++it) res.insertBackByOuterInner(j,it.index()) = it.value(); } res.finalize(); @@ -85,7 +86,6 @@ struct sparse_sparse_product_with_pruning_selector; template struct sparse_sparse_product_with_pruning_selector { - typedef typename traits::type>::Scalar Scalar; typedef typename ResultType::RealScalar RealScalar; static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, const RealScalar& tolerance) @@ -129,8 +129,8 @@ struct sparse_sparse_product_with_pruning_selector ColMajorMatrixLhs; - typedef SparseMatrix ColMajorMatrixRhs; + typedef SparseMatrix ColMajorMatrixLhs; + typedef SparseMatrix ColMajorMatrixRhs; ColMajorMatrixLhs colLhs(lhs); ColMajorMatrixRhs colRhs(rhs); internal::sparse_sparse_product_with_pruning_impl(colLhs, colRhs, res, tolerance); @@ -149,7 +149,7 @@ struct sparse_sparse_product_with_pruning_selector RowMajorMatrixLhs; + typedef SparseMatrix RowMajorMatrixLhs; RowMajorMatrixLhs rowLhs(lhs); sparse_sparse_product_with_pruning_selector(rowLhs,rhs,res,tolerance); } @@ -161,7 +161,7 @@ struct sparse_sparse_product_with_pruning_selector RowMajorMatrixRhs; + typedef SparseMatrix RowMajorMatrixRhs; RowMajorMatrixRhs rowRhs(rhs); sparse_sparse_product_with_pruning_selector(lhs,rowRhs,res,tolerance); } @@ -173,7 +173,7 @@ struct sparse_sparse_product_with_pruning_selector ColMajorMatrixRhs; + typedef SparseMatrix ColMajorMatrixRhs; ColMajorMatrixRhs colRhs(rhs); internal::sparse_sparse_product_with_pruning_impl(lhs, colRhs, res, tolerance); } @@ -185,7 +185,7 @@ struct sparse_sparse_product_with_pruning_selector ColMajorMatrixLhs; + typedef SparseMatrix ColMajorMatrixLhs; ColMajorMatrixLhs colLhs(lhs); internal::sparse_sparse_product_with_pruning_impl(colLhs, rhs, res, tolerance); } diff --git a/xs/src/eigen/Eigen/src/SparseQR/SparseQR.h b/xs/src/eigen/Eigen/src/SparseQR/SparseQR.h index 2d4498b03..7409fcae9 100644 --- a/xs/src/eigen/Eigen/src/SparseQR/SparseQR.h +++ b/xs/src/eigen/Eigen/src/SparseQR/SparseQR.h @@ -52,7 +52,7 @@ namespace internal { * rank-revealing permutations. Use colsPermutation() to get it. * * Q is the orthogonal matrix represented as products of Householder reflectors. - * Use matrixQ() to get an expression and matrixQ().transpose() to get the transpose. + * Use matrixQ() to get an expression and matrixQ().adjoint() to get the adjoint. * You can then apply it to a vector. * * R is the sparse triangular or trapezoidal matrix. The later occurs when A is rank-deficient. @@ -65,6 +65,7 @@ namespace internal { * \implsparsesolverconcept * * \warning The input sparse matrix A must be in compressed mode (see SparseMatrix::makeCompressed()). + * \warning For complex matrices matrixQ().transpose() will actually return the adjoint matrix. * */ template @@ -196,9 +197,9 @@ class SparseQR : public SparseSolverBase > Index rank = this->rank(); - // Compute Q^T * b; + // Compute Q^* * b; typename Dest::PlainObject y, b; - y = this->matrixQ().transpose() * B; + y = this->matrixQ().adjoint() * B; b = y; // Solve with the triangular matrix R @@ -604,7 +605,7 @@ struct SparseQR_QProduct : ReturnByValue @@ -668,13 +672,14 @@ struct SparseQRMatrixQReturnType : public EigenBase(m_qr,other.derived(),false); } + // To use for operations with the adjoint of Q SparseQRMatrixQTransposeReturnType adjoint() const { return SparseQRMatrixQTransposeReturnType(m_qr); } inline Index rows() const { return m_qr.rows(); } - inline Index cols() const { return (std::min)(m_qr.rows(),m_qr.cols()); } - // To use for operations with the transpose of Q + inline Index cols() const { return m_qr.rows(); } + // To use for operations with the transpose of Q FIXME this is the same as adjoint at the moment SparseQRMatrixQTransposeReturnType transpose() const { return SparseQRMatrixQTransposeReturnType(m_qr); @@ -682,6 +687,7 @@ struct SparseQRMatrixQReturnType : public EigenBase struct SparseQRMatrixQTransposeReturnType { @@ -712,7 +718,7 @@ struct Assignment, internal: typedef typename DstXprType::StorageIndex StorageIndex; static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &/*func*/) { - typename DstXprType::PlainObject idMat(src.m_qr.rows(), src.m_qr.rows()); + typename DstXprType::PlainObject idMat(src.rows(), src.cols()); idMat.setIdentity(); // Sort the sparse householder reflectors if needed const_cast(&src.m_qr)->_sort_matrix_Q(); diff --git a/xs/src/eigen/Eigen/src/UmfPackSupport/UmfPackSupport.h b/xs/src/eigen/Eigen/src/UmfPackSupport/UmfPackSupport.h index dc74de935..91c09ab13 100644 --- a/xs/src/eigen/Eigen/src/UmfPackSupport/UmfPackSupport.h +++ b/xs/src/eigen/Eigen/src/UmfPackSupport/UmfPackSupport.h @@ -10,19 +10,37 @@ #ifndef EIGEN_UMFPACKSUPPORT_H #define EIGEN_UMFPACKSUPPORT_H -namespace Eigen { +namespace Eigen { /* TODO extract L, extract U, compute det, etc... */ // generic double/complex wrapper functions: -inline void umfpack_defaults(double control[UMFPACK_CONTROL], double) +inline void umfpack_defaults(double control[UMFPACK_CONTROL], double) { umfpack_di_defaults(control); } -inline void umfpack_defaults(double control[UMFPACK_CONTROL], std::complex) +inline void umfpack_defaults(double control[UMFPACK_CONTROL], std::complex) { umfpack_zi_defaults(control); } +inline void umfpack_report_info(double control[UMFPACK_CONTROL], double info[UMFPACK_INFO], double) +{ umfpack_di_report_info(control, info);} + +inline void umfpack_report_info(double control[UMFPACK_CONTROL], double info[UMFPACK_INFO], std::complex) +{ umfpack_zi_report_info(control, info);} + +inline void umfpack_report_status(double control[UMFPACK_CONTROL], int status, double) +{ umfpack_di_report_status(control, status);} + +inline void umfpack_report_status(double control[UMFPACK_CONTROL], int status, std::complex) +{ umfpack_zi_report_status(control, status);} + +inline void umfpack_report_control(double control[UMFPACK_CONTROL], double) +{ umfpack_di_report_control(control);} + +inline void umfpack_report_control(double control[UMFPACK_CONTROL], std::complex) +{ umfpack_zi_report_control(control);} + inline void umfpack_free_numeric(void **Numeric, double) { umfpack_di_free_numeric(Numeric); *Numeric = 0; } @@ -156,6 +174,7 @@ class UmfPackLU : public SparseSolverBase > public: typedef Array UmfpackControl; + typedef Array UmfpackInfo; UmfPackLU() : m_dummy(0,0), mp_matrix(m_dummy) @@ -215,7 +234,7 @@ class UmfPackLU : public SparseSolverBase > return m_q; } - /** Computes the sparse Cholesky decomposition of \a matrix + /** Computes the sparse Cholesky decomposition of \a matrix * Note that the matrix should be column-major, and in compressed format for best performance. * \sa SparseMatrix::makeCompressed(). */ @@ -240,7 +259,7 @@ class UmfPackLU : public SparseSolverBase > { if(m_symbolic) umfpack_free_symbolic(&m_symbolic,Scalar()); if(m_numeric) umfpack_free_numeric(&m_numeric,Scalar()); - + grab(matrix.derived()); analyzePattern_impl(); @@ -267,7 +286,7 @@ class UmfPackLU : public SparseSolverBase > { return m_control; } - + /** Provides access to the control settings array used by UmfPack. * * If this array contains NaN's, the default values are used. @@ -278,7 +297,7 @@ class UmfPackLU : public SparseSolverBase > { return m_control; } - + /** Performs a numeric decomposition of \a matrix * * The given matrix must has the same sparcity than the matrix on which the pattern anylysis has been performed. @@ -293,10 +312,38 @@ class UmfPackLU : public SparseSolverBase > umfpack_free_numeric(&m_numeric,Scalar()); grab(matrix.derived()); - + factorize_impl(); } + /** Prints the current UmfPack control settings. + * + * \sa umfpackControl() + */ + void umfpackReportControl() + { + umfpack_report_control(m_control.data(), Scalar()); + } + + /** Prints statistics collected by UmfPack. + * + * \sa analyzePattern(), compute() + */ + void umfpackReportInfo() + { + eigen_assert(m_analysisIsOk && "UmfPackLU: you must first call analyzePattern()"); + umfpack_report_info(m_control.data(), m_umfpackInfo.data(), Scalar()); + } + + /** Prints the status of the previous factorization operation performed by UmfPack (symbolic or numerical factorization). + * + * \sa analyzePattern(), compute() + */ + void umfpackReportStatus() { + eigen_assert(m_analysisIsOk && "UmfPackLU: you must first call analyzePattern()"); + umfpack_report_status(m_control.data(), m_fact_errorCode, Scalar()); + } + /** \internal */ template bool _solve_impl(const MatrixBase &b, MatrixBase &x) const; @@ -314,41 +361,42 @@ class UmfPackLU : public SparseSolverBase > m_numeric = 0; m_symbolic = 0; m_extractedDataAreDirty = true; + + umfpack_defaults(m_control.data(), Scalar()); } - + void analyzePattern_impl() { - umfpack_defaults(m_control.data(), Scalar()); - int errorCode = 0; - errorCode = umfpack_symbolic(internal::convert_index(mp_matrix.rows()), - internal::convert_index(mp_matrix.cols()), - mp_matrix.outerIndexPtr(), mp_matrix.innerIndexPtr(), mp_matrix.valuePtr(), - &m_symbolic, m_control.data(), 0); + m_fact_errorCode = umfpack_symbolic(internal::convert_index(mp_matrix.rows()), + internal::convert_index(mp_matrix.cols()), + mp_matrix.outerIndexPtr(), mp_matrix.innerIndexPtr(), mp_matrix.valuePtr(), + &m_symbolic, m_control.data(), m_umfpackInfo.data()); m_isInitialized = true; - m_info = errorCode ? InvalidInput : Success; + m_info = m_fact_errorCode ? InvalidInput : Success; m_analysisIsOk = true; m_factorizationIsOk = false; m_extractedDataAreDirty = true; } - + void factorize_impl() { + m_fact_errorCode = umfpack_numeric(mp_matrix.outerIndexPtr(), mp_matrix.innerIndexPtr(), mp_matrix.valuePtr(), - m_symbolic, &m_numeric, m_control.data(), 0); + m_symbolic, &m_numeric, m_control.data(), m_umfpackInfo.data()); m_info = m_fact_errorCode == UMFPACK_OK ? Success : NumericalIssue; m_factorizationIsOk = true; m_extractedDataAreDirty = true; } - + template void grab(const EigenBase &A) { mp_matrix.~UmfpackMatrixRef(); ::new (&mp_matrix) UmfpackMatrixRef(A.derived()); } - + void grab(const UmfpackMatrixRef &A) { if(&(A.derived()) != &mp_matrix) @@ -357,19 +405,20 @@ class UmfPackLU : public SparseSolverBase > ::new (&mp_matrix) UmfpackMatrixRef(A); } } - + // cached data to reduce reallocation, etc. mutable LUMatrixType m_l; int m_fact_errorCode; UmfpackControl m_control; - + mutable UmfpackInfo m_umfpackInfo; + mutable LUMatrixType m_u; mutable IntColVectorType m_p; mutable IntRowVectorType m_q; UmfpackMatrixType m_dummy; UmfpackMatrixRef mp_matrix; - + void* m_numeric; void* m_symbolic; @@ -377,7 +426,7 @@ class UmfPackLU : public SparseSolverBase > int m_factorizationIsOk; int m_analysisIsOk; mutable bool m_extractedDataAreDirty; - + private: UmfPackLU(const UmfPackLU& ) { } }; @@ -427,7 +476,7 @@ bool UmfPackLU::_solve_impl(const MatrixBase &b, MatrixBas eigen_assert((BDerived::Flags&RowMajorBit)==0 && "UmfPackLU backend does not support non col-major rhs yet"); eigen_assert((XDerived::Flags&RowMajorBit)==0 && "UmfPackLU backend does not support non col-major result yet"); eigen_assert(b.derived().data() != x.derived().data() && " Umfpack does not support inplace solve"); - + int errorCode; Scalar* x_ptr = 0; Matrix x_tmp; @@ -442,7 +491,7 @@ bool UmfPackLU::_solve_impl(const MatrixBase &b, MatrixBas x_ptr = &x.col(j).coeffRef(0); errorCode = umfpack_solve(UMFPACK_A, mp_matrix.outerIndexPtr(), mp_matrix.innerIndexPtr(), mp_matrix.valuePtr(), - x_ptr, &b.const_cast_derived().col(j).coeffRef(0), m_numeric, m_control.data(), 0); + x_ptr, &b.const_cast_derived().col(j).coeffRef(0), m_numeric, m_control.data(), m_umfpackInfo.data()); if(x.innerStride()!=1) x.col(j) = x_tmp; if (errorCode!=0) diff --git a/xs/src/eigen/README.md b/xs/src/eigen/README.md index f56262cca..39892c00b 100644 --- a/xs/src/eigen/README.md +++ b/xs/src/eigen/README.md @@ -1,5 +1,5 @@ THIS IS NOT THE COMPLETE EIGEN DISTRIBUTION. ONLY FILES NEEDED FOR COMPILING EIGEN INTO SLIC3R WERE PUT INTO THE SLIC3R SOURCE DISTRIBUTION. -THIS DIRECTORY CONTAINS PIECES OF THE EIGEN 3.3.3 SOURCE DISTRIBUTION. +THIS DIRECTORY CONTAINS PIECES OF THE EIGEN 3.3.5 b3f3d4950030 SOURCE DISTRIBUTION. **Eigen is a C++ template library for linear algebra: matrices, vectors, numerical solvers, and related algorithms.** diff --git a/xs/src/libnest2d/libnest2d/geometry_traits.hpp b/xs/src/libnest2d/libnest2d/geometry_traits.hpp index 058c47cd4..8427c0552 100644 --- a/xs/src/libnest2d/libnest2d/geometry_traits.hpp +++ b/xs/src/libnest2d/libnest2d/geometry_traits.hpp @@ -163,25 +163,25 @@ struct PointLike { template static TCoord x(const RawPoint& p) { - return p.x(); + return p(0); } template static TCoord y(const RawPoint& p) { - return p.y(); + return p(1); } template static TCoord& x(RawPoint& p) { - return p.x(); + return p(0); } template static TCoord& y(RawPoint& p) { - return p.y(); + return p(1); } template diff --git a/xs/src/libslic3r/BoundingBox.cpp b/xs/src/libslic3r/BoundingBox.cpp index 4355cd61b..d3cca7ff2 100644 --- a/xs/src/libslic3r/BoundingBox.cpp +++ b/xs/src/libslic3r/BoundingBox.cpp @@ -7,9 +7,9 @@ namespace Slic3r { template BoundingBoxBase::BoundingBoxBase(const std::vector &points); -template BoundingBoxBase::BoundingBoxBase(const std::vector &points); +template BoundingBoxBase::BoundingBoxBase(const std::vector &points); -template BoundingBox3Base::BoundingBox3Base(const std::vector &points); +template BoundingBox3Base::BoundingBox3Base(const std::vector &points); BoundingBox::BoundingBox(const Lines &lines) { @@ -22,23 +22,21 @@ BoundingBox::BoundingBox(const Lines &lines) *this = BoundingBox(points); } -void -BoundingBox::polygon(Polygon* polygon) const +void BoundingBox::polygon(Polygon* polygon) const { polygon->points.clear(); polygon->points.resize(4); - polygon->points[0].x = this->min.x; - polygon->points[0].y = this->min.y; - polygon->points[1].x = this->max.x; - polygon->points[1].y = this->min.y; - polygon->points[2].x = this->max.x; - polygon->points[2].y = this->max.y; - polygon->points[3].x = this->min.x; - polygon->points[3].y = this->max.y; + polygon->points[0](0) = this->min(0); + polygon->points[0](1) = this->min(1); + polygon->points[1](0) = this->max(0); + polygon->points[1](1) = this->min(1); + polygon->points[2](0) = this->max(0); + polygon->points[2](1) = this->max(1); + polygon->points[3](0) = this->min(0); + polygon->points[3](1) = this->max(1); } -Polygon -BoundingBox::polygon() const +Polygon BoundingBox::polygon() const { Polygon p; this->polygon(&p); @@ -50,8 +48,8 @@ BoundingBox BoundingBox::rotated(double angle) const BoundingBox out; out.merge(this->min.rotated(angle)); out.merge(this->max.rotated(angle)); - out.merge(Point(this->min.x, this->max.y).rotated(angle)); - out.merge(Point(this->max.x, this->min.y).rotated(angle)); + out.merge(Point(this->min(0), this->max(1)).rotated(angle)); + out.merge(Point(this->max(0), this->min(1)).rotated(angle)); return out; } @@ -60,36 +58,35 @@ BoundingBox BoundingBox::rotated(double angle, const Point ¢er) const BoundingBox out; out.merge(this->min.rotated(angle, center)); out.merge(this->max.rotated(angle, center)); - out.merge(Point(this->min.x, this->max.y).rotated(angle, center)); - out.merge(Point(this->max.x, this->min.y).rotated(angle, center)); + out.merge(Point(this->min(0), this->max(1)).rotated(angle, center)); + out.merge(Point(this->max(0), this->min(1)).rotated(angle, center)); return out; } template void BoundingBoxBase::scale(double factor) { - this->min.scale(factor); - this->max.scale(factor); + this->min *= factor; + this->max *= factor; } template void BoundingBoxBase::scale(double factor); -template void BoundingBoxBase::scale(double factor); -template void BoundingBoxBase::scale(double factor); +template void BoundingBoxBase::scale(double factor); +template void BoundingBoxBase::scale(double factor); template void BoundingBoxBase::merge(const PointClass &point) { if (this->defined) { - this->min.x = std::min(point.x, this->min.x); - this->min.y = std::min(point.y, this->min.y); - this->max.x = std::max(point.x, this->max.x); - this->max.y = std::max(point.y, this->max.y); + this->min = this->min.cwiseMin(point); + this->max = this->max.cwiseMax(point); } else { - this->min = this->max = point; + this->min = point; + this->max = point; this->defined = true; } } template void BoundingBoxBase::merge(const Point &point); -template void BoundingBoxBase::merge(const Pointf &point); +template void BoundingBoxBase::merge(const Vec2d &point); template void BoundingBoxBase::merge(const std::vector &points) @@ -97,18 +94,16 @@ BoundingBoxBase::merge(const std::vector &points) this->merge(BoundingBoxBase(points)); } template void BoundingBoxBase::merge(const Points &points); -template void BoundingBoxBase::merge(const Pointfs &points); +template void BoundingBoxBase::merge(const Pointfs &points); template void BoundingBoxBase::merge(const BoundingBoxBase &bb) { - assert(bb.defined || bb.min.x >= bb.max.x || bb.min.y >= bb.max.y); + assert(bb.defined || bb.min(0) >= bb.max(0) || bb.min(1) >= bb.max(1)); if (bb.defined) { if (this->defined) { - this->min.x = std::min(bb.min.x, this->min.x); - this->min.y = std::min(bb.min.y, this->min.y); - this->max.x = std::max(bb.max.x, this->max.x); - this->max.y = std::max(bb.max.y, this->max.y); + this->min = this->min.cwiseMin(bb.min); + this->max = this->max.cwiseMax(bb.max); } else { this->min = bb.min; this->max = bb.max; @@ -117,120 +112,121 @@ BoundingBoxBase::merge(const BoundingBoxBase &bb) } } template void BoundingBoxBase::merge(const BoundingBoxBase &bb); -template void BoundingBoxBase::merge(const BoundingBoxBase &bb); +template void BoundingBoxBase::merge(const BoundingBoxBase &bb); template void BoundingBox3Base::merge(const PointClass &point) { if (this->defined) { - this->min.z = std::min(point.z, this->min.z); - this->max.z = std::max(point.z, this->max.z); + this->min = this->min.cwiseMin(point); + this->max = this->max.cwiseMax(point); + } else { + this->min = point; + this->max = point; + this->defined = true; } - BoundingBoxBase::merge(point); } -template void BoundingBox3Base::merge(const Pointf3 &point); +template void BoundingBox3Base::merge(const Vec3d &point); template void BoundingBox3Base::merge(const std::vector &points) { this->merge(BoundingBox3Base(points)); } -template void BoundingBox3Base::merge(const Pointf3s &points); +template void BoundingBox3Base::merge(const Pointf3s &points); template void BoundingBox3Base::merge(const BoundingBox3Base &bb) { - assert(bb.defined || bb.min.x >= bb.max.x || bb.min.y >= bb.max.y || bb.min.z >= bb.max.z); + assert(bb.defined || bb.min(0) >= bb.max(0) || bb.min(1) >= bb.max(1) || bb.min(2) >= bb.max(2)); if (bb.defined) { if (this->defined) { - this->min.z = std::min(bb.min.z, this->min.z); - this->max.z = std::max(bb.max.z, this->max.z); + this->min = this->min.cwiseMin(bb.min); + this->max = this->max.cwiseMax(bb.max); + } else { + this->min = bb.min; + this->max = bb.max; + this->defined = true; } - BoundingBoxBase::merge(bb); } } -template void BoundingBox3Base::merge(const BoundingBox3Base &bb); +template void BoundingBox3Base::merge(const BoundingBox3Base &bb); template PointClass BoundingBoxBase::size() const { - return PointClass(this->max.x - this->min.x, this->max.y - this->min.y); + return PointClass(this->max(0) - this->min(0), this->max(1) - this->min(1)); } template Point BoundingBoxBase::size() const; -template Pointf BoundingBoxBase::size() const; +template Vec2d BoundingBoxBase::size() const; template PointClass BoundingBox3Base::size() const { - return PointClass(this->max.x - this->min.x, this->max.y - this->min.y, this->max.z - this->min.z); + return PointClass(this->max(0) - this->min(0), this->max(1) - this->min(1), this->max(2) - this->min(2)); } -template Pointf3 BoundingBox3Base::size() const; +template Vec3d BoundingBox3Base::size() const; template double BoundingBoxBase::radius() const { assert(this->defined); - double x = this->max.x - this->min.x; - double y = this->max.y - this->min.y; + double x = this->max(0) - this->min(0); + double y = this->max(1) - this->min(1); return 0.5 * sqrt(x*x+y*y); } template double BoundingBoxBase::radius() const; -template double BoundingBoxBase::radius() const; +template double BoundingBoxBase::radius() const; template double BoundingBox3Base::radius() const { - double x = this->max.x - this->min.x; - double y = this->max.y - this->min.y; - double z = this->max.z - this->min.z; + double x = this->max(0) - this->min(0); + double y = this->max(1) - this->min(1); + double z = this->max(2) - this->min(2); return 0.5 * sqrt(x*x+y*y+z*z); } -template double BoundingBox3Base::radius() const; +template double BoundingBox3Base::radius() const; template void BoundingBoxBase::offset(coordf_t delta) { - this->min.translate(-delta, -delta); - this->max.translate(delta, delta); + PointClass v(delta, delta); + this->min -= v; + this->max += v; } template void BoundingBoxBase::offset(coordf_t delta); -template void BoundingBoxBase::offset(coordf_t delta); +template void BoundingBoxBase::offset(coordf_t delta); template void BoundingBox3Base::offset(coordf_t delta) { - this->min.translate(-delta, -delta, -delta); - this->max.translate(delta, delta, delta); + PointClass v(delta, delta, delta); + this->min -= v; + this->max += v; } -template void BoundingBox3Base::offset(coordf_t delta); +template void BoundingBox3Base::offset(coordf_t delta); template PointClass BoundingBoxBase::center() const { - return PointClass( - (this->max.x + this->min.x)/2, - (this->max.y + this->min.y)/2 - ); + return (this->min + this->max) / 2; } template Point BoundingBoxBase::center() const; -template Pointf BoundingBoxBase::center() const; +template Vec2d BoundingBoxBase::center() const; template PointClass BoundingBox3Base::center() const { - return PointClass( - (this->max.x + this->min.x)/2, - (this->max.y + this->min.y)/2, - (this->max.z + this->min.z)/2 - ); + return (this->min + this->max) / 2; } -template Pointf3 BoundingBox3Base::center() const; +template Vec3d BoundingBox3Base::center() const; template coordf_t BoundingBox3Base::max_size() const { PointClass s = size(); - return std::max(s.x, std::max(s.y, s.z)); + return std::max(s(0), std::max(s(1), s(2))); } -template coordf_t BoundingBox3Base::max_size() const; +template coordf_t BoundingBox3Base::max_size() const; // Align a coordinate to a grid. The coordinate may be negative, // the aligned value will never be bigger than the original one. @@ -248,46 +244,40 @@ static inline coord_t _align_to_grid(const coord_t coord, const coord_t spacing) void BoundingBox::align_to_grid(const coord_t cell_size) { if (this->defined) { - min.x = _align_to_grid(min.x, cell_size); - min.y = _align_to_grid(min.y, cell_size); + min(0) = _align_to_grid(min(0), cell_size); + min(1) = _align_to_grid(min(1), cell_size); } } -BoundingBoxf3 BoundingBoxf3::transformed(const std::vector& matrix) const +BoundingBoxf3 BoundingBoxf3::transformed(const Transform3d& matrix) const { - Eigen::Matrix vertices; + typedef Eigen::Matrix Vertices; - vertices(0, 0) = (float)min.x; vertices(1, 0) = (float)min.y; vertices(2, 0) = (float)min.z; - vertices(0, 1) = (float)max.x; vertices(1, 1) = (float)min.y; vertices(2, 1) = (float)min.z; - vertices(0, 2) = (float)max.x; vertices(1, 2) = (float)max.y; vertices(2, 2) = (float)min.z; - vertices(0, 3) = (float)min.x; vertices(1, 3) = (float)max.y; vertices(2, 3) = (float)min.z; - vertices(0, 4) = (float)min.x; vertices(1, 4) = (float)min.y; vertices(2, 4) = (float)max.z; - vertices(0, 5) = (float)max.x; vertices(1, 5) = (float)min.y; vertices(2, 5) = (float)max.z; - vertices(0, 6) = (float)max.x; vertices(1, 6) = (float)max.y; vertices(2, 6) = (float)max.z; - vertices(0, 7) = (float)min.x; vertices(1, 7) = (float)max.y; vertices(2, 7) = (float)max.z; + Vertices src_vertices; + src_vertices(0, 0) = min(0); src_vertices(1, 0) = min(1); src_vertices(2, 0) = min(2); + src_vertices(0, 1) = max(0); src_vertices(1, 1) = min(1); src_vertices(2, 1) = min(2); + src_vertices(0, 2) = max(0); src_vertices(1, 2) = max(1); src_vertices(2, 2) = min(2); + src_vertices(0, 3) = min(0); src_vertices(1, 3) = max(1); src_vertices(2, 3) = min(2); + src_vertices(0, 4) = min(0); src_vertices(1, 4) = min(1); src_vertices(2, 4) = max(2); + src_vertices(0, 5) = max(0); src_vertices(1, 5) = min(1); src_vertices(2, 5) = max(2); + src_vertices(0, 6) = max(0); src_vertices(1, 6) = max(1); src_vertices(2, 6) = max(2); + src_vertices(0, 7) = min(0); src_vertices(1, 7) = max(1); src_vertices(2, 7) = max(2); - Eigen::Transform m; - ::memcpy((void*)m.data(), (const void*)matrix.data(), 16 * sizeof(float)); - Eigen::Matrix transf_vertices = m * vertices.colwise().homogeneous(); + Vertices dst_vertices = matrix * src_vertices.colwise().homogeneous(); - float min_x = transf_vertices(0, 0); - float max_x = transf_vertices(0, 0); - float min_y = transf_vertices(1, 0); - float max_y = transf_vertices(1, 0); - float min_z = transf_vertices(2, 0); - float max_z = transf_vertices(2, 0); + Vec3d v_min(dst_vertices(0, 0), dst_vertices(1, 0), dst_vertices(2, 0)); + Vec3d v_max = v_min; for (int i = 1; i < 8; ++i) { - min_x = std::min(min_x, transf_vertices(0, i)); - max_x = std::max(max_x, transf_vertices(0, i)); - min_y = std::min(min_y, transf_vertices(1, i)); - max_y = std::max(max_y, transf_vertices(1, i)); - min_z = std::min(min_z, transf_vertices(2, i)); - max_z = std::max(max_z, transf_vertices(2, i)); + for (int j = 0; j < 3; ++j) + { + v_min(j) = std::min(v_min(j), dst_vertices(j, i)); + v_max(j) = std::max(v_max(j), dst_vertices(j, i)); + } } - return BoundingBoxf3(Pointf3((coordf_t)min_x, (coordf_t)min_y, (coordf_t)min_z), Pointf3((coordf_t)max_x, (coordf_t)max_y, (coordf_t)max_z)); + return BoundingBoxf3(v_min, v_max); } } diff --git a/xs/src/libslic3r/BoundingBox.hpp b/xs/src/libslic3r/BoundingBox.hpp index 5324dbe3b..db56c765c 100644 --- a/xs/src/libslic3r/BoundingBox.hpp +++ b/xs/src/libslic3r/BoundingBox.hpp @@ -7,11 +7,6 @@ namespace Slic3r { -typedef Point Size; -typedef Point3 Size3; -typedef Pointf Sizef; -typedef Pointf3 Sizef3; - template class BoundingBoxBase { @@ -20,25 +15,22 @@ public: PointClass max; bool defined; - BoundingBoxBase() : defined(false) {}; + BoundingBoxBase() : defined(false), min(PointClass::Zero()), max(PointClass::Zero()) {} BoundingBoxBase(const PointClass &pmin, const PointClass &pmax) : - min(pmin), max(pmax), defined(pmin.x < pmax.x && pmin.y < pmax.y) {} - BoundingBoxBase(const std::vector& points) + min(pmin), max(pmax), defined(pmin(0) < pmax(0) && pmin(1) < pmax(1)) {} + BoundingBoxBase(const std::vector& points) : min(PointClass::Zero()), max(PointClass::Zero()) { if (points.empty()) CONFESS("Empty point set supplied to BoundingBoxBase constructor"); typename std::vector::const_iterator it = points.begin(); - this->min.x = this->max.x = it->x; - this->min.y = this->max.y = it->y; - for (++it; it != points.end(); ++it) - { - this->min.x = std::min(it->x, this->min.x); - this->min.y = std::min(it->y, this->min.y); - this->max.x = std::max(it->x, this->max.x); - this->max.y = std::max(it->y, this->max.y); + this->min = *it; + this->max = *it; + for (++ it; it != points.end(); ++ it) { + this->min = this->min.cwiseMin(*it); + this->max = this->max.cwiseMax(*it); } - this->defined = (this->min.x < this->max.x) && (this->min.y < this->max.y); + this->defined = (this->min(0) < this->max(0)) && (this->min(1) < this->max(1)); } void merge(const PointClass &point); void merge(const std::vector &points); @@ -46,17 +38,17 @@ public: void scale(double factor); PointClass size() const; double radius() const; - void translate(coordf_t x, coordf_t y) { assert(this->defined); this->min.translate(x, y); this->max.translate(x, y); } - void translate(const Pointf &pos) { this->translate(pos.x, pos.y); } + void translate(coordf_t x, coordf_t y) { assert(this->defined); PointClass v(x, y); this->min += v; this->max += v; } + void translate(const Vec2d &v) { this->min += v; this->max += v; } void offset(coordf_t delta); PointClass center() const; bool contains(const PointClass &point) const { - return point.x >= this->min.x && point.x <= this->max.x - && point.y >= this->min.y && point.y <= this->max.y; + return point(0) >= this->min(0) && point(0) <= this->max(0) + && point(1) >= this->min(1) && point(1) <= this->max(1); } bool overlap(const BoundingBoxBase &other) const { - return ! (this->max.x < other.min.x || this->min.x > other.max.x || - this->max.y < other.min.y || this->min.y > other.max.y); + return ! (this->max(0) < other.min(0) || this->min(0) > other.max(0) || + this->max(1) < other.min(1) || this->min(1) > other.max(1)); } bool operator==(const BoundingBoxBase &rhs) { return this->min == rhs.min && this->max == rhs.max; } bool operator!=(const BoundingBoxBase &rhs) { return ! (*this == rhs); } @@ -69,35 +61,33 @@ public: BoundingBox3Base() : BoundingBoxBase() {}; BoundingBox3Base(const PointClass &pmin, const PointClass &pmax) : BoundingBoxBase(pmin, pmax) - { if (pmin.z >= pmax.z) BoundingBoxBase::defined = false; } + { if (pmin(2) >= pmax(2)) BoundingBoxBase::defined = false; } BoundingBox3Base(const std::vector& points) - : BoundingBoxBase(points) { if (points.empty()) CONFESS("Empty point set supplied to BoundingBox3Base constructor"); - typename std::vector::const_iterator it = points.begin(); - this->min.z = this->max.z = it->z; - for (++it; it != points.end(); ++it) - { - this->min.z = std::min(it->z, this->min.z); - this->max.z = std::max(it->z, this->max.z); + this->min = *it; + this->max = *it; + for (++ it; it != points.end(); ++ it) { + this->min = this->min.cwiseMin(*it); + this->max = this->max.cwiseMax(*it); } - this->defined &= (this->min.z < this->max.z); + this->defined = (this->min(0) < this->max(0)) && (this->min(1) < this->max(1)) && (this->min(2) < this->max(2)); } void merge(const PointClass &point); void merge(const std::vector &points); void merge(const BoundingBox3Base &bb); PointClass size() const; double radius() const; - void translate(coordf_t x, coordf_t y, coordf_t z) { this->min.translate(x, y, z); this->max.translate(x, y, z); } - void translate(const Pointf3 &pos) { this->translate(pos.x, pos.y, pos.z); } + void translate(coordf_t x, coordf_t y, coordf_t z) { assert(this->defined); PointClass v(x, y, z); this->min += v; this->max += v; } + void translate(const Vec3d &v) { this->min += v; this->max += v; } void offset(coordf_t delta); PointClass center() const; coordf_t max_size() const; bool contains(const PointClass &point) const { - return BoundingBoxBase::contains(point) && point.z >= this->min.z && point.z <= this->max.z; + return BoundingBoxBase::contains(point) && point(2) >= this->min(2) && point(2) <= this->max(2); } bool contains(const BoundingBox3Base& other) const { @@ -105,7 +95,7 @@ public: } bool intersects(const BoundingBox3Base& other) const { - return (this->min.x < other.max.x) && (this->max.x > other.min.x) && (this->min.y < other.max.y) && (this->max.y > other.min.y) && (this->min.z < other.max.z) && (this->max.z > other.min.z); + return (this->min(0) < other.max(0)) && (this->max(0) > other.min(0)) && (this->min(1) < other.max(1)) && (this->max(1) > other.min(1)) && (this->min(2) < other.max(2)) && (this->max(2) > other.min(2)); } }; @@ -130,42 +120,42 @@ public: friend BoundingBox get_extents_rotated(const Points &points, double angle); }; -class BoundingBox3 : public BoundingBox3Base +class BoundingBox3 : public BoundingBox3Base { public: - BoundingBox3() : BoundingBox3Base() {}; - BoundingBox3(const Point3 &pmin, const Point3 &pmax) : BoundingBox3Base(pmin, pmax) {}; - BoundingBox3(const Points3& points) : BoundingBox3Base(points) {}; + BoundingBox3() : BoundingBox3Base() {}; + BoundingBox3(const Vec3crd &pmin, const Vec3crd &pmax) : BoundingBox3Base(pmin, pmax) {}; + BoundingBox3(const Points3& points) : BoundingBox3Base(points) {}; }; -class BoundingBoxf : public BoundingBoxBase +class BoundingBoxf : public BoundingBoxBase { public: - BoundingBoxf() : BoundingBoxBase() {}; - BoundingBoxf(const Pointf &pmin, const Pointf &pmax) : BoundingBoxBase(pmin, pmax) {}; - BoundingBoxf(const std::vector &points) : BoundingBoxBase(points) {}; + BoundingBoxf() : BoundingBoxBase() {}; + BoundingBoxf(const Vec2d &pmin, const Vec2d &pmax) : BoundingBoxBase(pmin, pmax) {}; + BoundingBoxf(const std::vector &points) : BoundingBoxBase(points) {}; }; -class BoundingBoxf3 : public BoundingBox3Base +class BoundingBoxf3 : public BoundingBox3Base { public: - BoundingBoxf3() : BoundingBox3Base() {}; - BoundingBoxf3(const Pointf3 &pmin, const Pointf3 &pmax) : BoundingBox3Base(pmin, pmax) {}; - BoundingBoxf3(const std::vector &points) : BoundingBox3Base(points) {}; + BoundingBoxf3() : BoundingBox3Base() {}; + BoundingBoxf3(const Vec3d &pmin, const Vec3d &pmax) : BoundingBox3Base(pmin, pmax) {}; + BoundingBoxf3(const std::vector &points) : BoundingBox3Base(points) {}; - BoundingBoxf3 transformed(const std::vector& matrix) const; + BoundingBoxf3 transformed(const Transform3d& matrix) const; }; template inline bool empty(const BoundingBoxBase &bb) { - return ! bb.defined || bb.min.x >= bb.max.x || bb.min.y >= bb.max.y; + return ! bb.defined || bb.min(0) >= bb.max(0) || bb.min(1) >= bb.max(1); } template inline bool empty(const BoundingBox3Base &bb) { - return ! bb.defined || bb.min.x >= bb.max.x || bb.min.y >= bb.max.y || bb.min.z >= bb.max.z; + return ! bb.defined || bb.min(0) >= bb.max(0) || bb.min(1) >= bb.max(1) || bb.min(2) >= bb.max(2); } } // namespace Slic3r diff --git a/xs/src/libslic3r/BridgeDetector.cpp b/xs/src/libslic3r/BridgeDetector.cpp index a5272683f..ccc3505ce 100644 --- a/xs/src/libslic3r/BridgeDetector.cpp +++ b/xs/src/libslic3r/BridgeDetector.cpp @@ -102,16 +102,16 @@ bool BridgeDetector::detect_angle(double bridge_direction_override) // Get an oriented bounding box around _anchor_regions. BoundingBox bbox = get_extents_rotated(this->_anchor_regions, - angle); // Cover the region with line segments. - lines.reserve((bbox.max.y - bbox.min.y + this->spacing) / this->spacing); + lines.reserve((bbox.max(1) - bbox.min(1) + this->spacing) / this->spacing); double s = sin(angle); double c = cos(angle); //FIXME Vojtech: The lines shall be spaced half the line width from the edge, but then // some of the test cases fail. Need to adjust the test cases then? -// for (coord_t y = bbox.min.y + this->spacing / 2; y <= bbox.max.y; y += this->spacing) - for (coord_t y = bbox.min.y; y <= bbox.max.y; y += this->spacing) +// for (coord_t y = bbox.min(1) + this->spacing / 2; y <= bbox.max(1); y += this->spacing) + for (coord_t y = bbox.min(1); y <= bbox.max(1); y += this->spacing) lines.push_back(Line( - Point((coord_t)round(c * bbox.min.x - s * y), (coord_t)round(c * y + s * bbox.min.x)), - Point((coord_t)round(c * bbox.max.x - s * y), (coord_t)round(c * y + s * bbox.max.x)))); + Point((coord_t)round(c * bbox.min(0) - s * y), (coord_t)round(c * y + s * bbox.min(0))), + Point((coord_t)round(c * bbox.max(0) - s * y), (coord_t)round(c * y + s * bbox.max(0))))); } double total_length = 0; @@ -182,9 +182,9 @@ std::vector BridgeDetector::bridge_direction_candidates() const /* we also test angles of each open supporting edge (this finds the optimal angle for C-shaped supports) */ - for (Polylines::const_iterator edge = this->_edges.begin(); edge != this->_edges.end(); ++edge) - if (! edge->first_point().coincides_with(edge->last_point())) - angles.push_back(Line(edge->first_point(), edge->last_point()).direction()); + for (const Polyline &edge : this->_edges) + if (edge.first_point() != edge.last_point()) + angles.push_back(Line(edge.first_point(), edge.last_point()).direction()); // remove duplicates double min_resolution = PI/180.0; // 1 degree @@ -282,10 +282,12 @@ BridgeDetector::unsupported_edges(double angle, Polylines* unsupported) const extrusions would be anchored within such length (i.e. a slightly non-parallel bridging direction might still benefit from anchors if long enough) double angle_tolerance = PI / 180.0 * 5.0; */ - for (Lines::const_iterator line = unsupported_lines.begin(); line != unsupported_lines.end(); ++line) { - if (!Slic3r::Geometry::directions_parallel(line->direction(), angle)) - unsupported->push_back(*line); - } + for (const Line &line : unsupported_lines) + if (! Slic3r::Geometry::directions_parallel(line.direction(), angle)) { + unsupported->emplace_back(Polyline()); + unsupported->back().points.emplace_back(line.a); + unsupported->back().points.emplace_back(line.b); + } } /* diff --git a/xs/src/libslic3r/ClipperUtils.cpp b/xs/src/libslic3r/ClipperUtils.cpp index 31a12aa77..f00e908ce 100644 --- a/xs/src/libslic3r/ClipperUtils.cpp +++ b/xs/src/libslic3r/ClipperUtils.cpp @@ -171,7 +171,7 @@ Slic3rMultiPoint_to_ClipperPath(const MultiPoint &input) { ClipperLib::Path retval; for (Points::const_iterator pit = input.points.begin(); pit != input.points.end(); ++pit) - retval.push_back(ClipperLib::IntPoint( (*pit).x, (*pit).y )); + retval.push_back(ClipperLib::IntPoint( (*pit)(0), (*pit)(1) )); return retval; } @@ -181,7 +181,7 @@ Slic3rMultiPoint_to_ClipperPath_reversed(const Slic3r::MultiPoint &input) ClipperLib::Path output; output.reserve(input.points.size()); for (Slic3r::Points::const_reverse_iterator pit = input.points.rbegin(); pit != input.points.rend(); ++pit) - output.push_back(ClipperLib::IntPoint( (*pit).x, (*pit).y )); + output.push_back(ClipperLib::IntPoint( (*pit)(0), (*pit)(1) )); return output; } @@ -595,26 +595,26 @@ Polylines _clipper_pl(ClipperLib::ClipType clipType, const Polygons &subject, co to recombine continuous polylines. */ for (size_t i = 0; i < retval.size(); ++i) { for (size_t j = i+1; j < retval.size(); ++j) { - if (retval[i].points.back().coincides_with(retval[j].points.front())) { + if (retval[i].points.back() == retval[j].points.front()) { /* If last point of i coincides with first point of j, append points of j to i and delete j */ retval[i].points.insert(retval[i].points.end(), retval[j].points.begin()+1, retval[j].points.end()); retval.erase(retval.begin() + j); --j; - } else if (retval[i].points.front().coincides_with(retval[j].points.back())) { + } else if (retval[i].points.front() == retval[j].points.back()) { /* If first point of i coincides with last point of j, prepend points of j to i and delete j */ retval[i].points.insert(retval[i].points.begin(), retval[j].points.begin(), retval[j].points.end()-1); retval.erase(retval.begin() + j); --j; - } else if (retval[i].points.front().coincides_with(retval[j].points.front())) { + } else if (retval[i].points.front() == retval[j].points.front()) { /* Since Clipper does not preserve orientation of polylines, also check the case when first point of i coincides with first point of j. */ retval[j].reverse(); retval[i].points.insert(retval[i].points.begin(), retval[j].points.begin(), retval[j].points.end()-1); retval.erase(retval.begin() + j); --j; - } else if (retval[i].points.back().coincides_with(retval[j].points.back())) { + } else if (retval[i].points.back() == retval[j].points.back()) { /* Since Clipper does not preserve orientation of polylines, also check the case when last point of i coincides with last point of j. */ retval[j].reverse(); @@ -634,8 +634,8 @@ _clipper_ln(ClipperLib::ClipType clipType, const Lines &subject, const Polygons // convert Lines to Polylines Polylines polylines; polylines.reserve(subject.size()); - for (Lines::const_iterator line = subject.begin(); line != subject.end(); ++line) - polylines.push_back(*line); + for (const Line &line : subject) + polylines.emplace_back(Polyline(line.a, line.b)); // perform operation polylines = _clipper_pl(clipType, polylines, clip, safety_offset_); diff --git a/xs/src/libslic3r/Config.hpp b/xs/src/libslic3r/Config.hpp index 377bdbea4..7f75f815d 100644 --- a/xs/src/libslic3r/Config.hpp +++ b/xs/src/libslic3r/Config.hpp @@ -622,11 +622,11 @@ public: } }; -class ConfigOptionPoint : public ConfigOptionSingle +class ConfigOptionPoint : public ConfigOptionSingle { public: - ConfigOptionPoint() : ConfigOptionSingle(Pointf(0,0)) {} - explicit ConfigOptionPoint(const Pointf &value) : ConfigOptionSingle(value) {} + ConfigOptionPoint() : ConfigOptionSingle(Vec2d(0,0)) {} + explicit ConfigOptionPoint(const Vec2d &value) : ConfigOptionSingle(value) {} static ConfigOptionType static_type() { return coPoint; } ConfigOptionType type() const override { return static_type(); } @@ -637,9 +637,9 @@ public: std::string serialize() const override { std::ostringstream ss; - ss << this->value.x; + ss << this->value(0); ss << ","; - ss << this->value.y; + ss << this->value(1); return ss.str(); } @@ -647,18 +647,18 @@ public: { UNUSED(append); char dummy; - return sscanf(str.data(), " %lf , %lf %c", &this->value.x, &this->value.y, &dummy) == 2 || - sscanf(str.data(), " %lf x %lf %c", &this->value.x, &this->value.y, &dummy) == 2; + return sscanf(str.data(), " %lf , %lf %c", &this->value(0), &this->value(1), &dummy) == 2 || + sscanf(str.data(), " %lf x %lf %c", &this->value(0), &this->value(1), &dummy) == 2; } }; -class ConfigOptionPoints : public ConfigOptionVector +class ConfigOptionPoints : public ConfigOptionVector { public: - ConfigOptionPoints() : ConfigOptionVector() {} - explicit ConfigOptionPoints(size_t n, const Pointf &value) : ConfigOptionVector(n, value) {} - explicit ConfigOptionPoints(std::initializer_list il) : ConfigOptionVector(std::move(il)) {} - explicit ConfigOptionPoints(const std::vector &values) : ConfigOptionVector(values) {} + ConfigOptionPoints() : ConfigOptionVector() {} + explicit ConfigOptionPoints(size_t n, const Vec2d &value) : ConfigOptionVector(n, value) {} + explicit ConfigOptionPoints(std::initializer_list il) : ConfigOptionVector(std::move(il)) {} + explicit ConfigOptionPoints(const std::vector &values) : ConfigOptionVector(values) {} static ConfigOptionType static_type() { return coPoints; } ConfigOptionType type() const override { return static_type(); } @@ -671,9 +671,9 @@ public: std::ostringstream ss; for (Pointfs::const_iterator it = this->values.begin(); it != this->values.end(); ++it) { if (it - this->values.begin() != 0) ss << ","; - ss << it->x; + ss << (*it)(0); ss << "x"; - ss << it->y; + ss << (*it)(1); } return ss.str(); } @@ -696,13 +696,13 @@ public: std::istringstream is(str); std::string point_str; while (std::getline(is, point_str, ',')) { - Pointf point; + Vec2d point(Vec2d::Zero()); std::istringstream iss(point_str); std::string coord_str; if (std::getline(iss, coord_str, 'x')) { - std::istringstream(coord_str) >> point.x; + std::istringstream(coord_str) >> point(0); if (std::getline(iss, coord_str, 'x')) { - std::istringstream(coord_str) >> point.y; + std::istringstream(coord_str) >> point(1); } } this->values.push_back(point); diff --git a/xs/src/libslic3r/EdgeGrid.cpp b/xs/src/libslic3r/EdgeGrid.cpp index 733ff2ad7..50f424e6d 100644 --- a/xs/src/libslic3r/EdgeGrid.cpp +++ b/xs/src/libslic3r/EdgeGrid.cpp @@ -117,15 +117,15 @@ void EdgeGrid::Grid::create_from_m_contours(coord_t resolution) m_bbox.merge(pts[j]); } coord_t eps = 16; - m_bbox.min.x -= eps; - m_bbox.min.y -= eps; - m_bbox.max.x += eps; - m_bbox.max.y += eps; + m_bbox.min(0) -= eps; + m_bbox.min(1) -= eps; + m_bbox.max(0) += eps; + m_bbox.max(1) += eps; // 2) Initialize the edge grid. m_resolution = resolution; - m_cols = (m_bbox.max.x - m_bbox.min.x + m_resolution - 1) / m_resolution; - m_rows = (m_bbox.max.y - m_bbox.min.y + m_resolution - 1) / m_resolution; + m_cols = (m_bbox.max(0) - m_bbox.min(0) + m_resolution - 1) / m_resolution; + m_rows = (m_bbox.max(1) - m_bbox.min(1) + m_resolution - 1) / m_resolution; m_cells.assign(m_rows * m_cols, Cell()); // 3) First round of contour rasterization, count the edges per grid cell. @@ -135,15 +135,15 @@ void EdgeGrid::Grid::create_from_m_contours(coord_t resolution) // End points of the line segment. Slic3r::Point p1(pts[j]); Slic3r::Point p2 = pts[(j + 1 == pts.size()) ? 0 : j + 1]; - p1.x -= m_bbox.min.x; - p1.y -= m_bbox.min.y; - p2.x -= m_bbox.min.x; - p2.y -= m_bbox.min.y; + p1(0) -= m_bbox.min(0); + p1(1) -= m_bbox.min(1); + p2(0) -= m_bbox.min(0); + p2(1) -= m_bbox.min(1); // Get the cells of the end points. - coord_t ix = p1.x / m_resolution; - coord_t iy = p1.y / m_resolution; - coord_t ixb = p2.x / m_resolution; - coord_t iyb = p2.y / m_resolution; + coord_t ix = p1(0) / m_resolution; + coord_t iy = p1(1) / m_resolution; + coord_t ixb = p2(0) / m_resolution; + coord_t iyb = p2(1) / m_resolution; assert(ix >= 0 && ix < m_cols); assert(iy >= 0 && iy < m_rows); assert(ixb >= 0 && ixb < m_cols); @@ -154,13 +154,13 @@ void EdgeGrid::Grid::create_from_m_contours(coord_t resolution) // Both ends fall into the same cell. continue; // Raster the centeral part of the line. - coord_t dx = std::abs(p2.x - p1.x); - coord_t dy = std::abs(p2.y - p1.y); - if (p1.x < p2.x) { - int64_t ex = int64_t((ix + 1)*m_resolution - p1.x) * int64_t(dy); - if (p1.y < p2.y) { + coord_t dx = std::abs(p2(0) - p1(0)); + coord_t dy = std::abs(p2(1) - p1(1)); + if (p1(0) < p2(0)) { + int64_t ex = int64_t((ix + 1)*m_resolution - p1(0)) * int64_t(dy); + if (p1(1) < p2(1)) { // x positive, y positive - int64_t ey = int64_t((iy + 1)*m_resolution - p1.y) * int64_t(dx); + int64_t ey = int64_t((iy + 1)*m_resolution - p1(1)) * int64_t(dx); do { assert(ix <= ixb && iy <= iyb); if (ex < ey) { @@ -185,7 +185,7 @@ void EdgeGrid::Grid::create_from_m_contours(coord_t resolution) } else { // x positive, y non positive - int64_t ey = int64_t(p1.y - iy*m_resolution) * int64_t(dx); + int64_t ey = int64_t(p1(1) - iy*m_resolution) * int64_t(dx); do { assert(ix <= ixb && iy >= iyb); if (ex <= ey) { @@ -203,10 +203,10 @@ void EdgeGrid::Grid::create_from_m_contours(coord_t resolution) } } else { - int64_t ex = int64_t(p1.x - ix*m_resolution) * int64_t(dy); - if (p1.y < p2.y) { + int64_t ex = int64_t(p1(0) - ix*m_resolution) * int64_t(dy); + if (p1(1) < p2(1)) { // x non positive, y positive - int64_t ey = int64_t((iy + 1)*m_resolution - p1.y) * int64_t(dx); + int64_t ey = int64_t((iy + 1)*m_resolution - p1(1)) * int64_t(dx); do { assert(ix >= ixb && iy <= iyb); if (ex < ey) { @@ -225,7 +225,7 @@ void EdgeGrid::Grid::create_from_m_contours(coord_t resolution) } else { // x non positive, y non positive - int64_t ey = int64_t(p1.y - iy*m_resolution) * int64_t(dx); + int64_t ey = int64_t(p1(1) - iy*m_resolution) * int64_t(dx); do { assert(ix >= ixb && iy >= iyb); if (ex < ey) { @@ -279,15 +279,15 @@ void EdgeGrid::Grid::create_from_m_contours(coord_t resolution) // End points of the line segment. Slic3r::Point p1(pts[j]); Slic3r::Point p2 = pts[(j + 1 == pts.size()) ? 0 : j + 1]; - p1.x -= m_bbox.min.x; - p1.y -= m_bbox.min.y; - p2.x -= m_bbox.min.x; - p2.y -= m_bbox.min.y; + p1(0) -= m_bbox.min(0); + p1(1) -= m_bbox.min(1); + p2(0) -= m_bbox.min(0); + p2(1) -= m_bbox.min(1); // Get the cells of the end points. - coord_t ix = p1.x / m_resolution; - coord_t iy = p1.y / m_resolution; - coord_t ixb = p2.x / m_resolution; - coord_t iyb = p2.y / m_resolution; + coord_t ix = p1(0) / m_resolution; + coord_t iy = p1(1) / m_resolution; + coord_t ixb = p2(0) / m_resolution; + coord_t iyb = p2(1) / m_resolution; assert(ix >= 0 && ix < m_cols); assert(iy >= 0 && iy < m_rows); assert(ixb >= 0 && ixb < m_cols); @@ -298,13 +298,13 @@ void EdgeGrid::Grid::create_from_m_contours(coord_t resolution) // Both ends fall into the same cell. continue; // Raster the centeral part of the line. - coord_t dx = std::abs(p2.x - p1.x); - coord_t dy = std::abs(p2.y - p1.y); - if (p1.x < p2.x) { - int64_t ex = int64_t((ix + 1)*m_resolution - p1.x) * int64_t(dy); - if (p1.y < p2.y) { + coord_t dx = std::abs(p2(0) - p1(0)); + coord_t dy = std::abs(p2(1) - p1(1)); + if (p1(0) < p2(0)) { + int64_t ex = int64_t((ix + 1)*m_resolution - p1(0)) * int64_t(dy); + if (p1(1) < p2(1)) { // x positive, y positive - int64_t ey = int64_t((iy + 1)*m_resolution - p1.y) * int64_t(dx); + int64_t ey = int64_t((iy + 1)*m_resolution - p1(1)) * int64_t(dx); do { assert(ix <= ixb && iy <= iyb); if (ex < ey) { @@ -329,7 +329,7 @@ void EdgeGrid::Grid::create_from_m_contours(coord_t resolution) } else { // x positive, y non positive - int64_t ey = int64_t(p1.y - iy*m_resolution) * int64_t(dx); + int64_t ey = int64_t(p1(1) - iy*m_resolution) * int64_t(dx); do { assert(ix <= ixb && iy >= iyb); if (ex <= ey) { @@ -347,10 +347,10 @@ void EdgeGrid::Grid::create_from_m_contours(coord_t resolution) } } else { - int64_t ex = int64_t(p1.x - ix*m_resolution) * int64_t(dy); - if (p1.y < p2.y) { + int64_t ex = int64_t(p1(0) - ix*m_resolution) * int64_t(dy); + if (p1(1) < p2(1)) { // x non positive, y positive - int64_t ey = int64_t((iy + 1)*m_resolution - p1.y) * int64_t(dx); + int64_t ey = int64_t((iy + 1)*m_resolution - p1(1)) * int64_t(dx); do { assert(ix >= ixb && iy <= iyb); if (ex < ey) { @@ -369,7 +369,7 @@ void EdgeGrid::Grid::create_from_m_contours(coord_t resolution) } else { // x non positive, y non positive - int64_t ey = int64_t(p1.y - iy*m_resolution) * int64_t(dx); + int64_t ey = int64_t(p1(1) - iy*m_resolution) * int64_t(dx); do { assert(ix >= ixb && iy >= iyb); if (ex < ey) { @@ -429,15 +429,15 @@ bool EdgeGrid::Grid::intersect(const MultiPoint &polyline, bool closed) Point p1 = p1src; Point p2 = p2src; // Discretize the line segment p1, p2. - p1.x -= m_bbox.min.x; - p1.y -= m_bbox.min.y; - p2.x -= m_bbox.min.x; - p2.y -= m_bbox.min.y; + p1(0) -= m_bbox.min(0); + p1(1) -= m_bbox.min(1); + p2(0) -= m_bbox.min(0); + p2(1) -= m_bbox.min(1); // Get the cells of the end points. - coord_t ix = div_floor(p1.x, m_resolution); - coord_t iy = div_floor(p1.y, m_resolution); - coord_t ixb = div_floor(p2.x, m_resolution); - coord_t iyb = div_floor(p2.y, m_resolution); + coord_t ix = div_floor(p1(0), m_resolution); + coord_t iy = div_floor(p1(1), m_resolution); + coord_t ixb = div_floor(p2(0), m_resolution); + coord_t iyb = div_floor(p2(1), m_resolution); // assert(ix >= 0 && ix < m_cols); // assert(iy >= 0 && iy < m_rows); // assert(ixb >= 0 && ixb < m_cols); @@ -449,12 +449,12 @@ bool EdgeGrid::Grid::intersect(const MultiPoint &polyline, bool closed) // Both ends fall into the same cell. continue; // Raster the centeral part of the line. - coord_t dx = std::abs(p2.x - p1.x); - coord_t dy = std::abs(p2.y - p1.y); - if (p1.x < p2.x) { - int64_t ex = int64_t((ix + 1)*m_resolution - p1.x) * int64_t(dy); - if (p1.y < p2.y) { - int64_t ey = int64_t((iy + 1)*m_resolution - p1.y) * int64_t(dx); + coord_t dx = std::abs(p2(0) - p1(0)); + coord_t dy = std::abs(p2(1) - p1(1)); + if (p1(0) < p2(0)) { + int64_t ex = int64_t((ix + 1)*m_resolution - p1(0)) * int64_t(dy); + if (p1(1) < p2(1)) { + int64_t ey = int64_t((iy + 1)*m_resolution - p1(1)) * int64_t(dx); do { assert(ix <= ixb && iy <= iyb); if (ex < ey) { @@ -479,7 +479,7 @@ bool EdgeGrid::Grid::intersect(const MultiPoint &polyline, bool closed) } while (ix != ixb || iy != iyb); } else { - int64_t ey = int64_t(p1.y - iy*m_resolution) * int64_t(dx); + int64_t ey = int64_t(p1(1) - iy*m_resolution) * int64_t(dx); do { assert(ix <= ixb && iy >= iyb); if (ex <= ey) { @@ -498,9 +498,9 @@ bool EdgeGrid::Grid::intersect(const MultiPoint &polyline, bool closed) } } else { - int64_t ex = int64_t(p1.x - ix*m_resolution) * int64_t(dy); - if (p1.y < p2.y) { - int64_t ey = int64_t((iy + 1)*m_resolution - p1.y) * int64_t(dx); + int64_t ex = int64_t(p1(0) - ix*m_resolution) * int64_t(dy); + if (p1(1) < p2(1)) { + int64_t ey = int64_t((iy + 1)*m_resolution - p1(1)) * int64_t(dx); do { assert(ix >= ixb && iy <= iyb); if (ex < ey) { @@ -519,7 +519,7 @@ bool EdgeGrid::Grid::intersect(const MultiPoint &polyline, bool closed) } while (ix != ixb || iy != iyb); } else { - int64_t ey = int64_t(p1.y - iy*m_resolution) * int64_t(dx); + int64_t ey = int64_t(p1(1) - iy*m_resolution) * int64_t(dx); do { assert(ix >= ixb && iy >= iyb); if (ex < ey) { @@ -556,8 +556,8 @@ bool EdgeGrid::Grid::line_cell_intersect(const Point &p1a, const Point &p2a, con { BoundingBox bbox(p1a, p1a); bbox.merge(p2a); - int64_t va_x = p2a.x - p1a.x; - int64_t va_y = p2a.y - p1a.y; + int64_t va_x = p2a(0) - p1a(0); + int64_t va_y = p2a(1) - p1a(1); for (size_t i = cell.begin; i != cell.end; ++ i) { const std::pair &cell_data = m_cell_data[i]; // Contour indexed by the ith line of this cell. @@ -576,21 +576,21 @@ bool EdgeGrid::Grid::line_cell_intersect(const Point &p1a, const Point &p2a, con if (! bbox.overlap(bbox2)) continue; // Now intersect the two line segments using exact arithmetics. - int64_t w1_x = p1b.x - p1a.x; - int64_t w1_y = p1b.y - p1a.y; - int64_t w2_x = p2b.x - p1a.x; - int64_t w2_y = p2b.y - p1a.y; + int64_t w1_x = p1b(0) - p1a(0); + int64_t w1_y = p1b(1) - p1a(1); + int64_t w2_x = p2b(0) - p1a(0); + int64_t w2_y = p2b(1) - p1a(1); int64_t side1 = va_x * w1_y - va_y * w1_x; int64_t side2 = va_x * w2_y - va_y * w2_x; if (side1 == side2 && side1 != 0) // The line segments don't intersect. continue; - w1_x = p1a.x - p1b.x; - w1_y = p1a.y - p1b.y; - w2_x = p2a.x - p1b.x; - w2_y = p2a.y - p1b.y; - int64_t vb_x = p2b.x - p1b.x; - int64_t vb_y = p2b.y - p1b.y; + w1_x = p1a(0) - p1b(0); + w1_y = p1a(1) - p1b(1); + w2_x = p2a(0) - p1b(0); + w2_y = p2a(1) - p1b(1); + int64_t vb_x = p2b(0) - p1b(0); + int64_t vb_y = p2b(1) - p1b(1); side1 = vb_x * w1_y - vb_y * w1_x; side2 = vb_x * w2_y - vb_y * w2_x; if (side1 == side2 && side1 != 0) @@ -607,13 +607,13 @@ bool EdgeGrid::Grid::line_cell_intersect(const Point &p1a, const Point &p2a, con bool EdgeGrid::Grid::inside(const Point &pt_src) { Point p = pt_src; - p.x -= m_bbox.min.x; - p.y -= m_bbox.min.y; + p(0) -= m_bbox.min(0); + p(1) -= m_bbox.min(1); // Get the cell of the point. - if (p.x < 0 || p.y < 0) + if (p(0) < 0 || p(1) < 0) return false; - coord_t ix = p.x / m_resolution; - coord_t iy = p.y / m_resolution; + coord_t ix = p(0) / m_resolution; + coord_t iy = p(1) / m_resolution; if (ix >= this->m_cols || iy >= this->m_rows) return false; @@ -634,21 +634,21 @@ bool EdgeGrid::Grid::inside(const Point &pt_src) idx2 = 0; const Point &p1 = contour[idx1]; const Point &p2 = contour[idx2]; - if (p1.y < p2.y) { - if (p.y < p1.y || p.y > p2.y) + if (p1(1) < p2(1)) { + if (p(1) < p1(1) || p(1) > p2(1)) continue; //FIXME finish this! int64_t vx = 0;// pt_src //FIXME finish this! int64_t det = 0; - } else if (p1.y != p2.y) { - assert(p1.y > p2.y); - if (p.y < p2.y || p.y > p1.y) + } else if (p1(1) != p2(1)) { + assert(p1(1) > p2(1)); + if (p(1) < p2(1) || p(1) > p1(1)) continue; } else { - assert(p1.y == p2.y); - if (p1.y == p.y) { - if (p.x >= p1.x && p.x <= p2.x) + assert(p1(1) == p2(1)); + if (p1(1) == p(1)) { + if (p(0) >= p1(0) && p(0) <= p2(0)) // On the segment. return true; // Before or after the segment. @@ -767,9 +767,9 @@ void EdgeGrid::Grid::calculate_sdf() const Slic3r::Point &p1 = pts[ipt]; const Slic3r::Point &p2 = pts[(ipt + 1 == pts.size()) ? 0 : ipt + 1]; // Segment vector - const Slic3r::Point v_seg = p1.vector_to(p2); + const Slic3r::Point v_seg = p2 - p1; // l2 of v_seg - const int64_t l2_seg = int64_t(v_seg.x) * int64_t(v_seg.x) + int64_t(v_seg.y) * int64_t(v_seg.y); + const int64_t l2_seg = int64_t(v_seg(0)) * int64_t(v_seg(0)) + int64_t(v_seg(1)) * int64_t(v_seg(1)); // For each corner of this cell and its 1 ring neighbours: for (int corner_y = -1; corner_y < 3; ++ corner_y) { coord_t corner_r = r + corner_y; @@ -780,28 +780,28 @@ void EdgeGrid::Grid::calculate_sdf() if (corner_c < 0 || corner_c >= ncols) continue; float &d_min = m_signed_distance_field[corner_r * ncols + corner_c]; - Slic3r::Point pt(m_bbox.min.x + corner_c * m_resolution, m_bbox.min.y + corner_r * m_resolution); - Slic3r::Point v_pt = p1.vector_to(pt); + Slic3r::Point pt(m_bbox.min(0) + corner_c * m_resolution, m_bbox.min(1) + corner_r * m_resolution); + Slic3r::Point v_pt = pt - p1; // dot(p2-p1, pt-p1) - int64_t t_pt = int64_t(v_seg.x) * int64_t(v_pt.x) + int64_t(v_seg.y) * int64_t(v_pt.y); + int64_t t_pt = int64_t(v_seg(0)) * int64_t(v_pt(0)) + int64_t(v_seg(1)) * int64_t(v_pt(1)); if (t_pt < 0) { // Closest to p1. - double dabs = sqrt(int64_t(v_pt.x) * int64_t(v_pt.x) + int64_t(v_pt.y) * int64_t(v_pt.y)); + double dabs = sqrt(int64_t(v_pt(0)) * int64_t(v_pt(0)) + int64_t(v_pt(1)) * int64_t(v_pt(1))); if (dabs < d_min) { // Previous point. const Slic3r::Point &p0 = pts[(ipt == 0) ? (pts.size() - 1) : ipt - 1]; - Slic3r::Point v_seg_prev = p0.vector_to(p1); - int64_t t2_pt = int64_t(v_seg_prev.x) * int64_t(v_pt.x) + int64_t(v_seg_prev.y) * int64_t(v_pt.y); + Slic3r::Point v_seg_prev = p1 - p0; + int64_t t2_pt = int64_t(v_seg_prev(0)) * int64_t(v_pt(0)) + int64_t(v_seg_prev(1)) * int64_t(v_pt(1)); if (t2_pt > 0) { // Inside the wedge between the previous and the next segment. // Set the signum depending on whether the vertex is convex or reflex. - int64_t det = int64_t(v_seg_prev.x) * int64_t(v_seg.y) - int64_t(v_seg_prev.y) * int64_t(v_seg.x); + int64_t det = int64_t(v_seg_prev(0)) * int64_t(v_seg(1)) - int64_t(v_seg_prev(1)) * int64_t(v_seg(0)); assert(det != 0); d_min = dabs; // Fill in an unsigned vector towards the zero iso surface. float *l = &L[(corner_r * ncols + corner_c) << 1]; - l[0] = std::abs(v_pt.x); - l[1] = std::abs(v_pt.y); + l[0] = std::abs(v_pt(0)); + l[1] = std::abs(v_pt(1)); #ifdef _DEBUG double dabs2 = sqrt(l[0]*l[0]+l[1]*l[1]); assert(std::abs(dabs-dabs2) < 1e-4 * std::max(dabs, dabs2)); @@ -816,7 +816,7 @@ void EdgeGrid::Grid::calculate_sdf() } else { // Closest to the segment. assert(t_pt >= 0 && t_pt <= l2_seg); - int64_t d_seg = int64_t(v_seg.y) * int64_t(v_pt.x) - int64_t(v_seg.x) * int64_t(v_pt.y); + int64_t d_seg = int64_t(v_seg(1)) * int64_t(v_pt(0)) - int64_t(v_seg(0)) * int64_t(v_pt(1)); double d = double(d_seg) / sqrt(double(l2_seg)); double dabs = std::abs(d); if (dabs < d_min) { @@ -824,8 +824,8 @@ void EdgeGrid::Grid::calculate_sdf() // Fill in an unsigned vector towards the zero iso surface. float *l = &L[(corner_r * ncols + corner_c) << 1]; float linv = float(d_seg) / float(l2_seg); - l[0] = std::abs(float(v_seg.y) * linv); - l[1] = std::abs(float(v_seg.x) * linv); + l[0] = std::abs(float(v_seg(1)) * linv); + l[1] = std::abs(float(v_seg(0)) * linv); #ifdef _DEBUG double dabs2 = sqrt(l[0]*l[0]+l[1]*l[1]); assert(std::abs(dabs-dabs2) <= 1e-4 * std::max(dabs, dabs2)); @@ -1059,8 +1059,8 @@ void EdgeGrid::Grid::calculate_sdf() float EdgeGrid::Grid::signed_distance_bilinear(const Point &pt) const { - coord_t x = pt.x - m_bbox.min.x; - coord_t y = pt.y - m_bbox.min.y; + coord_t x = pt(0) - m_bbox.min(0); + coord_t y = pt(1) - m_bbox.min(1); coord_t w = m_resolution * m_cols; coord_t h = m_resolution * m_rows; bool clamped = false; @@ -1124,39 +1124,39 @@ float EdgeGrid::Grid::signed_distance_bilinear(const Point &pt) const bool EdgeGrid::Grid::signed_distance_edges(const Point &pt, coord_t search_radius, coordf_t &result_min_dist, bool *pon_segment) const { BoundingBox bbox; - bbox.min = bbox.max = Point(pt.x - m_bbox.min.x, pt.y - m_bbox.min.y); + bbox.min = bbox.max = Point(pt(0) - m_bbox.min(0), pt(1) - m_bbox.min(1)); bbox.defined = true; // Upper boundary, round to grid and test validity. - bbox.max.x += search_radius; - bbox.max.y += search_radius; - if (bbox.max.x < 0 || bbox.max.y < 0) + bbox.max(0) += search_radius; + bbox.max(1) += search_radius; + if (bbox.max(0) < 0 || bbox.max(1) < 0) return false; - bbox.max.x /= m_resolution; - bbox.max.y /= m_resolution; - if (bbox.max.x >= m_cols) - bbox.max.x = m_cols - 1; - if (bbox.max.y >= m_rows) - bbox.max.y = m_rows - 1; + bbox.max(0) /= m_resolution; + bbox.max(1) /= m_resolution; + if (bbox.max(0) >= m_cols) + bbox.max(0) = m_cols - 1; + if (bbox.max(1) >= m_rows) + bbox.max(1) = m_rows - 1; // Lower boundary, round to grid and test validity. - bbox.min.x -= search_radius; - bbox.min.y -= search_radius; - if (bbox.min.x < 0) - bbox.min.x = 0; - if (bbox.min.y < 0) - bbox.min.y = 0; - bbox.min.x /= m_resolution; - bbox.min.y /= m_resolution; + bbox.min(0) -= search_radius; + bbox.min(1) -= search_radius; + if (bbox.min(0) < 0) + bbox.min(0) = 0; + if (bbox.min(1) < 0) + bbox.min(1) = 0; + bbox.min(0) /= m_resolution; + bbox.min(1) /= m_resolution; // Is the interval empty? - if (bbox.min.x > bbox.max.x || - bbox.min.y > bbox.max.y) + if (bbox.min(0) > bbox.max(0) || + bbox.min(1) > bbox.max(1)) return false; // Traverse all cells in the bounding box. float d_min = search_radius; // Signum of the distance field at pt. int sign_min = 0; bool on_segment = false; - for (int r = bbox.min.y; r <= bbox.max.y; ++ r) { - for (int c = bbox.min.x; c <= bbox.max.x; ++ c) { + for (int r = bbox.min(1); r <= bbox.max(1); ++ r) { + for (int c = bbox.min(0); c <= bbox.max(0); ++ c) { const Cell &cell = m_cells[r * m_cols + c]; for (size_t i = cell.begin; i < cell.end; ++ i) { const Slic3r::Points &pts = *m_contours[m_cell_data[i].first]; @@ -1164,25 +1164,25 @@ bool EdgeGrid::Grid::signed_distance_edges(const Point &pt, coord_t search_radiu // End points of the line segment. const Slic3r::Point &p1 = pts[ipt]; const Slic3r::Point &p2 = pts[(ipt + 1 == pts.size()) ? 0 : ipt + 1]; - Slic3r::Point v_seg = p1.vector_to(p2); - Slic3r::Point v_pt = p1.vector_to(pt); + Slic3r::Point v_seg = p2 - p1; + Slic3r::Point v_pt = pt - p1; // dot(p2-p1, pt-p1) - int64_t t_pt = int64_t(v_seg.x) * int64_t(v_pt.x) + int64_t(v_seg.y) * int64_t(v_pt.y); + int64_t t_pt = int64_t(v_seg(0)) * int64_t(v_pt(0)) + int64_t(v_seg(1)) * int64_t(v_pt(1)); // l2 of seg - int64_t l2_seg = int64_t(v_seg.x) * int64_t(v_seg.x) + int64_t(v_seg.y) * int64_t(v_seg.y); + int64_t l2_seg = int64_t(v_seg(0)) * int64_t(v_seg(0)) + int64_t(v_seg(1)) * int64_t(v_seg(1)); if (t_pt < 0) { // Closest to p1. - double dabs = sqrt(int64_t(v_pt.x) * int64_t(v_pt.x) + int64_t(v_pt.y) * int64_t(v_pt.y)); + double dabs = sqrt(int64_t(v_pt(0)) * int64_t(v_pt(0)) + int64_t(v_pt(1)) * int64_t(v_pt(1))); if (dabs < d_min) { // Previous point. const Slic3r::Point &p0 = pts[(ipt == 0) ? (pts.size() - 1) : ipt - 1]; - Slic3r::Point v_seg_prev = p0.vector_to(p1); - int64_t t2_pt = int64_t(v_seg_prev.x) * int64_t(v_pt.x) + int64_t(v_seg_prev.y) * int64_t(v_pt.y); + Slic3r::Point v_seg_prev = p1 - p0; + int64_t t2_pt = int64_t(v_seg_prev(0)) * int64_t(v_pt(0)) + int64_t(v_seg_prev(1)) * int64_t(v_pt(1)); if (t2_pt > 0) { // Inside the wedge between the previous and the next segment. d_min = dabs; // Set the signum depending on whether the vertex is convex or reflex. - int64_t det = int64_t(v_seg_prev.x) * int64_t(v_seg.y) - int64_t(v_seg_prev.y) * int64_t(v_seg.x); + int64_t det = int64_t(v_seg_prev(0)) * int64_t(v_seg(1)) - int64_t(v_seg_prev(1)) * int64_t(v_seg(0)); assert(det != 0); sign_min = (det > 0) ? 1 : -1; on_segment = false; @@ -1195,7 +1195,7 @@ bool EdgeGrid::Grid::signed_distance_edges(const Point &pt, coord_t search_radiu } else { // Closest to the segment. assert(t_pt >= 0 && t_pt <= l2_seg); - int64_t d_seg = int64_t(v_seg.y) * int64_t(v_pt.x) - int64_t(v_seg.x) * int64_t(v_pt.y); + int64_t d_seg = int64_t(v_seg(1)) * int64_t(v_pt(0)) - int64_t(v_seg(0)) * int64_t(v_pt(1)); double d = double(d_seg) / sqrt(double(l2_seg)); double dabs = std::abs(d); if (dabs < d_min) { @@ -1307,7 +1307,7 @@ Polygons EdgeGrid::Grid::contours_simplified(coord_t offset) const const Line &line_next = lines[it->second]; const Vector v1 = line_current.vector(); const Vector v2 = line_next.vector(); - int64_t cross = int64_t(v1.x) * int64_t(v2.y) - int64_t(v2.x) * int64_t(v1.y); + int64_t cross = int64_t(v1(0)) * int64_t(v2(1)) - int64_t(v2(0)) * int64_t(v1(1)); if (cross > 0) { // This has to be a convex right angle. There is no better next line. i_next = it->second; @@ -1328,10 +1328,10 @@ Polygons EdgeGrid::Grid::contours_simplified(coord_t offset) const Polygon &poly = out[i]; for (size_t j = 0; j < poly.points.size(); ++ j) { Point &p = poly.points[j]; - p.x *= m_resolution; - p.y *= m_resolution; - p.x += m_bbox.min.x; - p.y += m_bbox.min.y; + p(0) *= m_resolution; + p(1) *= m_resolution; + p(0) += m_bbox.min(0); + p(1) += m_bbox.min(1); } // Shrink the contour slightly, so if the same contour gets discretized and simplified again, one will get the same result. // Remove collineaer points. @@ -1341,11 +1341,11 @@ Polygons EdgeGrid::Grid::contours_simplified(coord_t offset) const size_t j0 = (j == 0) ? poly.points.size() - 1 : j - 1; size_t j2 = (j + 1 == poly.points.size()) ? 0 : j + 1; Point v = poly.points[j2] - poly.points[j0]; - if (v.x != 0 && v.y != 0) { + if (v(0) != 0 && v(1) != 0) { // This is a corner point. Copy it to the output contour. Point p = poly.points[j]; - p.y += (v.x < 0) ? - offset : offset; - p.x += (v.y > 0) ? - offset : offset; + p(1) += (v(0) < 0) ? - offset : offset; + p(0) += (v(1) > 0) ? - offset : offset; pts.push_back(p); } } @@ -1357,8 +1357,8 @@ Polygons EdgeGrid::Grid::contours_simplified(coord_t offset) const #if 0 void EdgeGrid::save_png(const EdgeGrid::Grid &grid, const BoundingBox &bbox, coord_t resolution, const char *path) { - unsigned int w = (bbox.max.x - bbox.min.x + resolution - 1) / resolution; - unsigned int h = (bbox.max.y - bbox.min.y + resolution - 1) / resolution; + unsigned int w = (bbox.max(0) - bbox.min(0) + resolution - 1) / resolution; + unsigned int h = (bbox.max(1) - bbox.min(1) + resolution - 1) / resolution; wxImage img(w, h); unsigned char *data = img.GetData(); memset(data, 0, w * h * 3); @@ -1371,7 +1371,7 @@ void EdgeGrid::save_png(const EdgeGrid::Grid &grid, const BoundingBox &bbox, coo for (coord_t r = 0; r < h; ++r) { for (coord_t c = 0; c < w; ++ c) { unsigned char *pxl = data + (((h - r - 1) * w) + c) * 3; - Point pt(c * resolution + bbox.min.x, r * resolution + bbox.min.y); + Point pt(c * resolution + bbox.min(0), r * resolution + bbox.min(1)); coordf_t min_dist; bool on_segment = true; #if 0 @@ -1409,8 +1409,8 @@ void EdgeGrid::save_png(const EdgeGrid::Grid &grid, const BoundingBox &bbox, coo pxl[2] = 0; } - float gridx = float(pt.x - grid.bbox().min.x) / float(grid.resolution()); - float gridy = float(pt.y - grid.bbox().min.y) / float(grid.resolution()); + float gridx = float(pt(0) - grid.bbox().min(0)) / float(grid.resolution()); + float gridy = float(pt(1) - grid.bbox().min(1)) / float(grid.resolution()); if (gridx >= -0.4f && gridy >= -0.4f && gridx <= grid.cols() + 0.4f && gridy <= grid.rows() + 0.4f) { int ix = int(floor(gridx + 0.5f)); int iy = int(floor(gridy + 0.5f)); diff --git a/xs/src/libslic3r/ExPolygon.cpp b/xs/src/libslic3r/ExPolygon.cpp index cd57fd7b0..4294fe543 100644 --- a/xs/src/libslic3r/ExPolygon.cpp +++ b/xs/src/libslic3r/ExPolygon.cpp @@ -34,54 +34,43 @@ ExPolygon::operator Polylines() const return to_polylines(*this); } -void -ExPolygon::scale(double factor) +void ExPolygon::scale(double factor) { contour.scale(factor); - for (Polygons::iterator it = holes.begin(); it != holes.end(); ++it) { - (*it).scale(factor); - } + for (Polygon &hole : holes) + hole.scale(factor); } -void -ExPolygon::translate(double x, double y) +void ExPolygon::translate(double x, double y) { contour.translate(x, y); - for (Polygons::iterator it = holes.begin(); it != holes.end(); ++it) { - (*it).translate(x, y); - } + for (Polygon &hole : holes) + hole.translate(x, y); } -void -ExPolygon::rotate(double angle) +void ExPolygon::rotate(double angle) { contour.rotate(angle); - for (Polygons::iterator it = holes.begin(); it != holes.end(); ++it) { - (*it).rotate(angle); - } + for (Polygon &hole : holes) + hole.rotate(angle); } -void -ExPolygon::rotate(double angle, const Point ¢er) +void ExPolygon::rotate(double angle, const Point ¢er) { contour.rotate(angle, center); - for (Polygons::iterator it = holes.begin(); it != holes.end(); ++it) { - (*it).rotate(angle, center); - } + for (Polygon &hole : holes) + hole.rotate(angle, center); } -double -ExPolygon::area() const +double ExPolygon::area() const { double a = this->contour.area(); - for (Polygons::const_iterator it = this->holes.begin(); it != this->holes.end(); ++it) { - a -= -(*it).area(); // holes have negative area - } + for (const Polygon &hole : holes) + a -= - hole.area(); // holes have negative area return a; } -bool -ExPolygon::is_valid() const +bool ExPolygon::is_valid() const { if (!this->contour.is_valid() || !this->contour.is_counter_clockwise()) return false; for (Polygons::const_iterator it = this->holes.begin(); it != this->holes.end(); ++it) { @@ -90,20 +79,17 @@ ExPolygon::is_valid() const return true; } -bool -ExPolygon::contains(const Line &line) const +bool ExPolygon::contains(const Line &line) const { - return this->contains((Polyline)line); + return this->contains(Polyline(line.a, line.b)); } -bool -ExPolygon::contains(const Polyline &polyline) const +bool ExPolygon::contains(const Polyline &polyline) const { return diff_pl((Polylines)polyline, *this).empty(); } -bool -ExPolygon::contains(const Polylines &polylines) const +bool ExPolygon::contains(const Polylines &polylines) const { #if 0 BoundingBox bbox = get_extents(polylines); @@ -120,8 +106,7 @@ ExPolygon::contains(const Polylines &polylines) const return pl_out.empty(); } -bool -ExPolygon::contains(const Point &point) const +bool ExPolygon::contains(const Point &point) const { if (!this->contour.contains(point)) return false; for (Polygons::const_iterator it = this->holes.begin(); it != this->holes.end(); ++it) { @@ -131,8 +116,7 @@ ExPolygon::contains(const Point &point) const } // inclusive version of contains() that also checks whether point is on boundaries -bool -ExPolygon::contains_b(const Point &point) const +bool ExPolygon::contains_b(const Point &point) const { return this->contains(point) || this->has_boundary_point(point); } @@ -243,25 +227,24 @@ ExPolygon::medial_axis(double max_width, double min_width, ThickPolylines* polyl Point new_front = polyline.points.front(); Point new_back = polyline.points.back(); if (polyline.endpoints.first && !this->has_boundary_point(new_front)) { - Line line(polyline.points.front(), polyline.points[1]); - + Vec2d p1 = polyline.points.front().cast(); + Vec2d p2 = polyline.points[1].cast(); // prevent the line from touching on the other side, otherwise intersection() might return that solution - if (polyline.points.size() == 2) line.b = line.midpoint(); - - line.extend_start(max_width); - (void)this->contour.intersection(line, &new_front); + if (polyline.points.size() == 2) + p2 = (p1 + p2) * 0.5; + // Extend the start of the segment. + p1 -= (p2 - p1).normalized() * max_width; + this->contour.intersection(Line(p1.cast(), p2.cast()), &new_front); } if (polyline.endpoints.second && !this->has_boundary_point(new_back)) { - Line line( - *(polyline.points.end() - 2), - polyline.points.back() - ); - + Vec2d p1 = (polyline.points.end() - 2)->cast(); + Vec2d p2 = polyline.points.back().cast(); // prevent the line from touching on the other side, otherwise intersection() might return that solution - if (polyline.points.size() == 2) line.a = line.midpoint(); - line.extend_end(max_width); - - (void)this->contour.intersection(line, &new_back); + if (polyline.points.size() == 2) + p1 = (p1 + p2) * 0.5; + // Extend the start of the segment. + p2 += (p2 - p1).normalized() * max_width; + this->contour.intersection(Line(p1.cast(), p2.cast()), &new_back); } polyline.points.front() = new_front; polyline.points.back() = new_back; @@ -294,14 +277,14 @@ ExPolygon::medial_axis(double max_width, double min_width, ThickPolylines* polyl // find another polyline starting here for (size_t j = i+1; j < pp.size(); ++j) { ThickPolyline& other = pp[j]; - if (polyline.last_point().coincides_with(other.last_point())) { + if (polyline.last_point() == other.last_point()) { other.reverse(); - } else if (polyline.first_point().coincides_with(other.last_point())) { + } else if (polyline.first_point() == other.last_point()) { polyline.reverse(); other.reverse(); - } else if (polyline.first_point().coincides_with(other.first_point())) { + } else if (polyline.first_point() == other.first_point()) { polyline.reverse(); - } else if (!polyline.last_point().coincides_with(other.first_point())) { + } else if (polyline.last_point() != other.first_point()) { continue; } @@ -361,7 +344,7 @@ ExPolygon::get_trapezoids2(Polygons* polygons) const std::vector xx; xx.reserve(pp.size()); for (Points::const_iterator p = pp.begin(); p != pp.end(); ++p) - xx.push_back(p->x); + xx.push_back(p->x()); std::sort(xx.begin(), xx.end()); // find trapezoids by looping from first to next-to-last coordinate @@ -372,14 +355,14 @@ ExPolygon::get_trapezoids2(Polygons* polygons) const // build rectangle Polygon poly; poly.points.resize(4); - poly[0].x = *x; - poly[0].y = bb.min.y; - poly[1].x = next_x; - poly[1].y = bb.min.y; - poly[2].x = next_x; - poly[2].y = bb.max.y; - poly[3].x = *x; - poly[3].y = bb.max.y; + poly[0](0) = *x; + poly[0](1) = bb.min(1); + poly[1](0) = next_x; + poly[1](1) = bb.min(1); + poly[2](0) = next_x; + poly[2](1) = bb.max(1); + poly[3](0) = *x; + poly[3](1) = bb.max(1); // intersect with this expolygon // append results to return value @@ -425,10 +408,11 @@ ExPolygon::triangulate_pp(Polygons* polygons) const TPPLPoly p; p.Init(int(ex->contour.points.size())); //printf(PRINTF_ZU "\n0\n", ex->contour.points.size()); - for (Points::const_iterator point = ex->contour.points.begin(); point != ex->contour.points.end(); ++point) { - p[ point-ex->contour.points.begin() ].x = point->x; - p[ point-ex->contour.points.begin() ].y = point->y; - //printf("%ld %ld\n", point->x, point->y); + for (const Point &point : ex->contour.points) { + size_t i = &point - &ex->contour.points.front(); + p[i].x = point(0); + p[i].y = point(1); + //printf("%ld %ld\n", point->x(), point->y()); } p.SetHole(false); input.push_back(p); @@ -439,10 +423,11 @@ ExPolygon::triangulate_pp(Polygons* polygons) const TPPLPoly p; p.Init(hole->points.size()); //printf(PRINTF_ZU "\n1\n", hole->points.size()); - for (Points::const_iterator point = hole->points.begin(); point != hole->points.end(); ++point) { - p[ point-hole->points.begin() ].x = point->x; - p[ point-hole->points.begin() ].y = point->y; - //printf("%ld %ld\n", point->x, point->y); + for (const Point &point : hole->points) { + size_t i = &point - &hole->points.front(); + p[i].x = point(0); + p[i].y = point(1); + //printf("%ld %ld\n", point->x(), point->y()); } p.SetHole(true); input.push_back(p); @@ -460,8 +445,8 @@ ExPolygon::triangulate_pp(Polygons* polygons) const Polygon p; p.points.resize(num_points); for (long i = 0; i < num_points; ++i) { - p.points[i].x = coord_t((*poly)[i].x); - p.points[i].y = coord_t((*poly)[i].y); + p.points[i](0) = coord_t((*poly)[i].x); + p.points[i](1) = coord_t((*poly)[i].y); } polygons->push_back(p); } @@ -477,19 +462,17 @@ ExPolygon::triangulate_p2t(Polygons* polygons) const // contour std::vector ContourPoints; - for (Points::const_iterator point = ex->contour.points.begin(); point != ex->contour.points.end(); ++point) { + for (const Point &pt : ex->contour.points) // We should delete each p2t::Point object - ContourPoints.push_back(new p2t::Point(point->x, point->y)); - } + ContourPoints.push_back(new p2t::Point(pt(0), pt(1))); p2t::CDT cdt(ContourPoints); // holes for (Polygons::const_iterator hole = ex->holes.begin(); hole != ex->holes.end(); ++hole) { std::vector points; - for (Points::const_iterator point = hole->points.begin(); point != hole->points.end(); ++point) { + for (const Point &pt : hole->points) // will be destructed in SweepContext::~SweepContext - points.push_back(new p2t::Point(point->x, point->y)); - } + points.push_back(new p2t::Point(pt(0), pt(1))); cdt.AddHole(points); } @@ -506,9 +489,8 @@ ExPolygon::triangulate_p2t(Polygons* polygons) const polygons->push_back(p); } - for(std::vector::iterator it = ContourPoints.begin(); it != ContourPoints.end(); ++it) { - delete *it; - } + for (p2t::Point *ptr : ContourPoints) + delete ptr; } } @@ -523,17 +505,6 @@ ExPolygon::lines() const return lines; } -std::string -ExPolygon::dump_perl() const -{ - std::ostringstream ret; - ret << "[" << this->contour.dump_perl(); - for (Polygons::const_iterator h = this->holes.begin(); h != this->holes.end(); ++h) - ret << "," << h->dump_perl(); - ret << "]"; - return ret.str(); -} - BoundingBox get_extents(const ExPolygon &expolygon) { return get_extents(expolygon.contour); diff --git a/xs/src/libslic3r/ExPolygon.hpp b/xs/src/libslic3r/ExPolygon.hpp index f4782ba55..4833ee49e 100644 --- a/xs/src/libslic3r/ExPolygon.hpp +++ b/xs/src/libslic3r/ExPolygon.hpp @@ -63,7 +63,6 @@ public: void triangulate_pp(Polygons* polygons) const; void triangulate_p2t(Polygons* polygons) const; Lines lines() const; - std::string dump_perl() const; }; // Count a nuber of polygons stored inside the vector of expolygons. diff --git a/xs/src/libslic3r/ExtrusionEntity.cpp b/xs/src/libslic3r/ExtrusionEntity.cpp index c6f67b169..92f0d3669 100644 --- a/xs/src/libslic3r/ExtrusionEntity.cpp +++ b/xs/src/libslic3r/ExtrusionEntity.cpp @@ -220,7 +220,7 @@ void ExtrusionLoop::split_at(const Point &point, bool prefer_non_overhang) double min_non_overhang = std::numeric_limits::max(); for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) { Point p_tmp = point.projection_onto(path->polyline); - double dist = point.distance_to(p_tmp); + double dist = (p_tmp - point).cast().norm(); if (dist < min) { p = p_tmp; min = dist; diff --git a/xs/src/libslic3r/ExtrusionEntity.hpp b/xs/src/libslic3r/ExtrusionEntity.hpp index 15363e8ed..90675c04a 100644 --- a/xs/src/libslic3r/ExtrusionEntity.hpp +++ b/xs/src/libslic3r/ExtrusionEntity.hpp @@ -149,7 +149,7 @@ public: // Minimum volumetric velocity of this extrusion entity. Used by the constant nozzle pressure algorithm. double min_mm3_per_mm() const { return this->mm3_per_mm; } Polyline as_polyline() const { return this->polyline; } - virtual double total_volume() const { return mm3_per_mm * unscale(length()); } + virtual double total_volume() const { return mm3_per_mm * unscale(length()); } private: void _inflate_collection(const Polylines &polylines, ExtrusionEntityCollection* collection) const; diff --git a/xs/src/libslic3r/ExtrusionEntityCollection.hpp b/xs/src/libslic3r/ExtrusionEntityCollection.hpp index 382455fe3..3b34145f8 100644 --- a/xs/src/libslic3r/ExtrusionEntityCollection.hpp +++ b/xs/src/libslic3r/ExtrusionEntityCollection.hpp @@ -50,10 +50,15 @@ public: src.clear(); } } - void append(const ExtrusionPaths &paths) { + void append(const ExtrusionPaths &paths) { this->entities.reserve(this->entities.size() + paths.size()); - for (ExtrusionPaths::const_iterator path = paths.begin(); path != paths.end(); ++path) - this->entities.push_back(path->clone()); + for (const ExtrusionPath &path : paths) + this->entities.emplace_back(path.clone()); + } + void append(ExtrusionPaths &&paths) { + this->entities.reserve(this->entities.size() + paths.size()); + for (ExtrusionPath &path : paths) + this->entities.emplace_back(new ExtrusionPath(std::move(path))); } void replace(size_t i, const ExtrusionEntity &entity); void remove(size_t i); diff --git a/xs/src/libslic3r/ExtrusionSimulator.cpp b/xs/src/libslic3r/ExtrusionSimulator.cpp index daecbc0d1..fcb2fe825 100644 --- a/xs/src/libslic3r/ExtrusionSimulator.cpp +++ b/xs/src/libslic3r/ExtrusionSimulator.cpp @@ -893,24 +893,24 @@ ExtrusionSimulator::~ExtrusionSimulator() void ExtrusionSimulator::set_image_size(const Point &image_size) { // printf("ExtrusionSimulator::set_image_size()\n"); - if (this->image_size.x == image_size.x && - this->image_size.y == image_size.y) + if (this->image_size.x() == image_size.x() && + this->image_size.y() == image_size.y()) return; // printf("Setting image size: %d, %d\n", image_size.x, image_size.y); this->image_size = image_size; // Allocate the image data in an RGBA format. // printf("Allocating image data, size %d\n", image_size.x * image_size.y * 4); - pimpl->image_data.assign(image_size.x * image_size.y * 4, 0); + pimpl->image_data.assign(image_size.x() * image_size.y() * 4, 0); // printf("Allocating image data, allocated\n"); //FIXME fill the image with red vertical lines. - for (size_t r = 0; r < image_size.y; ++ r) { - for (size_t c = 0; c < image_size.x; c += 2) { + for (size_t r = 0; r < image_size.y(); ++ r) { + for (size_t c = 0; c < image_size.x(); c += 2) { // Color red - pimpl->image_data[r * image_size.x * 4 + c * 4] = 255; + pimpl->image_data[r * image_size.x() * 4 + c * 4] = 255; // Opacity full - pimpl->image_data[r * image_size.x * 4 + c * 4 + 3] = 255; + pimpl->image_data[r * image_size.x() * 4 + c * 4 + 3] = 255; } } // printf("Allocating image data, set\n"); @@ -922,8 +922,8 @@ void ExtrusionSimulator::set_viewport(const BoundingBox &viewport) if (this->viewport != viewport) { this->viewport = viewport; Point sz = viewport.size(); - pimpl->accumulator.resize(boost::extents[sz.y][sz.x]); - pimpl->bitmap.resize(boost::extents[sz.y*pimpl->bitmap_oversampled][sz.x*pimpl->bitmap_oversampled]); + pimpl->accumulator.resize(boost::extents[sz.y()][sz.x()]); + pimpl->bitmap.resize(boost::extents[sz.y()*pimpl->bitmap_oversampled][sz.x()*pimpl->bitmap_oversampled]); // printf("Accumulator size: %d, %d\n", sz.y, sz.x); } } @@ -943,8 +943,8 @@ void ExtrusionSimulator::reset_accumulator() // printf("ExtrusionSimulator::reset_accumulator()\n"); Point sz = viewport.size(); // printf("Reset accumulator, Accumulator size: %d, %d\n", sz.y, sz.x); - memset(&pimpl->accumulator[0][0], 0, sizeof(float) * sz.x * sz.y); - memset(&pimpl->bitmap[0][0], 0, sz.x * sz.y * pimpl->bitmap_oversampled * pimpl->bitmap_oversampled); + memset(&pimpl->accumulator[0][0], 0, sizeof(float) * sz.x() * sz.y()); + memset(&pimpl->bitmap[0][0], 0, sz.x() * sz.y() * pimpl->bitmap_oversampled * pimpl->bitmap_oversampled); pimpl->extrusion_points.clear(); // printf("Reset accumulator, done.\n"); } @@ -955,17 +955,17 @@ void ExtrusionSimulator::extrude_to_accumulator(const ExtrusionPath &path, const // Convert the path to V2f points, shift and scale them to the viewport. std::vector polyline; polyline.reserve(path.polyline.points.size()); - float scalex = float(viewport.size().x) / float(bbox.size().x); - float scaley = float(viewport.size().y) / float(bbox.size().y); + float scalex = float(viewport.size().x()) / float(bbox.size().x()); + float scaley = float(viewport.size().y()) / float(bbox.size().y()); float w = scale_(path.width) * scalex; float h = scale_(path.height) * scalex; w = scale_(path.mm3_per_mm / path.height) * scalex; // printf("scalex: %f, scaley: %f\n", scalex, scaley); - // printf("bbox: %d,%d %d,%d\n", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y); + // printf("bbox: %d,%d %d,%d\n", bbox.min.x(), bbox.min.y, bbox.max.x(), bbox.max.y); for (Points::const_iterator it = path.polyline.points.begin(); it != path.polyline.points.end(); ++ it) { - // printf("point %d,%d\n", it->x+shift.x, it->y+shift.y); + // printf("point %d,%d\n", it->x+shift.x(), it->y+shift.y); ExtrusionPoint ept; - ept.center = V2f(float(it->x+shift.x-bbox.min.x) * scalex, float(it->y+shift.y-bbox.min.y) * scaley); + ept.center = V2f(float((*it)(0)+shift.x()-bbox.min.x()) * scalex, float((*it)(1)+shift.y()-bbox.min.y()) * scaley); ept.radius = w/2.f; ept.height = 0.5f; polyline.push_back(ept.center); @@ -989,9 +989,9 @@ void ExtrusionSimulator::evaluate_accumulator(ExtrusionSimulationType simulation if (simulationType > ExtrusionSimulationDontSpread) { // Average the cells of a bitmap into a lower resolution floating point mask. - A2f mask(boost::extents[sz.y][sz.x]); - for (int r = 0; r < sz.y; ++r) { - for (int c = 0; c < sz.x; ++c) { + A2f mask(boost::extents[sz.y()][sz.x()]); + for (int r = 0; r < sz.y(); ++r) { + for (int c = 0; c < sz.x(); ++c) { float p = 0; for (int j = 0; j < pimpl->bitmap_oversampled; ++ j) { for (int i = 0; i < pimpl->bitmap_oversampled; ++ i) { @@ -1009,9 +1009,9 @@ void ExtrusionSimulator::evaluate_accumulator(ExtrusionSimulationType simulation } // Color map the accumulator. - for (int r = 0; r < sz.y; ++r) { - unsigned char *ptr = &pimpl->image_data[(image_size.x * (viewport.min.y + r) + viewport.min.x) * 4]; - for (int c = 0; c < sz.x; ++c) { + for (int r = 0; r < sz.y(); ++r) { + unsigned char *ptr = &pimpl->image_data[(image_size.x() * (viewport.min.y() + r) + viewport.min.x()) * 4]; + for (int c = 0; c < sz.x(); ++c) { #if 1 float p = pimpl->accumulator[r][c]; #else diff --git a/xs/src/libslic3r/Fill/Fill3DHoneycomb.cpp b/xs/src/libslic3r/Fill/Fill3DHoneycomb.cpp index aa9774784..6a37e4369 100644 --- a/xs/src/libslic3r/Fill/Fill3DHoneycomb.cpp +++ b/xs/src/libslic3r/Fill/Fill3DHoneycomb.cpp @@ -54,9 +54,9 @@ static std::vector perpendPoints(const coordf_t offset, const size_t b // components that are outside these limits are set to the limits. static inline void trim(Pointfs &pts, coordf_t minX, coordf_t minY, coordf_t maxX, coordf_t maxY) { - for (Pointfs::iterator it = pts.begin(); it != pts.end(); ++ it) { - it->x = clamp(minX, maxX, it->x); - it->y = clamp(minY, maxY, it->y); + for (Vec2d &pt : pts) { + pt(0) = clamp(minX, maxX, pt(0)); + pt(1) = clamp(minY, maxY, pt(1)); } } @@ -66,7 +66,7 @@ static inline Pointfs zip(const std::vector &x, const std::vectorbegin(); it != it_polylines->end(); ++ it) - polyline.points.push_back(Point(coord_t(it->x * scaleFactor), coord_t(it->y * scaleFactor))); + polyline.points.push_back(Point(coord_t((*it)(0) * scaleFactor), coord_t((*it)(1) * scaleFactor))); } return result; } @@ -153,13 +153,13 @@ void Fill3DHoneycomb::_fill_surface_single( Polylines polylines = makeGrid( scale_(this->z), distance, - ceil(bb.size().x / distance) + 1, - ceil(bb.size().y / distance) + 1, + ceil(bb.size()(0) / distance) + 1, + ceil(bb.size()(1) / distance) + 1, ((this->layer_id/thickness_layers) % 2) + 1); // move pattern in place for (Polylines::iterator it = polylines.begin(); it != polylines.end(); ++ it) - it->translate(bb.min.x, bb.min.y); + it->translate(bb.min(0), bb.min(1)); // clip pattern to boundaries polylines = intersection_pl(polylines, (Polygons)expolygon); @@ -187,7 +187,7 @@ void Fill3DHoneycomb::_fill_surface_single( const Point &last_point = pts_end.back(); // TODO: we should also check that both points are on a fill_boundary to avoid // connecting paths on the boundaries of internal regions - if (first_point.distance_to(last_point) <= 1.5 * distance && + if ((last_point - first_point).cast().norm() <= 1.5 * distance && expolygon_off.contains(Line(last_point, first_point))) { // Append the polyline. pts_end.insert(pts_end.end(), it_polyline->points.begin(), it_polyline->points.end()); diff --git a/xs/src/libslic3r/Fill/FillBase.hpp b/xs/src/libslic3r/Fill/FillBase.hpp index 62d18e518..b67d14339 100644 --- a/xs/src/libslic3r/Fill/FillBase.hpp +++ b/xs/src/libslic3r/Fill/FillBase.hpp @@ -121,11 +121,11 @@ public: return aligned; } static Point _align_to_grid(Point coord, Point spacing) - { return Point(_align_to_grid(coord.x, spacing.x), _align_to_grid(coord.y, spacing.y)); } + { return Point(_align_to_grid(coord(0), spacing(0)), _align_to_grid(coord(1), spacing(1))); } static coord_t _align_to_grid(coord_t coord, coord_t spacing, coord_t base) { return base + _align_to_grid(coord - base, spacing); } static Point _align_to_grid(Point coord, Point spacing, Point base) - { return Point(_align_to_grid(coord.x, spacing.x, base.x), _align_to_grid(coord.y, spacing.y, base.y)); } + { return Point(_align_to_grid(coord(0), spacing(0), base(0)), _align_to_grid(coord(1), spacing(1), base(1))); } }; } // namespace Slic3r diff --git a/xs/src/libslic3r/Fill/FillConcentric.cpp b/xs/src/libslic3r/Fill/FillConcentric.cpp index b21ad2799..8a3a7ea89 100644 --- a/xs/src/libslic3r/Fill/FillConcentric.cpp +++ b/xs/src/libslic3r/Fill/FillConcentric.cpp @@ -20,8 +20,8 @@ void FillConcentric::_fill_surface_single( coord_t distance = coord_t(min_spacing / params.density); if (params.density > 0.9999f && !params.dont_adjust) { - distance = this->_adjust_solid_spacing(bounding_box.size().x, distance); - this->spacing = unscale(distance); + distance = this->_adjust_solid_spacing(bounding_box.size()(0), distance); + this->spacing = unscale(distance); } Polygons loops = (Polygons)expolygon; diff --git a/xs/src/libslic3r/Fill/FillGyroid.cpp b/xs/src/libslic3r/Fill/FillGyroid.cpp index 89d5d231e..d6bf03ce6 100644 --- a/xs/src/libslic3r/Fill/FillGyroid.cpp +++ b/xs/src/libslic3r/Fill/FillGyroid.cpp @@ -30,39 +30,39 @@ static inline double f(double x, double z_sin, double z_cos, bool vertical, bool } static inline Polyline make_wave( - const std::vector& one_period, double width, double height, double offset, double scaleFactor, + const std::vector& one_period, double width, double height, double offset, double scaleFactor, double z_cos, double z_sin, bool vertical) { - std::vector points = one_period; - double period = points.back().x; + std::vector points = one_period; + double period = points.back()(0); points.pop_back(); int n = points.size(); do { - points.emplace_back(Pointf(points[points.size()-n].x + period, points[points.size()-n].y)); - } while (points.back().x < width); - points.back().x = width; + points.emplace_back(Vec2d(points[points.size()-n](0) + period, points[points.size()-n](1))); + } while (points.back()(0) < width); + points.back()(0) = width; // and construct the final polyline to return: Polyline polyline; for (auto& point : points) { - point.y += offset; - point.y = clamp(0., height, double(point.y)); + point(1) += offset; + point(1) = clamp(0., height, double(point(1))); if (vertical) - std::swap(point.x, point.y); - polyline.points.emplace_back(convert_to(point * scaleFactor)); + std::swap(point(0), point(1)); + polyline.points.emplace_back((point * scaleFactor).cast()); } return polyline; } -static std::vector make_one_period(double width, double scaleFactor, double z_cos, double z_sin, bool vertical, bool flip) +static std::vector make_one_period(double width, double scaleFactor, double z_cos, double z_sin, bool vertical, bool flip) { - std::vector points; + std::vector points; double dx = M_PI_4; // very coarse spacing to begin with double limit = std::min(2*M_PI, width); for (double x = 0.; x < limit + EPSILON; x += dx) { // so the last point is there too x = std::min(x, limit); - points.emplace_back(Pointf(x,f(x, z_sin,z_cos, vertical, flip))); + points.emplace_back(Vec2d(x,f(x, z_sin,z_cos, vertical, flip))); } // now we will check all internal points and in case some are too far from the line connecting its neighbours, @@ -71,17 +71,19 @@ static std::vector make_one_period(double width, double scaleFactor, dou for (unsigned int i=1;i(scaleFactor) * std::abs(cross2(rp, lp) - cross2(rp - lp, tp)) / lrv.norm(); if (dist_mm > tolerance) { // if the difference from straight line is more than this - double x = 0.5f * (points[i-1].x + points[i].x); - points.emplace_back(Pointf(x, f(x, z_sin, z_cos, vertical, flip))); - x = 0.5f * (points[i+1].x + points[i].x); - points.emplace_back(Pointf(x, f(x, z_sin, z_cos, vertical, flip))); - std::sort(points.begin(), points.end()); // we added the points to the end, but need them all in order - --i; // decrement i so we also check the first newly added point + double x = 0.5f * (points[i-1](0) + points[i](0)); + points.emplace_back(Vec2d(x, f(x, z_sin, z_cos, vertical, flip))); + x = 0.5f * (points[i+1](0) + points[i](0)); + points.emplace_back(Vec2d(x, f(x, z_sin, z_cos, vertical, flip))); + // we added the points to the end, but need them all in order + std::sort(points.begin(), points.end(), [](const Vec2d &lhs, const Vec2d &rhs){ return lhs < rhs; }); + // decrement i so we also check the first newly added point + --i; } } return points; @@ -107,7 +109,7 @@ static Polylines make_gyroid_waves(double gridZ, double density_adjusted, double std::swap(width,height); } - std::vector one_period = make_one_period(width, scaleFactor, z_cos, z_sin, vertical, flip); // creates one period of the waves, so it doesn't have to be recalculated all the time + std::vector one_period = make_one_period(width, scaleFactor, z_cos, z_sin, vertical, flip); // creates one period of the waves, so it doesn't have to be recalculated all the time Polylines result; for (double y0 = lower_bound; y0 < upper_bound+EPSILON; y0 += 2*M_PI) // creates odd polylines @@ -143,12 +145,12 @@ void FillGyroid::_fill_surface_single( scale_(this->z), density_adjusted, this->spacing, - ceil(bb.size().x / distance) + 1., - ceil(bb.size().y / distance) + 1.); + ceil(bb.size()(0) / distance) + 1., + ceil(bb.size()(1) / distance) + 1.); // move pattern in place for (Polyline &polyline : polylines) - polyline.translate(bb.min.x, bb.min.y); + polyline.translate(bb.min(0), bb.min(1)); // clip pattern to boundaries polylines = intersection_pl(polylines, (Polygons)expolygon); @@ -177,7 +179,7 @@ void FillGyroid::_fill_surface_single( // TODO: we should also check that both points are on a fill_boundary to avoid // connecting paths on the boundaries of internal regions // TODO: avoid crossing current infill path - if (first_point.distance_to(last_point) <= 5 * distance && + if ((last_point - first_point).cast().norm() <= 5 * distance && expolygon_off.contains(Line(last_point, first_point))) { // Append the polyline. pts_end.insert(pts_end.end(), polyline.points.begin(), polyline.points.end()); diff --git a/xs/src/libslic3r/Fill/FillHoneycomb.cpp b/xs/src/libslic3r/Fill/FillHoneycomb.cpp index aa0e0f6b0..6f26167a2 100644 --- a/xs/src/libslic3r/Fill/FillHoneycomb.cpp +++ b/xs/src/libslic3r/Fill/FillHoneycomb.cpp @@ -50,13 +50,13 @@ void FillHoneycomb::_fill_surface_single( bounding_box.merge(_align_to_grid(bounding_box.min, Point(m.hex_width, m.pattern_height))); } - coord_t x = bounding_box.min.x; - while (x <= bounding_box.max.x) { + coord_t x = bounding_box.min(0); + while (x <= bounding_box.max(0)) { Polygon p; coord_t ax[2] = { x + m.x_offset, x + m.distance - m.x_offset }; for (size_t i = 0; i < 2; ++ i) { std::reverse(p.points.begin(), p.points.end()); // turn first half upside down - for (coord_t y = bounding_box.min.y; y <= bounding_box.max.y; y += m.y_short + m.hex_side + m.y_short + m.hex_side) { + for (coord_t y = bounding_box.min(1); y <= bounding_box.max(1); y += m.y_short + m.hex_side + m.y_short + m.hex_side) { p.points.push_back(Point(ax[1], y + m.y_offset)); p.points.push_back(Point(ax[0], y + m.y_short - m.y_offset)); p.points.push_back(Point(ax[0], y + m.y_short + m.hex_side + m.y_offset)); @@ -101,7 +101,7 @@ void FillHoneycomb::_fill_surface_single( for (Polylines::iterator it_path = chained.begin(); it_path != chained.end(); ++ it_path) { if (! paths.empty()) { // distance between first point of this path and last point of last path - double distance = paths.back().last_point().distance_to(it_path->first_point()); + double distance = (it_path->first_point() - paths.back().last_point()).cast().norm(); if (distance <= m.hex_width) { paths.back().points.insert(paths.back().points.end(), it_path->points.begin(), it_path->points.end()); continue; diff --git a/xs/src/libslic3r/Fill/FillPlanePath.cpp b/xs/src/libslic3r/Fill/FillPlanePath.cpp index f71ef95a1..615cc6efe 100644 --- a/xs/src/libslic3r/Fill/FillPlanePath.cpp +++ b/xs/src/libslic3r/Fill/FillPlanePath.cpp @@ -24,14 +24,14 @@ void FillPlanePath::_fill_surface_single( Point shift = this->_centered() ? bounding_box.center() : bounding_box.min; - expolygon.translate(-shift.x, -shift.y); - bounding_box.translate(-shift.x, -shift.y); + expolygon.translate(-shift(0), -shift(1)); + bounding_box.translate(-shift(0), -shift(1)); Pointfs pts = _generate( - coord_t(ceil(coordf_t(bounding_box.min.x) / distance_between_lines)), - coord_t(ceil(coordf_t(bounding_box.min.y) / distance_between_lines)), - coord_t(ceil(coordf_t(bounding_box.max.x) / distance_between_lines)), - coord_t(ceil(coordf_t(bounding_box.max.y) / distance_between_lines))); + coord_t(ceil(coordf_t(bounding_box.min(0)) / distance_between_lines)), + coord_t(ceil(coordf_t(bounding_box.min(1)) / distance_between_lines)), + coord_t(ceil(coordf_t(bounding_box.max(0)) / distance_between_lines)), + coord_t(ceil(coordf_t(bounding_box.max(1)) / distance_between_lines))); Polylines polylines; if (pts.size() >= 2) { @@ -41,8 +41,8 @@ void FillPlanePath::_fill_surface_single( polyline.points.reserve(pts.size()); for (Pointfs::iterator it = pts.begin(); it != pts.end(); ++ it) polyline.points.push_back(Point( - coord_t(floor(it->x * distance_between_lines + 0.5)), - coord_t(floor(it->y * distance_between_lines + 0.5)))); + coord_t(floor((*it)(0) * distance_between_lines + 0.5)), + coord_t(floor((*it)(1) * distance_between_lines + 0.5)))); // intersection(polylines_src, offset((Polygons)expolygon, scale_(0.02)), &polylines); polylines = intersection_pl(polylines, to_polygons(expolygon)); @@ -62,7 +62,7 @@ void FillPlanePath::_fill_surface_single( // paths must be repositioned and rotated back for (Polylines::iterator it = polylines.begin(); it != polylines.end(); ++ it) { - it->translate(shift.x, shift.y); + it->translate(shift(0), shift(1)); it->rotate(direction.first); } } @@ -86,12 +86,12 @@ Pointfs FillArchimedeanChords::_generate(coord_t min_x, coord_t min_y, coord_t m coordf_t r = 1; Pointfs out; //FIXME Vojtech: If used as a solid infill, there is a gap left at the center. - out.push_back(Pointf(0, 0)); - out.push_back(Pointf(1, 0)); + out.push_back(Vec2d(0, 0)); + out.push_back(Vec2d(1, 0)); while (r < rmax) { theta += 1. / r; r = a + b * theta; - out.push_back(Pointf(r * cos(theta), r * sin(theta))); + out.push_back(Vec2d(r * cos(theta), r * sin(theta))); } return out; } @@ -162,7 +162,7 @@ Pointfs FillHilbertCurve::_generate(coord_t min_x, coord_t min_y, coord_t max_x, line.reserve(sz2); for (size_t i = 0; i < sz2; ++ i) { Point p = hilbert_n_to_xy(i); - line.push_back(Pointf(p.x + min_x, p.y + min_y)); + line.push_back(Vec2d(p(0) + min_x, p(1) + min_y)); } return line; } @@ -175,27 +175,27 @@ Pointfs FillOctagramSpiral::_generate(coord_t min_x, coord_t min_y, coord_t max_ coordf_t r = 0; coordf_t r_inc = sqrt(2.); Pointfs out; - out.push_back(Pointf(0, 0)); + out.push_back(Vec2d(0, 0)); while (r < rmax) { r += r_inc; coordf_t rx = r / sqrt(2.); coordf_t r2 = r + rx; - out.push_back(Pointf( r, 0.)); - out.push_back(Pointf( r2, rx)); - out.push_back(Pointf( rx, rx)); - out.push_back(Pointf( rx, r2)); - out.push_back(Pointf(0., r)); - out.push_back(Pointf(-rx, r2)); - out.push_back(Pointf(-rx, rx)); - out.push_back(Pointf(-r2, rx)); - out.push_back(Pointf(-r, 0.)); - out.push_back(Pointf(-r2, -rx)); - out.push_back(Pointf(-rx, -rx)); - out.push_back(Pointf(-rx, -r2)); - out.push_back(Pointf(0., -r)); - out.push_back(Pointf( rx, -r2)); - out.push_back(Pointf( rx, -rx)); - out.push_back(Pointf( r2+r_inc, -rx)); + out.push_back(Vec2d( r, 0.)); + out.push_back(Vec2d( r2, rx)); + out.push_back(Vec2d( rx, rx)); + out.push_back(Vec2d( rx, r2)); + out.push_back(Vec2d(0., r)); + out.push_back(Vec2d(-rx, r2)); + out.push_back(Vec2d(-rx, rx)); + out.push_back(Vec2d(-r2, rx)); + out.push_back(Vec2d(-r, 0.)); + out.push_back(Vec2d(-r2, -rx)); + out.push_back(Vec2d(-rx, -rx)); + out.push_back(Vec2d(-rx, -r2)); + out.push_back(Vec2d(0., -r)); + out.push_back(Vec2d( rx, -r2)); + out.push_back(Vec2d( rx, -rx)); + out.push_back(Vec2d( r2+r_inc, -rx)); } return out; } diff --git a/xs/src/libslic3r/Fill/FillRectilinear.cpp b/xs/src/libslic3r/Fill/FillRectilinear.cpp index 5ba30ba51..205eb1b66 100644 --- a/xs/src/libslic3r/Fill/FillRectilinear.cpp +++ b/xs/src/libslic3r/Fill/FillRectilinear.cpp @@ -26,8 +26,8 @@ void FillRectilinear::_fill_surface_single( // define flow spacing according to requested density if (params.density > 0.9999f && !params.dont_adjust) { - this->_line_spacing = this->_adjust_solid_spacing(bounding_box.size().x, this->_line_spacing); - this->spacing = unscale(this->_line_spacing); + this->_line_spacing = this->_adjust_solid_spacing(bounding_box.size()(0), this->_line_spacing); + this->spacing = unscale(this->_line_spacing); } else { // extend bounding box so that our pattern will be aligned with other layers // Transform the reference point to the rotated coordinate system. @@ -38,14 +38,14 @@ void FillRectilinear::_fill_surface_single( } // generate the basic pattern - coord_t x_max = bounding_box.max.x + SCALED_EPSILON; + coord_t x_max = bounding_box.max(0) + SCALED_EPSILON; Lines lines; - for (coord_t x = bounding_box.min.x; x <= x_max; x += this->_line_spacing) - lines.push_back(this->_line(lines.size(), x, bounding_box.min.y, bounding_box.max.y)); + for (coord_t x = bounding_box.min(0); x <= x_max; x += this->_line_spacing) + lines.push_back(this->_line(lines.size(), x, bounding_box.min(1), bounding_box.max(1))); if (this->_horizontal_lines()) { - coord_t y_max = bounding_box.max.y + SCALED_EPSILON; - for (coord_t y = bounding_box.min.y; y <= y_max; y += this->_line_spacing) - lines.push_back(Line(Point(bounding_box.min.x, y), Point(bounding_box.max.x, y))); + coord_t y_max = bounding_box.max(1) + SCALED_EPSILON; + for (coord_t y = bounding_box.min(1); y <= y_max; y += this->_line_spacing) + lines.push_back(Line(Point(bounding_box.min(0), y), Point(bounding_box.max(0), y))); } // clip paths against a slightly larger expolygon, so that the first and last paths @@ -72,10 +72,10 @@ void FillRectilinear::_fill_surface_single( for (Polylines::iterator it_polyline = polylines.begin(); it_polyline != polylines.end(); ++ it_polyline) { Point *first_point = &it_polyline->points.front(); Point *last_point = &it_polyline->points.back(); - if (first_point->y > last_point->y) + if (first_point->y() > last_point->y()) std::swap(first_point, last_point); - first_point->y -= extra; - last_point->y += extra; + first_point->y() -= extra; + last_point->y() += extra; } size_t n_polylines_out_old = polylines_out.size(); @@ -103,10 +103,10 @@ void FillRectilinear::_fill_surface_single( const Point &first_point = it_polyline->points.front(); const Point &last_point = pts_end.back(); // Distance in X, Y. - const Vector distance = first_point.vector_to(last_point); + const Vector distance = last_point - first_point; // TODO: we should also check that both points are on a fill_boundary to avoid // connecting paths on the boundaries of internal regions - if (this->_can_connect(std::abs(distance.x), std::abs(distance.y)) && + if (this->_can_connect(std::abs(distance(0)), std::abs(distance(1))) && expolygon_off.contains(Line(last_point, first_point))) { // Append the polyline. pts_end.insert(pts_end.end(), it_polyline->points.begin(), it_polyline->points.end()); @@ -122,7 +122,7 @@ void FillRectilinear::_fill_surface_single( // paths must be rotated back for (Polylines::iterator it = polylines_out.begin() + n_polylines_out_old; it != polylines_out.end(); ++ it) { // No need to translate, the absolute position is irrelevant. - // it->translate(- direction.second.x, - direction.second.y); + // it->translate(- direction.second(0), - direction.second(1)); it->rotate(direction.first); } } diff --git a/xs/src/libslic3r/Fill/FillRectilinear2.cpp b/xs/src/libslic3r/Fill/FillRectilinear2.cpp index ddd785101..65440d0ef 100644 --- a/xs/src/libslic3r/Fill/FillRectilinear2.cpp +++ b/xs/src/libslic3r/Fill/FillRectilinear2.cpp @@ -42,12 +42,12 @@ static inline coordf_t segment_length(const Polygon &poly, size_t seg1, const Po Point px = (i == 0) ? p1 : p2; Point pa = poly.points[((seg == 0) ? poly.points.size() : seg) - 1]; Point pb = poly.points[seg]; - if (pa.x > pb.x) - std::swap(pa.x, pb.x); - if (pa.y > pb.y) - std::swap(pa.y, pb.y); - assert(px.x >= pa.x && px.x <= pb.x); - assert(px.y >= pa.y && px.y <= pb.y); + if (pa(0) > pb(0)) + std::swap(pa(0), pb(0)); + if (pa(1) > pb(1)) + std::swap(pa(1), pb(1)); + assert(px(0) >= pa(0) && px(0) <= pb(0)); + assert(px(1) >= pa(1) && px(1) <= pb(1)); } #endif /* SLIC3R_DEBUG */ const Point *pPrev = &p1; @@ -55,14 +55,14 @@ static inline coordf_t segment_length(const Polygon &poly, size_t seg1, const Po coordf_t len = 0; if (seg1 <= seg2) { for (size_t i = seg1; i < seg2; ++ i, pPrev = pThis) - len += pPrev->distance_to(*(pThis = &poly.points[i])); + len += (*pPrev - *(pThis = &poly.points[i])).cast().norm(); } else { for (size_t i = seg1; i < poly.points.size(); ++ i, pPrev = pThis) - len += pPrev->distance_to(*(pThis = &poly.points[i])); + len += (*pPrev - *(pThis = &poly.points[i])).cast().norm(); for (size_t i = 0; i < seg2; ++ i, pPrev = pThis) - len += pPrev->distance_to(*(pThis = &poly.points[i])); + len += (*pPrev - *(pThis = &poly.points[i])).cast().norm(); } - len += pPrev->distance_to(p2); + len += (*pPrev - p2).cast().norm(); return len; } @@ -791,15 +791,15 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP // define flow spacing according to requested density if (params.full_infill() && !params.dont_adjust) { - line_spacing = this->_adjust_solid_spacing(bounding_box.size().x, line_spacing); - this->spacing = unscale(line_spacing); + line_spacing = this->_adjust_solid_spacing(bounding_box.size()(0), line_spacing); + this->spacing = unscale(line_spacing); } else { // extend bounding box so that our pattern will be aligned with other layers // Transform the reference point to the rotated coordinate system. Point refpt = rotate_vector.second.rotated(- rotate_vector.first); // _align_to_grid will not work correctly with positive pattern_shift. coord_t pattern_shift_scaled = coord_t(scale_(pattern_shift)) % line_spacing; - refpt.x -= (pattern_shift_scaled >= 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled); + refpt(0) -= (pattern_shift_scaled >= 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled); bounding_box.merge(_align_to_grid( bounding_box.min, Point(line_spacing, line_spacing), @@ -808,8 +808,8 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP // Intersect a set of euqally spaced vertical lines wiht expolygon. // n_vlines = ceil(bbox_width / line_spacing) - size_t n_vlines = (bounding_box.max.x - bounding_box.min.x + line_spacing - 1) / line_spacing; - coord_t x0 = bounding_box.min.x; + size_t n_vlines = (bounding_box.max(0) - bounding_box.min(0) + line_spacing - 1) / line_spacing; + coord_t x0 = bounding_box.min(0); if (params.full_infill()) x0 += (line_spacing + SCALED_EPSILON) / 2; @@ -842,8 +842,8 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP const Point &p1 = contour[iPrev]; const Point &p2 = contour[iSegment]; // Which of the equally spaced vertical lines is intersected by this segment? - coord_t l = p1.x; - coord_t r = p2.x; + coord_t l = p1(0); + coord_t r = p2(0); if (l > r) std::swap(l, r); // il, ir are the left / right indices of vertical lines intersecting a segment @@ -869,33 +869,33 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP assert(l <= this_x); assert(r >= this_x); // Calculate the intersection position in y axis. x is known. - if (p1.x == this_x) { - if (p2.x == this_x) { + if (p1(0) == this_x) { + if (p2(0) == this_x) { // Ignore strictly vertical segments. continue; } - is.pos_p = p1.y; + is.pos_p = p1(1); is.pos_q = 1; - } else if (p2.x == this_x) { - is.pos_p = p2.y; + } else if (p2(0) == this_x) { + is.pos_p = p2(1); is.pos_q = 1; } else { // First calculate the intersection parameter 't' as a rational number with non negative denominator. - if (p2.x > p1.x) { - is.pos_p = this_x - p1.x; - is.pos_q = p2.x - p1.x; + if (p2(0) > p1(0)) { + is.pos_p = this_x - p1(0); + is.pos_q = p2(0) - p1(0); } else { - is.pos_p = p1.x - this_x; - is.pos_q = p1.x - p2.x; + is.pos_p = p1(0) - this_x; + is.pos_q = p1(0) - p2(0); } assert(is.pos_p >= 0 && is.pos_p <= is.pos_q); // Make an intersection point from the 't'. - is.pos_p *= int64_t(p2.y - p1.y); - is.pos_p += p1.y * int64_t(is.pos_q); + is.pos_p *= int64_t(p2(1) - p1(1)); + is.pos_p += p1(1) * int64_t(is.pos_q); } // +-1 to take rounding into account. - assert(is.pos() + 1 >= std::min(p1.y, p2.y)); - assert(is.pos() <= std::max(p1.y, p2.y) + 1); + assert(is.pos() + 1 >= std::min(p1(1), p2(1))); + assert(is.pos() <= std::max(p1(1), p2(1)) + 1); segs[i].intersections.push_back(is); } } @@ -919,7 +919,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP const Points &contour = poly_with_offset.contour(iContour).points; size_t iSegment = sil.intersections[i].iSegment; size_t iPrev = ((iSegment == 0) ? contour.size() : iSegment) - 1; - coord_t dir = contour[iSegment].x - contour[iPrev].x; + coord_t dir = contour[iSegment](0) - contour[iPrev](0); bool low = dir > 0; sil.intersections[i].type = poly_with_offset.is_contour_outer(iContour) ? (low ? SegmentIntersection::OUTER_LOW : SegmentIntersection::OUTER_HIGH) : @@ -1066,7 +1066,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP intrsctn.consumed_vertical_up : seg.intersections[i-1].consumed_vertical_up; if (! consumed) { - coordf_t dist2 = sqr(coordf_t(pointLast.x - seg.pos)) + sqr(coordf_t(pointLast.y - intrsctn.pos())); + coordf_t dist2 = sqr(coordf_t(pointLast(0) - seg.pos)) + sqr(coordf_t(pointLast(1) - intrsctn.pos())); if (dist2 < dist2min) { dist2min = dist2; i_vline = i_vline2; @@ -1356,8 +1356,8 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP // Handle nearly zero length edges. if (polyline_current->points.size() <= 1 || (polyline_current->points.size() == 2 && - std::abs(polyline_current->points.front().x - polyline_current->points.back().x) < SCALED_EPSILON && - std::abs(polyline_current->points.front().y - polyline_current->points.back().y) < SCALED_EPSILON)) + std::abs(polyline_current->points.front()(0) - polyline_current->points.back()(0)) < SCALED_EPSILON && + std::abs(polyline_current->points.front()(1) - polyline_current->points.back()(1)) < SCALED_EPSILON)) polylines_out.pop_back(); intrsctn = NULL; i_intersection = -1; @@ -1383,7 +1383,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP // paths must be rotated back for (Polylines::iterator it = polylines_out.begin() + n_polylines_out_initial; it != polylines_out.end(); ++ it) { // No need to translate, the absolute position is irrelevant. - // it->translate(- rotate_vector.second.x, - rotate_vector.second.y); + // it->translate(- rotate_vector.second(0), - rotate_vector.second(1)); assert(! it->has_duplicate_points()); it->rotate(rotate_vector.first); //FIXME rather simplify the paths to avoid very short edges? diff --git a/xs/src/libslic3r/Fill/FillRectilinear3.cpp b/xs/src/libslic3r/Fill/FillRectilinear3.cpp index cccea3030..8fc129eac 100644 --- a/xs/src/libslic3r/Fill/FillRectilinear3.cpp +++ b/xs/src/libslic3r/Fill/FillRectilinear3.cpp @@ -217,30 +217,30 @@ Point SegmentIntersection::pos() const const Point &seg_start = poly.points[(this->iSegment == 0) ? poly.points.size() - 1 : this->iSegment - 1]; const Point &seg_end = poly.points[this->iSegment]; // Point, vector of the segment. - const Pointf p1 = convert_to(seg_start); - const Pointf v1 = convert_to(seg_end - seg_start); + const Vec2d p1(seg_start.cast()); + const Vec2d v1((seg_end - seg_start).cast()); // Point, vector of this hatching line. - const Pointf p2 = convert_to(line->pos); - const Pointf v2 = convert_to(line->dir); + const Vec2d p2(line->pos.cast()); + const Vec2d v2(line->dir.cast()); // Intersect the two rays. - double denom = v1.x * v2.y - v2.x * v1.y; + double denom = v1(0) * v2(1) - v2(0) * v1(1); Point out; if (denom == 0.) { // Lines are collinear. As the pos() method is not supposed to be called on collinear vectors, // the source vectors are not quite collinear. Return the center of the contour segment. out = seg_start + seg_end; - out.x >>= 1; - out.y >>= 1; + out(0) >>= 1; + out(1) >>= 1; } else { // Find the intersection point. - double t = (v2.x * (p1.y - p2.y) - v2.y * (p1.x - p2.x)) / denom; + double t = (v2(0) * (p1(1) - p2(1)) - v2(1) * (p1(0) - p2(0))) / denom; if (t < 0.) out = seg_start; else if (t > 1.) out = seg_end; else { - out.x = coord_t(floor(p1.x + t * v1.x + 0.5)); - out.y = coord_t(floor(p1.y + t * v1.y + 0.5)); + out(0) = coord_t(floor(p1(0) + t * v1(0) + 0.5)); + out(1) = coord_t(floor(p1(1) + t * v1(1) + 0.5)); } } return out; @@ -276,13 +276,13 @@ int SegmentIntersection::ordering_along_line(const SegmentIntersection &other) c // other.iSegment succeeds this->iSegment assert(seg_end_a == seg_start_b); // Avoid calling the 128bit x 128bit multiplication below if this->line intersects the common point. - if (cross(this->line->dir, seg_end_b - this->line->pos) == 0) + if (cross2(Vec2i64(this->line->dir.cast()), (seg_end_b - this->line->pos).cast()) == 0) return 0; } else if ((other.iSegment + 1) % poly_a.points.size() == this->iSegment) { // this->iSegment succeeds other.iSegment assert(seg_start_a == seg_end_b); // Avoid calling the 128bit x 128bit multiplication below if this->line intersects the common point. - if (cross(this->line->dir, seg_start_a - this->line->pos) == 0) + if (cross2(Vec2i64(this->line->dir.cast()), (seg_start_a - this->line->pos).cast()) == 0) return 0; } else { // General case. @@ -290,35 +290,35 @@ int SegmentIntersection::ordering_along_line(const SegmentIntersection &other) c } // First test, whether both points of one segment are completely in one half-plane of the other line. - const Point vec_b = seg_end_b - seg_start_b; - int side_start = signum(cross(vec_b, seg_start_a - seg_start_b)); - int side_end = signum(cross(vec_b, seg_end_a - seg_start_b)); + const Vec2i64 vec_b = (seg_end_b - seg_start_b).cast(); + int side_start = signum(cross2(vec_b, (seg_start_a - seg_start_b).cast())); + int side_end = signum(cross2(vec_b, (seg_end_a - seg_start_b).cast())); int side = side_start * side_end; if (side > 0) // This segment is completely inside one half-plane of the other line, therefore the ordering is trivial. - return signum(cross(vec_b, this->line->dir)) * side_start; + return signum(cross2(vec_b, this->line->dir.cast())) * side_start; - const Point vec_a = seg_end_a - seg_start_a; - int side_start2 = signum(cross(vec_a, seg_start_b - seg_start_a)); - int side_end2 = signum(cross(vec_a, seg_end_b - seg_start_a)); + const Vec2i64 vec_a = (seg_end_a - seg_start_a).cast(); + int side_start2 = signum(cross2(vec_a, (seg_start_b - seg_start_a).cast())); + int side_end2 = signum(cross2(vec_a, (seg_end_b - seg_start_a).cast())); int side2 = side_start2 * side_end2; //if (side == 0 && side2 == 0) // The segments share one of their end points. if (side2 > 0) // This segment is completely inside one half-plane of the other line, therefore the ordering is trivial. - return signum(cross(this->line->dir, vec_a)) * side_start2; + return signum(cross2(this->line->dir.cast(), vec_a)) * side_start2; // The two segments intersect and they are not sucessive segments of the same contour. // Ordering of the points depends on the position of the segment intersection (left / right from this->line), // therefore a simple test over the input segment end points is not sufficient. // Find the parameters of intersection of the two segmetns with this->line. - int64_t denom1 = cross(this->line->dir, vec_a); - int64_t denom2 = cross(this->line->dir, vec_b); - Point vx_a = seg_start_a - this->line->pos; - Point vx_b = seg_start_b - this->line->pos; - int64_t t1_times_denom1 = int64_t(vx_a.x) * int64_t(vec_a.y) - int64_t(vx_a.y) * int64_t(vec_a.x); - int64_t t2_times_denom2 = int64_t(vx_b.x) * int64_t(vec_b.y) - int64_t(vx_b.y) * int64_t(vec_b.x); + int64_t denom1 = cross2(this->line->dir.cast(), vec_a); + int64_t denom2 = cross2(this->line->dir.cast(), vec_b); + Vec2i64 vx_a = (seg_start_a - this->line->pos).cast(); + Vec2i64 vx_b = (seg_start_b - this->line->pos).cast(); + int64_t t1_times_denom1 = vx_a(0) * vec_a(1) - vx_a(1) * vec_a(0); + int64_t t2_times_denom2 = vx_b(0) * vec_b(1) - vx_b(1) * vec_b(0); assert(denom1 != 0); assert(denom2 != 0); return Int128::compare_rationals_filtered(t1_times_denom1, denom1, t2_times_denom2, denom2); @@ -330,7 +330,7 @@ bool SegmentIntersection::operator<(const SegmentIntersection &other) const #ifdef _DEBUG Point p1 = this->pos(); Point p2 = other.pos(); - int64_t d = dot(this->line->dir, p2 - p1); + int64_t d = this->line->dir.cast().dot((p2 - p1).cast()); #endif /* _DEBUG */ int ordering = this->ordering_along_line(other); #ifdef _DEBUG @@ -389,16 +389,16 @@ static bool prepare_infill_hatching_segments( // Define the flow spacing according to requested density. if (params.full_infill() && ! params.dont_adjust) { // Full infill, adjust the line spacing to fit an integer number of lines. - out.line_spacing = Fill::_adjust_solid_spacing(bounding_box.size().x, line_spacing); + out.line_spacing = Fill::_adjust_solid_spacing(bounding_box.size()(0), line_spacing); // Report back the adjusted line spacing. - fill_dir_params.spacing = float(unscale(line_spacing)); + fill_dir_params.spacing = unscale(line_spacing); } else { // Extend bounding box so that our pattern will be aligned with the other layers. // Transform the reference point to the rotated coordinate system. Point refpt = rotate_vector.second.rotated(- out.angle); // _align_to_grid will not work correctly with positive pattern_shift. coord_t pattern_shift_scaled = coord_t(scale_(fill_dir_params.pattern_shift)) % line_spacing; - refpt.x -= (pattern_shift_scaled >= 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled); + refpt(0) -= (pattern_shift_scaled >= 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled); bounding_box.merge(Fill::_align_to_grid( bounding_box.min, Point(line_spacing, line_spacing), @@ -407,13 +407,13 @@ static bool prepare_infill_hatching_segments( // Intersect a set of euqally spaced vertical lines wiht expolygon. // n_vlines = ceil(bbox_width / line_spacing) - size_t n_vlines = (bounding_box.max.x - bounding_box.min.x + line_spacing - 1) / line_spacing; - coord_t x0 = bounding_box.min.x; + size_t n_vlines = (bounding_box.max(0) - bounding_box.min(0) + line_spacing - 1) / line_spacing; + coord_t x0 = bounding_box.min(0); if (params.full_infill()) x0 += coord_t((line_spacing + SCALED_EPSILON) / 2); out.line_spacing = line_spacing; - out.start_point = Point(x0, bounding_box.min.y); + out.start_point = Point(x0, bounding_box.min(1)); out.start_point.rotate(out.angle); #ifdef SLIC3R_DEBUG @@ -436,10 +436,10 @@ static bool prepare_infill_hatching_segments( for (size_t i = 0; i < n_vlines; ++ i) { auto &seg = out.segs[i]; seg.idx = i; - // seg.x = x0 + coord_t(i) * line_spacing; + // seg(0) = x0 + coord_t(i) * line_spacing; coord_t x = x0 + coord_t(i) * line_spacing; - seg.pos.x = coord_t(floor(cos_a * x - sin_a * bounding_box.min.y + 0.5)); - seg.pos.y = coord_t(floor(cos_a * bounding_box.min.y + sin_a * x + 0.5)); + seg.pos(0) = coord_t(floor(cos_a * x - sin_a * bounding_box.min(1) + 0.5)); + seg.pos(1) = coord_t(floor(cos_a * bounding_box.min(1) + sin_a * x + 0.5)); seg.dir = out.direction; } @@ -454,7 +454,7 @@ static bool prepare_infill_hatching_segments( const Point *pr = &contour[iSegment]; // Orient the segment to the direction vector. const Point v = *pr - *pl; - int orientation = Int128::sign_determinant_2x2_filtered(v.x, v.y, out.direction.x, out.direction.y); + int orientation = Int128::sign_determinant_2x2_filtered(v(0), v(1), out.direction(0), out.direction(1)); if (orientation == 0) // Ignore strictly vertical segments. continue; @@ -462,8 +462,8 @@ static bool prepare_infill_hatching_segments( // Always orient the input segment consistently towards the hatching direction. std::swap(pl, pr); // Which of the equally spaced vertical lines is intersected by this segment? - coord_t l = (coord_t)floor(cos_a * pl->x + sin_a * pl->y - SCALED_EPSILON); - coord_t r = (coord_t)ceil (cos_a * pr->x + sin_a * pr->y + SCALED_EPSILON); + coord_t l = (coord_t)floor(cos_a * (*pl)(0) + sin_a * (*pl)(1) - SCALED_EPSILON); + coord_t r = (coord_t)ceil (cos_a * (*pr)(0) + sin_a * (*pr)(1) + SCALED_EPSILON); assert(l < r - SCALED_EPSILON); // il, ir are the left / right indices of vertical lines intersecting a segment int il = std::max(0, (l - x0 + line_spacing) / line_spacing); @@ -479,9 +479,9 @@ static bool prepare_infill_hatching_segments( // 2) all lines from il to ir intersect . assert(il >= 0 && ir < int(out.segs.size())); for (int i = il; i <= ir; ++ i) { - // assert(out.segs[i].x == i * line_spacing + x0); - // assert(l <= out.segs[i].x); - // assert(r >= out.segs[i].x); + // assert(out.segs[i](0) == i * line_spacing + x0); + // assert(l <= out.segs[i](0)); + // assert(r >= out.segs[i](0)); SegmentIntersection is; is.line = &out.segs[i]; is.expoly_with_offset = &poly_with_offset; @@ -491,10 +491,10 @@ static bool prepare_infill_hatching_segments( // +-1 to take rounding into account. assert(int128::orient(out.segs[i].pos, out.segs[i].pos + out.direction, *pl) >= 0); assert(int128::orient(out.segs[i].pos, out.segs[i].pos + out.direction, *pr) <= 0); - assert(is.pos().x + 1 >= std::min(pl->x, pr->x)); - assert(is.pos().y + 1 >= std::min(pl->y, pr->y)); - assert(is.pos().x <= std::max(pl->x, pr->x) + 1); - assert(is.pos().y <= std::max(pl->y, pr->y) + 1); + assert(is.pos()(0) + 1 >= std::min((*pl)(0), (*pr)(0))); + assert(is.pos()(1) + 1 >= std::min((*pl)(1), (*pr)(1))); + assert(is.pos()(0) <= std::max((*pl)(0), (*pr)(0)) + 1); + assert(is.pos()(1) <= std::max((*pl)(1), (*pr)(1)) + 1); out.segs[i].intersections.push_back(is); } } @@ -510,7 +510,7 @@ static bool prepare_infill_hatching_segments( for (size_t i = 1; i < sil.intersections.size(); ++ i) { Point p1 = sil.intersections[i - 1].pos(); Point p2 = sil.intersections[i].pos(); - int64_t d = dot(sil.dir, p2 - p1); + int64_t d = sil.dir.cast().dot((p2 - p1).cast()); assert(d >= - int64_t(SCALED_EPSILON)); } #endif /* _DEBUG */ @@ -659,12 +659,12 @@ static inline coordf_t segment_length(const Polygon &poly, size_t seg1, const Po Point px = (i == 0) ? p1 : p2; Point pa = poly.points[((seg == 0) ? poly.points.size() : seg) - 1]; Point pb = poly.points[seg]; - if (pa.x > pb.x) - std::swap(pa.x, pb.x); - if (pa.y > pb.y) - std::swap(pa.y, pb.y); - assert(px.x >= pa.x && px.x <= pb.x); - assert(px.y >= pa.y && px.y <= pb.y); + if (pa(0) > pb(0)) + std::swap(pa(0), pb(0)); + if (pa(1) > pb(1)) + std::swap(pa(1), pb(1)); + assert(px(0) >= pa(0) && px(0) <= pb(0)); + assert(px(1) >= pa(1) && px(1) <= pb(1)); } #endif /* SLIC3R_DEBUG */ const Point *pPrev = &p1; @@ -672,14 +672,14 @@ static inline coordf_t segment_length(const Polygon &poly, size_t seg1, const Po coordf_t len = 0; if (seg1 <= seg2) { for (size_t i = seg1; i < seg2; ++ i, pPrev = pThis) - len += pPrev->distance_to(*(pThis = &poly.points[i])); + len += (*pPrev - *(pThis = &poly.points[i])).cast().norm(); } else { for (size_t i = seg1; i < poly.points.size(); ++ i, pPrev = pThis) - len += pPrev->distance_to(*(pThis = &poly.points[i])); + len += (*pPrev - *(pThis = &poly.points[i])).cast().norm(); for (size_t i = 0; i < seg2; ++ i, pPrev = pThis) - len += pPrev->distance_to(*(pThis = &poly.points[i])); + len += (*pPrev - *(pThis = &poly.points[i])).cast().norm(); } - len += pPrev->distance_to(p2); + len += (*pPrev - p2).cast().norm(); return len; } @@ -1191,7 +1191,7 @@ static bool fill_hatching_segments_legacy( intrsctn.consumed_vertical_up : seg.intersections[i-1].consumed_vertical_up; if (! consumed) { - coordf_t dist2 = pointLast.distance_to(intrsctn.pos()); + coordf_t dist2 = (intrsctn.pos() - pointLast).cast().norm(); if (dist2 < dist2min) { dist2min = dist2; i_vline = i_vline2; @@ -1481,8 +1481,8 @@ static bool fill_hatching_segments_legacy( // Handle nearly zero length edges. if (polyline_current->points.size() <= 1 || (polyline_current->points.size() == 2 && - std::abs(polyline_current->points.front().x - polyline_current->points.back().x) < SCALED_EPSILON && - std::abs(polyline_current->points.front().y - polyline_current->points.back().y) < SCALED_EPSILON)) + std::abs(polyline_current->points.front()(0) - polyline_current->points.back()(0)) < SCALED_EPSILON && + std::abs(polyline_current->points.front()(1) - polyline_current->points.back()(1)) < SCALED_EPSILON)) polylines_out.pop_back(); intrsctn = NULL; i_intersection = -1; @@ -1510,7 +1510,7 @@ static bool fill_hatching_segments_legacy( // paths must be rotated back for (Polylines::iterator it = polylines_out.begin() + n_polylines_out_initial; it != polylines_out.end(); ++ it) { // No need to translate, the absolute position is irrelevant. - // it->translate(- rotate_vector.second.x, - rotate_vector.second.y); + // it->translate(- rotate_vector.second(0), - rotate_vector.second(1)); assert(! it->has_duplicate_points()); //it->rotate(rotate_vector.first); //FIXME rather simplify the paths to avoid very short edges? diff --git a/xs/src/libslic3r/Format/3mf.cpp b/xs/src/libslic3r/Format/3mf.cpp index 5de1d26c5..d05460408 100644 --- a/xs/src/libslic3r/Format/3mf.cpp +++ b/xs/src/libslic3r/Format/3mf.cpp @@ -1352,8 +1352,8 @@ namespace Slic3r { double angle_z = (rotation.axis() == Eigen::Vector3d::UnitZ()) ? rotation.angle() : -rotation.angle(); #endif - instance.offset.x = offset_x; - instance.offset.y = offset_y; + instance.offset(0) = offset_x; + instance.offset(1) = offset_y; instance.scaling_factor = sx; instance.rotation = angle_z; } @@ -1485,7 +1485,7 @@ namespace Slic3r { stl_facet& facet = stl.facet_start[i]; for (unsigned int v = 0; v < 3; ++v) { - ::memcpy((void*)&facet.vertex[v].x, (const void*)&geometry.vertices[geometry.triangles[src_start_id + ii + v] * 3], 3 * sizeof(float)); + ::memcpy(facet.vertex[v].data(), (const void*)&geometry.vertices[geometry.triangles[src_start_id + ii + v] * 3], 3 * sizeof(float)); } } @@ -1802,7 +1802,7 @@ namespace Slic3r { } Eigen::Affine3f transform; - transform = Eigen::Translation3f((float)instance->offset.x, (float)instance->offset.y, 0.0f) * Eigen::AngleAxisf((float)instance->rotation, Eigen::Vector3f::UnitZ()) * Eigen::Scaling((float)instance->scaling_factor); + transform = Eigen::Translation3f((float)instance->offset(0), (float)instance->offset(1), 0.0f) * Eigen::AngleAxisf((float)instance->rotation, Eigen::Vector3f::UnitZ()) * Eigen::Scaling((float)instance->scaling_factor); build_items.emplace_back(instance_id, transform.matrix()); stream << " \n"; @@ -1845,9 +1845,9 @@ namespace Slic3r { for (int i = 0; i < stl.stats.shared_vertices; ++i) { stream << " <" << VERTEX_TAG << " "; - stream << "x=\"" << stl.v_shared[i].x << "\" "; - stream << "y=\"" << stl.v_shared[i].y << "\" "; - stream << "z=\"" << stl.v_shared[i].z << "\" />\n"; + stream << "x=\"" << stl.v_shared[i](0) << "\" "; + stream << "y=\"" << stl.v_shared[i](1) << "\" "; + stream << "z=\"" << stl.v_shared[i](2) << "\" />\n"; } } diff --git a/xs/src/libslic3r/Format/AMF.cpp b/xs/src/libslic3r/Format/AMF.cpp index 886bbae97..81617ad72 100644 --- a/xs/src/libslic3r/Format/AMF.cpp +++ b/xs/src/libslic3r/Format/AMF.cpp @@ -402,7 +402,7 @@ void AMFParserContext::endElement(const char * /* name */) for (size_t i = 0; i < m_volume_facets.size();) { stl_facet &facet = stl.facet_start[i/3]; for (unsigned int v = 0; v < 3; ++ v) - memcpy(&facet.vertex[v].x, &m_object_vertices[m_volume_facets[i ++] * 3], 3 * sizeof(float)); + memcpy(facet.vertex[v].data(), &m_object_vertices[m_volume_facets[i ++] * 3], 3 * sizeof(float)); } stl_get_size(&stl); m_volume->mesh.repair(); @@ -498,8 +498,8 @@ void AMFParserContext::endDocument() for (const Instance &instance : object.second.instances) if (instance.deltax_set && instance.deltay_set) { ModelInstance *mi = m_model.objects[object.second.idx]->add_instance(); - mi->offset.x = instance.deltax; - mi->offset.y = instance.deltay; + mi->offset(0) = instance.deltax; + mi->offset(1) = instance.deltay; mi->rotation = instance.rz_set ? instance.rz : 0.f; mi->scaling_factor = instance.scale_set ? instance.scale : 1.f; } @@ -761,9 +761,9 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c for (size_t i = 0; i < stl.stats.shared_vertices; ++ i) { stream << " \n"; stream << " \n"; - stream << " " << stl.v_shared[i].x << "\n"; - stream << " " << stl.v_shared[i].y << "\n"; - stream << " " << stl.v_shared[i].z << "\n"; + stream << " " << stl.v_shared[i](0) << "\n"; + stream << " " << stl.v_shared[i](1) << "\n"; + stream << " " << stl.v_shared[i](2) << "\n"; stream << " \n"; stream << " \n"; } @@ -804,8 +804,8 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c " %lf\n" " \n", object_id, - instance->offset.x, - instance->offset.y, + instance->offset(0), + instance->offset(1), instance->rotation, instance->scaling_factor); //FIXME missing instance->scaling_factor diff --git a/xs/src/libslic3r/Format/OBJ.cpp b/xs/src/libslic3r/Format/OBJ.cpp index ea6b5604c..ee5756083 100644 --- a/xs/src/libslic3r/Format/OBJ.cpp +++ b/xs/src/libslic3r/Format/OBJ.cpp @@ -57,14 +57,14 @@ bool load_obj(const char *path, Model *model, const char *object_name_in) continue; stl_facet &facet = stl.facet_start[i_face ++]; size_t num_normals = 0; - stl_normal normal = { 0.f }; + stl_normal normal(stl_normal::Zero()); for (unsigned int v = 0; v < 3; ++ v) { const ObjParser::ObjVertex &vertex = data.vertices[i++]; - memcpy(&facet.vertex[v].x, &data.coordinates[vertex.coordIdx*4], 3 * sizeof(float)); + memcpy(facet.vertex[v].data(), &data.coordinates[vertex.coordIdx*4], 3 * sizeof(float)); if (vertex.normalIdx != -1) { - normal.x += data.normals[vertex.normalIdx*3]; - normal.y += data.normals[vertex.normalIdx*3+1]; - normal.z += data.normals[vertex.normalIdx*3+2]; + normal(0) += data.normals[vertex.normalIdx*3]; + normal(1) += data.normals[vertex.normalIdx*3+1]; + normal(2) += data.normals[vertex.normalIdx*3+2]; ++ num_normals; } } @@ -74,33 +74,27 @@ bool load_obj(const char *path, Model *model, const char *object_name_in) facet2.vertex[0] = facet.vertex[0]; facet2.vertex[1] = facet.vertex[2]; const ObjParser::ObjVertex &vertex = data.vertices[i++]; - memcpy(&facet2.vertex[2].x, &data.coordinates[vertex.coordIdx * 4], 3 * sizeof(float)); + memcpy(facet2.vertex[2].data(), &data.coordinates[vertex.coordIdx * 4], 3 * sizeof(float)); if (vertex.normalIdx != -1) { - normal.x += data.normals[vertex.normalIdx*3]; - normal.y += data.normals[vertex.normalIdx*3+1]; - normal.z += data.normals[vertex.normalIdx*3+2]; + normal(0) += data.normals[vertex.normalIdx*3]; + normal(1) += data.normals[vertex.normalIdx*3+1]; + normal(2) += data.normals[vertex.normalIdx*3+2]; ++ num_normals; } if (num_normals == 4) { // Normalize an average normal of a quad. - float len = sqrt(facet.normal.x*facet.normal.x + facet.normal.y*facet.normal.y + facet.normal.z*facet.normal.z); + float len = facet.normal.norm(); if (len > EPSILON) { - normal.x /= len; - normal.y /= len; - normal.z /= len; + normal /= len; facet.normal = normal; facet2.normal = normal; } } } else if (num_normals == 3) { // Normalize an average normal of a triangle. - float len = sqrt(facet.normal.x*facet.normal.x + facet.normal.y*facet.normal.y + facet.normal.z*facet.normal.z); - if (len > EPSILON) { - normal.x /= len; - normal.y /= len; - normal.z /= len; - facet.normal = normal; - } + float len = facet.normal.norm(); + if (len > EPSILON) + facet.normal = normal / len; } } stl_get_size(&stl); diff --git a/xs/src/libslic3r/Format/PRUS.cpp b/xs/src/libslic3r/Format/PRUS.cpp index 1809eaead..3cf3fc075 100644 --- a/xs/src/libslic3r/Format/PRUS.cpp +++ b/xs/src/libslic3r/Format/PRUS.cpp @@ -166,7 +166,7 @@ bool load_prus(const char *path, Model *model) float trafo[3][4] = { 0 }; double instance_rotation = 0.; double instance_scaling_factor = 1.f; - Pointf instance_offset(0., 0.); + Vec2d instance_offset(0., 0.); bool trafo_set = false; unsigned int group_id = (unsigned int)-1; unsigned int extruder_id = (unsigned int)-1; @@ -207,8 +207,8 @@ bool load_prus(const char *path, Model *model) for (size_t c = 0; c < 3; ++ c) trafo[r][c] += mat_trafo(r, c); } - instance_offset.x = position[0] - zero[0]; - instance_offset.y = position[1] - zero[1]; + instance_offset(0) = position[0] - zero[0]; + instance_offset(1) = position[1] - zero[1]; trafo[2][3] = position[2] / instance_scaling_factor; trafo_set = true; } @@ -260,8 +260,8 @@ bool load_prus(const char *path, Model *model) mesh.repair(); // Transform the model. stl_transform(&stl, &trafo[0][0]); - if (std::abs(stl.stats.min.z) < EPSILON) - stl.stats.min.z = 0.; + if (std::abs(stl.stats.min(2)) < EPSILON) + stl.stats.min(2) = 0.; // Add a mesh to a model. if (mesh.facets_count() > 0) mesh_valid = true; @@ -309,11 +309,11 @@ bool load_prus(const char *path, Model *model) assert(res_normal == 3); int res_outer_loop = line_reader.next_line_scanf(" outer loop"); assert(res_outer_loop == 0); - int res_vertex1 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[0].x, &facet.vertex[0].y, &facet.vertex[0].z); + int res_vertex1 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[0](0), &facet.vertex[0](1), &facet.vertex[0](2)); assert(res_vertex1 == 3); - int res_vertex2 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[1].x, &facet.vertex[1].y, &facet.vertex[1].z); + int res_vertex2 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[1](0), &facet.vertex[1](1), &facet.vertex[1](2)); assert(res_vertex2 == 3); - int res_vertex3 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[2].x, &facet.vertex[2].y, &facet.vertex[2].z); + int res_vertex3 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[2](0), &facet.vertex[2](1), &facet.vertex[2](2)); assert(res_vertex3 == 3); int res_endloop = line_reader.next_line_scanf(" endloop"); assert(res_endloop == 0); @@ -324,9 +324,9 @@ bool load_prus(const char *path, Model *model) break; } // The facet normal has been parsed as a single string as to workaround for not a numbers in the normal definition. - if (sscanf(normal_buf[0], "%f", &facet.normal.x) != 1 || - sscanf(normal_buf[1], "%f", &facet.normal.y) != 1 || - sscanf(normal_buf[2], "%f", &facet.normal.z) != 1) { + if (sscanf(normal_buf[0], "%f", &facet.normal(0)) != 1 || + sscanf(normal_buf[1], "%f", &facet.normal(1)) != 1 || + sscanf(normal_buf[2], "%f", &facet.normal(2)) != 1) { // Normal was mangled. Maybe denormals or "not a number" were stored? // Just reset the normal and silently ignore it. memset(&facet.normal, 0, sizeof(facet.normal)); diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index b34ba5441..fa18ddf3f 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -49,11 +49,11 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point & // If use_external, then perform the path planning in the world coordinate system (correcting for the gcodegen offset). // Otherwise perform the path planning in the coordinate system of the active object. bool use_external = this->use_external_mp || this->use_external_mp_once; - Point scaled_origin = use_external ? Point::new_scale(gcodegen.origin().x, gcodegen.origin().y) : Point(0, 0); + Point scaled_origin = use_external ? Point::new_scale(gcodegen.origin()(0), gcodegen.origin()(1)) : Point(0, 0); Polyline result = (use_external ? m_external_mp.get() : m_layer_mp.get())-> shortest_path(gcodegen.last_pos() + scaled_origin, point + scaled_origin); if (use_external) - result.translate(scaled_origin.negative()); + result.translate(- scaled_origin); return result; } @@ -64,8 +64,8 @@ std::string OozePrevention::pre_toolchange(GCode &gcodegen) // move to the nearest standby point if (!this->standby_points.empty()) { // get current position in print coordinates - Pointf3 writer_pos = gcodegen.writer().get_position(); - Point pos = Point::new_scale(writer_pos.x, writer_pos.y); + Vec3d writer_pos = gcodegen.writer().get_position(); + Point pos = Point::new_scale(writer_pos(0), writer_pos(1)); // find standby point Point standby_point; @@ -74,7 +74,7 @@ std::string OozePrevention::pre_toolchange(GCode &gcodegen) /* We don't call gcodegen.travel_to() because we don't need retraction (it was already triggered by the caller) nor avoid_crossing_perimeters and also because the coordinates of the destination point must not be transformed by origin nor current extruder offset. */ - gcode += gcodegen.writer().travel_to_xy(Pointf::new_unscale(standby_point), + gcode += gcodegen.writer().travel_to_xy(unscale(standby_point), "move to standby position"); } @@ -160,7 +160,7 @@ Wipe::wipe(GCode &gcodegen, bool toolchange) static inline Point wipe_tower_point_to_object_point(GCode &gcodegen, const WipeTower::xy &wipe_tower_pt) { - return Point(scale_(wipe_tower_pt.x - gcodegen.origin().x), scale_(wipe_tower_pt.y - gcodegen.origin().y)); + return Point(scale_(wipe_tower_pt.x - gcodegen.origin()(0)), scale_(wipe_tower_pt.y - gcodegen.origin()(1))); } std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const @@ -207,7 +207,7 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T check_add_eol(gcode); } // A phony move to the end position at the wipe tower. - gcodegen.writer().travel_to_xy(Pointf(end_pos.x, end_pos.y)); + gcodegen.writer().travel_to_xy(Vec2d(end_pos.x, end_pos.y)); gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, end_pos)); // Prepare a future wipe. @@ -293,7 +293,7 @@ std::string WipeTowerIntegration::prime(GCode &gcodegen) gcodegen.writer().toolchange(current_extruder_id); gcodegen.placeholder_parser().set("current_extruder", current_extruder_id); // A phony move to the end position at the wipe tower. - gcodegen.writer().travel_to_xy(Pointf(m_priming.end_pos.x, m_priming.end_pos.y)); + gcodegen.writer().travel_to_xy(Vec2d(m_priming.end_pos.x, m_priming.end_pos.y)); gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, m_priming.end_pos)); // Prepare a future wipe. gcodegen.m_wipe.path.points.clear(); @@ -325,7 +325,7 @@ std::string WipeTowerIntegration::tool_change(GCode &gcodegen, int extruder_id, std::string WipeTowerIntegration::finalize(GCode &gcodegen) { std::string gcode; - if (std::abs(gcodegen.writer().get_position().z - m_final_purge.print_z) > EPSILON) + if (std::abs(gcodegen.writer().get_position()(2) - m_final_purge.print_z) > EPSILON) gcode += gcodegen.change_layer(m_final_purge.print_z); gcode += append_tcr(gcodegen, m_final_purge, -1); return gcode; @@ -767,7 +767,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data) for (const ExPolygon &expoly : layer->slices.expolygons) for (const Point © : object->_shifted_copies) { islands.emplace_back(expoly.contour); - islands.back().translate(copy); + islands.back().translate(- copy); } //FIXME Mege the islands in parallel. m_avoid_crossing_perimeters.init_external_mp(union_ex(islands)); @@ -783,9 +783,9 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data) Polygon outer_skirt = Slic3r::Geometry::convex_hull(skirt_points); Polygons skirts; for (unsigned int extruder_id : print.extruders()) { - const Pointf &extruder_offset = print.config.extruder_offset.get_at(extruder_id); + const Vec2d &extruder_offset = print.config.extruder_offset.get_at(extruder_id); Polygon s(outer_skirt); - s.translate(-scale_(extruder_offset.x), -scale_(extruder_offset.y)); + s.translate(Point::new_scale(- extruder_offset(0), - extruder_offset(1))); skirts.emplace_back(std::move(s)); } m_ooze_prevention.enable = true; @@ -814,7 +814,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data) // Print objects from the smallest to the tallest to avoid collisions // when moving onto next object starting point. std::vector objects(printable_objects); - std::sort(objects.begin(), objects.end(), [](const PrintObject* po1, const PrintObject* po2) { return po1->size.z < po2->size.z; }); + std::sort(objects.begin(), objects.end(), [](const PrintObject* po1, const PrintObject* po2) { return po1->size(2) < po2->size(2); }); size_t finished_objects = 0; for (size_t object_id = initial_print_object_id; object_id < objects.size(); ++ object_id) { const PrintObject &object = *objects[object_id]; @@ -831,7 +831,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data) final_extruder_id = tool_ordering.last_extruder(); assert(final_extruder_id != (unsigned int)-1); } - this->set_origin(unscale(copy.x), unscale(copy.y)); + this->set_origin(unscale(copy)); if (finished_objects > 0) { // Move to the origin position for the copy we're going to print. // This happens before Z goes down to layer 0 again, so that no collision happens hopefully. @@ -940,7 +940,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data) { DynamicConfig config; config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index)); - config.set_key_value("layer_z", new ConfigOptionFloat(m_writer.get_position().z - m_config.z_offset.value)); + config.set_key_value("layer_z", new ConfigOptionFloat(m_writer.get_position()(2) - m_config.z_offset.value)); if (print.config.single_extruder_multi_material) { // Process the end_filament_gcode for the active filament only. _writeln(file, this->placeholder_parser_process("end_filament_gcode", print.config.end_filament_gcode.get_at(m_writer.extruder()->id()), m_writer.extruder()->id(), &config)); @@ -1396,8 +1396,8 @@ void GCode::process_layer( layer_surface_bboxes.push_back(get_extents(expoly.contour)); auto point_inside_surface = [&layer, &layer_surface_bboxes](const size_t i, const Point &point) { const BoundingBox &bbox = layer_surface_bboxes[i]; - return point.x >= bbox.min.x && point.x < bbox.max.x && - point.y >= bbox.min.y && point.y < bbox.max.y && + return point(0) >= bbox.min(0) && point(0) < bbox.max(0) && + point(1) >= bbox.min(1) && point(1) < bbox.max(1) && layer.slices.expolygons[i].contour.contains(point); }; @@ -1547,7 +1547,7 @@ void GCode::process_layer( if (m_last_obj_copy != this_object_copy) m_avoid_crossing_perimeters.use_external_mp_once = true; m_last_obj_copy = this_object_copy; - this->set_origin(unscale(copy.x), unscale(copy.y)); + this->set_origin(unscale(copy)); if (object_by_extruder.support != nullptr && !print_wipe_extrusions) { m_layer = layers[layer_id].support_layer; gcode += this->extrude_support( @@ -1632,14 +1632,14 @@ void GCode::set_extruders(const std::vector &extruder_ids) } } -void GCode::set_origin(const Pointf &pointf) +void GCode::set_origin(const Vec2d &pointf) { // if origin increases (goes towards right), last_pos decreases because it goes towards left const Point translate( - scale_(m_origin.x - pointf.x), - scale_(m_origin.y - pointf.y) + scale_(m_origin(0) - pointf(0)), + scale_(m_origin(1) - pointf(1)) ); - m_last_pos.translate(translate); + m_last_pos += translate; m_wipe.path.translate(translate); m_origin = pointf; } @@ -1770,13 +1770,13 @@ static Points::iterator project_point_to_polygon_and_insert(Polygon &polygon, co j = 0; const Point &p1 = polygon.points[i]; const Point &p2 = polygon.points[j]; - const Slic3r::Point v_seg = p1.vector_to(p2); - const Slic3r::Point v_pt = p1.vector_to(pt); - const int64_t l2_seg = int64_t(v_seg.x) * int64_t(v_seg.x) + int64_t(v_seg.y) * int64_t(v_seg.y); - int64_t t_pt = int64_t(v_seg.x) * int64_t(v_pt.x) + int64_t(v_seg.y) * int64_t(v_pt.y); + const Slic3r::Point v_seg = p2 - p1; + const Slic3r::Point v_pt = pt - p1; + const int64_t l2_seg = int64_t(v_seg(0)) * int64_t(v_seg(0)) + int64_t(v_seg(1)) * int64_t(v_seg(1)); + int64_t t_pt = int64_t(v_seg(0)) * int64_t(v_pt(0)) + int64_t(v_seg(1)) * int64_t(v_pt(1)); if (t_pt < 0) { // Closest to p1. - double dabs = sqrt(int64_t(v_pt.x) * int64_t(v_pt.x) + int64_t(v_pt.y) * int64_t(v_pt.y)); + double dabs = sqrt(int64_t(v_pt(0)) * int64_t(v_pt(0)) + int64_t(v_pt(1)) * int64_t(v_pt(1))); if (dabs < d_min) { d_min = dabs; i_min = i; @@ -1789,7 +1789,7 @@ static Points::iterator project_point_to_polygon_and_insert(Polygon &polygon, co } else { // Closest to the segment. assert(t_pt >= 0 && t_pt <= l2_seg); - int64_t d_seg = int64_t(v_seg.y) * int64_t(v_pt.x) - int64_t(v_seg.x) * int64_t(v_pt.y); + int64_t d_seg = int64_t(v_seg(1)) * int64_t(v_pt(0)) - int64_t(v_seg(0)) * int64_t(v_pt(1)); double d = double(d_seg) / sqrt(double(l2_seg)); double dabs = std::abs(d); if (dabs < d_min) { @@ -1798,15 +1798,15 @@ static Points::iterator project_point_to_polygon_and_insert(Polygon &polygon, co // Evaluate the foot point. pt_min = p1; double linv = double(d_seg) / double(l2_seg); - pt_min.x = pt.x - coord_t(floor(double(v_seg.y) * linv + 0.5)); - pt_min.y = pt.y + coord_t(floor(double(v_seg.x) * linv + 0.5)); + pt_min(0) = pt(0) - coord_t(floor(double(v_seg(1)) * linv + 0.5)); + pt_min(1) = pt(1) + coord_t(floor(double(v_seg(0)) * linv + 0.5)); assert(Line(p1, p2).distance_to(pt_min) < scale_(1e-5)); } } } assert(i_min != size_t(-1)); - if (pt_min.distance_to(polygon.points[i_min]) > eps) { + if ((pt_min - polygon.points[i_min]).cast().norm() > eps) { // Insert a new point on the segment i_min, i_min+1. return polygon.points.insert(polygon.points.begin() + (i_min + 1), pt_min); } @@ -1818,8 +1818,8 @@ std::vector polygon_parameter_by_length(const Polygon &polygon) // Parametrize the polygon by its length. std::vector lengths(polygon.points.size()+1, 0.); for (size_t i = 1; i < polygon.points.size(); ++ i) - lengths[i] = lengths[i-1] + float(polygon.points[i].distance_to(polygon.points[i-1])); - lengths.back() = lengths[lengths.size()-2] + float(polygon.points.front().distance_to(polygon.points.back())); + lengths[i] = lengths[i-1] + (polygon.points[i] - polygon.points[i-1]).cast().norm(); + lengths.back() = lengths[lengths.size()-2] + (polygon.points.front() - polygon.points.back()).cast().norm(); return lengths; } @@ -1867,10 +1867,10 @@ std::vector polygon_angles_at_vertices(const Polygon &polygon, const std: const Point &p0 = polygon.points[idx_prev]; const Point &p1 = polygon.points[idx_curr]; const Point &p2 = polygon.points[idx_next]; - const Point v1 = p0.vector_to(p1); - const Point v2 = p1.vector_to(p2); - int64_t dot = int64_t(v1.x)*int64_t(v2.x) + int64_t(v1.y)*int64_t(v2.y); - int64_t cross = int64_t(v1.x)*int64_t(v2.y) - int64_t(v1.y)*int64_t(v2.x); + const Point v1 = p1 - p0; + const Point v2 = p2 - p1; + int64_t dot = int64_t(v1(0))*int64_t(v2(0)) + int64_t(v1(1))*int64_t(v2(1)); + int64_t cross = int64_t(v1(0))*int64_t(v2(1)) - int64_t(v1(1))*int64_t(v2(0)); float angle = float(atan2(double(cross), double(dot))); angles[idx_curr] = angle; } @@ -1894,10 +1894,10 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou { static int iRun = 0; BoundingBox bbox = (*lower_layer_edge_grid)->bbox(); - bbox.min.x -= scale_(5.f); - bbox.min.y -= scale_(5.f); - bbox.max.x += scale_(5.f); - bbox.max.y += scale_(5.f); + bbox.min(0) -= scale_(5.f); + bbox.min(1) -= scale_(5.f); + bbox.max(0) += scale_(5.f); + bbox.max(1) += scale_(5.f); EdgeGrid::save_png(*(*lower_layer_edge_grid), bbox, scale_(0.1f), debug_out_path("GCode_extrude_loop_edge_grid-%d.png", iRun++)); } #endif @@ -1933,7 +1933,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou break; case spRear: last_pos = m_layer->object()->bounding_box().center(); - last_pos.y += coord_t(3. * m_layer->object()->bounding_box().radius()); + last_pos(1) += coord_t(3. * m_layer->object()->bounding_box().radius()); last_pos_weight = 5.f; break; } @@ -2066,7 +2066,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou //FIXME Better parametrize the loop by its length. Polygon polygon = loop.polygon(); Point centroid = polygon.centroid(); - last_pos = Point(polygon.bounding_box().max.x, centroid.y); + last_pos = Point(polygon.bounding_box().max(0), centroid(1)); last_pos.rotate(fmod((float)rand()/16.0, 2.0*PI), centroid); } // Find the closest point, avoid overhangs. @@ -2123,19 +2123,17 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou // create the destination point along the first segment and rotate it // we make sure we don't exceed the segment length because we don't know // the rotation of the second segment so we might cross the object boundary - Line first_segment( - paths.front().polyline.points[0], - paths.front().polyline.points[1] - ); - double distance = std::min( - scale_(EXTRUDER_CONFIG(nozzle_diameter)), - first_segment.length() - ); - Point point = first_segment.point_at(distance); - point.rotate(angle, first_segment.a); - + Vec2d p1 = paths.front().polyline.points.front().cast(); + Vec2d p2 = paths.front().polyline.points[1].cast(); + Vec2d v = p2 - p1; + double nd = scale_(EXTRUDER_CONFIG(nozzle_diameter)); + double l2 = v.squaredNorm(); + // Shift by no more than a nozzle diameter. + //FIXME Hiding the seams will not work nicely for very densely discretized contours! + Point pt = ((nd * nd >= l2) ? p2 : (p1 + v * (nd / sqrt(l2)))).cast(); + pt.rotate(angle, paths.front().polyline.points.front()); // generate the travel move - gcode += m_writer.travel_to_xy(this->point_to_gcode(point), "move inwards before travel"); + gcode += m_writer.travel_to_xy(this->point_to_gcode(pt), "move inwards before travel"); } return gcode; @@ -2305,7 +2303,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, std::string gcode; // go to first point of extrusion path - if (!m_last_pos_defined || !m_last_pos.coincides_with(path.first_point())) { + if (!m_last_pos_defined || m_last_pos != path.first_point()) { gcode += this->travel_to( path.first_point(), path.role(), @@ -2620,24 +2618,21 @@ std::string GCode::set_extruder(unsigned int extruder_id) } // convert a model-space scaled point into G-code coordinates -Pointf GCode::point_to_gcode(const Point &point) const +Vec2d GCode::point_to_gcode(const Point &point) const { - Pointf extruder_offset = EXTRUDER_CONFIG(extruder_offset); - return Pointf( - unscale(point.x) + m_origin.x - extruder_offset.x, - unscale(point.y) + m_origin.y - extruder_offset.y); + Vec2d extruder_offset = EXTRUDER_CONFIG(extruder_offset); + return unscale(point) + m_origin - extruder_offset; } // convert a model-space scaled point into G-code coordinates -Point GCode::gcode_to_point(const Pointf &point) const +Point GCode::gcode_to_point(const Vec2d &point) const { - Pointf extruder_offset = EXTRUDER_CONFIG(extruder_offset); + Vec2d extruder_offset = EXTRUDER_CONFIG(extruder_offset); return Point( - scale_(point.x - m_origin.x + extruder_offset.x), - scale_(point.y - m_origin.y + extruder_offset.y)); + scale_(point(0) - m_origin(0) + extruder_offset(0)), + scale_(point(1) - m_origin(1) + extruder_offset(1))); } - // Goes through by_region std::vector and returns reference to a subvector of entities, that are to be printed // during infill/perimeter wiping, or normally (depends on wiping_entities parameter) // Returns a reference to member to avoid copying. diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp index 4953c39fe..dc8a32135 100644 --- a/xs/src/libslic3r/GCode.hpp +++ b/xs/src/libslic3r/GCode.hpp @@ -125,6 +125,7 @@ private: class GCode { public: GCode() : + m_origin(Vec2d::Zero()), m_enable_loop_clipping(true), m_enable_cooling_markers(false), m_enable_extrusion_role_markers(false), @@ -152,12 +153,12 @@ public: void do_export(Print *print, const char *path, GCodePreviewData *preview_data = nullptr); // Exported for the helper classes (OozePrevention, Wipe) and for the Perl binding for unit tests. - const Pointf& origin() const { return m_origin; } - void set_origin(const Pointf &pointf); - void set_origin(const coordf_t x, const coordf_t y) { this->set_origin(Pointf(x, y)); } + const Vec2d& origin() const { return m_origin; } + void set_origin(const Vec2d &pointf); + void set_origin(const coordf_t x, const coordf_t y) { this->set_origin(Vec2d(x, y)); } const Point& last_pos() const { return m_last_pos; } - Pointf point_to_gcode(const Point &point) const; - Point gcode_to_point(const Pointf &point) const; + Vec2d point_to_gcode(const Point &point) const; + Point gcode_to_point(const Vec2d &point) const; const FullPrintConfig &config() const { return m_config; } const Layer* layer() const { return m_layer; } GCodeWriter& writer() { return m_writer; } @@ -258,7 +259,7 @@ protected: /* Origin of print coordinates expressed in unscaled G-code coordinates. This affects the input arguments supplied to the extrude*() and travel_to() methods. */ - Pointf m_origin; + Vec2d m_origin; FullPrintConfig m_config; GCodeWriter m_writer; PlaceholderParser m_placeholder_parser; diff --git a/xs/src/libslic3r/GCode/Analyzer.cpp b/xs/src/libslic3r/GCode/Analyzer.cpp index b7ecee5a4..51d5b1a06 100644 --- a/xs/src/libslic3r/GCode/Analyzer.cpp +++ b/xs/src/libslic3r/GCode/Analyzer.cpp @@ -14,7 +14,7 @@ static const float MMMIN_TO_MMSEC = 1.0f / 60.0f; static const float INCHES_TO_MM = 25.4f; static const float DEFAULT_FEEDRATE = 0.0f; static const unsigned int DEFAULT_EXTRUDER_ID = 0; -static const Slic3r::Pointf3 DEFAULT_START_POSITION = Slic3r::Pointf3(0.0f, 0.0f, 0.0f); +static const Slic3r::Vec3d DEFAULT_START_POSITION = Slic3r::Vec3d(0.0f, 0.0f, 0.0f); static const float DEFAULT_START_EXTRUSION = 0.0f; namespace Slic3r { @@ -71,7 +71,7 @@ bool GCodeAnalyzer::Metadata::operator != (const GCodeAnalyzer::Metadata& other) return false; } -GCodeAnalyzer::GCodeMove::GCodeMove(GCodeMove::EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, const Pointf3& start_position, const Pointf3& end_position, float delta_extruder) +GCodeAnalyzer::GCodeMove::GCodeMove(GCodeMove::EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, const Vec3d& start_position, const Vec3d& end_position, float delta_extruder) : type(type) , data(extrusion_role, extruder_id, mm3_per_mm, width, height, feedrate) , start_position(start_position) @@ -80,7 +80,7 @@ GCodeAnalyzer::GCodeMove::GCodeMove(GCodeMove::EType type, ExtrusionRole extrusi { } -GCodeAnalyzer::GCodeMove::GCodeMove(GCodeMove::EType type, const GCodeAnalyzer::Metadata& data, const Pointf3& start_position, const Pointf3& end_position, float delta_extruder) +GCodeAnalyzer::GCodeMove::GCodeMove(GCodeMove::EType type, const GCodeAnalyzer::Metadata& data, const Vec3d& start_position, const Vec3d& end_position, float delta_extruder) : type(type) , data(data) , start_position(start_position) @@ -587,12 +587,12 @@ void GCodeAnalyzer::_reset_axes_position() ::memset((void*)m_state.position, 0, Num_Axis * sizeof(float)); } -void GCodeAnalyzer::_set_start_position(const Pointf3& position) +void GCodeAnalyzer::_set_start_position(const Vec3d& position) { m_state.start_position = position; } -const Pointf3& GCodeAnalyzer::_get_start_position() const +const Vec3d& GCodeAnalyzer::_get_start_position() const { return m_state.start_position; } @@ -612,9 +612,9 @@ float GCodeAnalyzer::_get_delta_extrusion() const return _get_axis_position(E) - m_state.start_extrusion; } -Pointf3 GCodeAnalyzer::_get_end_position() const +Vec3d GCodeAnalyzer::_get_end_position() const { - return Pointf3(m_state.position[X], m_state.position[Y], m_state.position[Z]); + return Vec3d(m_state.position[X], m_state.position[Y], m_state.position[Z]); } void GCodeAnalyzer::_store_move(GCodeAnalyzer::GCodeMove::EType type) @@ -673,7 +673,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ Metadata data; float z = FLT_MAX; Polyline polyline; - Pointf3 position(FLT_MAX, FLT_MAX, FLT_MAX); + Vec3d position(FLT_MAX, FLT_MAX, FLT_MAX); float volumetric_rate = FLT_MAX; GCodePreviewData::Range height_range; GCodePreviewData::Range width_range; @@ -683,7 +683,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ // constructs the polylines while traversing the moves for (const GCodeMove& move : extrude_moves->second) { - if ((data != move.data) || (z != move.start_position.z) || (position != move.start_position) || (volumetric_rate != move.data.feedrate * (float)move.data.mm3_per_mm)) + if ((data != move.data) || (z != move.start_position.z()) || (position != move.start_position) || (volumetric_rate != move.data.feedrate * (float)move.data.mm3_per_mm)) { // store current polyline polyline.remove_duplicate_points(); @@ -693,12 +693,12 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ polyline = Polyline(); // add both vertices of the move - polyline.append(Point(scale_(move.start_position.x), scale_(move.start_position.y))); - polyline.append(Point(scale_(move.end_position.x), scale_(move.end_position.y))); + polyline.append(Point(scale_(move.start_position.x()), scale_(move.start_position.y()))); + polyline.append(Point(scale_(move.end_position.x()), scale_(move.end_position.y()))); // update current values data = move.data; - z = move.start_position.z; + z = move.start_position.z(); volumetric_rate = move.data.feedrate * (float)move.data.mm3_per_mm; height_range.update_from(move.data.height); width_range.update_from(move.data.width); @@ -707,7 +707,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ } else // append end vertex of the move to current polyline - polyline.append(Point(scale_(move.end_position.x), scale_(move.end_position.y))); + polyline.append(Point(scale_(move.end_position.x()), scale_(move.end_position.y()))); // update current values position = move.end_position; @@ -742,7 +742,7 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data) return; Polyline3 polyline; - Pointf3 position(FLT_MAX, FLT_MAX, FLT_MAX); + Vec3d position(FLT_MAX, FLT_MAX, FLT_MAX); GCodePreviewData::Travel::EType type = GCodePreviewData::Travel::Num_Types; GCodePreviewData::Travel::Polyline::EDirection direction = GCodePreviewData::Travel::Polyline::Num_Directions; float feedrate = FLT_MAX; @@ -756,7 +756,7 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data) for (const GCodeMove& move : travel_moves->second) { GCodePreviewData::Travel::EType move_type = (move.delta_extruder < 0.0f) ? GCodePreviewData::Travel::Retract : ((move.delta_extruder > 0.0f) ? GCodePreviewData::Travel::Extrude : GCodePreviewData::Travel::Move); - GCodePreviewData::Travel::Polyline::EDirection move_direction = ((move.start_position.x != move.end_position.x) || (move.start_position.y != move.end_position.y)) ? GCodePreviewData::Travel::Polyline::Generic : GCodePreviewData::Travel::Polyline::Vertical; + GCodePreviewData::Travel::Polyline::EDirection move_direction = ((move.start_position.x() != move.end_position.x()) || (move.start_position.y() != move.end_position.y())) ? GCodePreviewData::Travel::Polyline::Generic : GCodePreviewData::Travel::Polyline::Vertical; if ((type != move_type) || (direction != move_direction) || (feedrate != move.data.feedrate) || (position != move.start_position) || (extruder_id != move.data.extruder_id)) { @@ -768,12 +768,12 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data) polyline = Polyline3(); // add both vertices of the move - polyline.append(Point3(scale_(move.start_position.x), scale_(move.start_position.y), scale_(move.start_position.z))); - polyline.append(Point3(scale_(move.end_position.x), scale_(move.end_position.y), scale_(move.end_position.z))); + polyline.append(Vec3crd(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z()))); + polyline.append(Vec3crd(scale_(move.end_position.x()), scale_(move.end_position.y()), scale_(move.end_position.z()))); } else // append end vertex of the move to current polyline - polyline.append(Point3(scale_(move.end_position.x), scale_(move.end_position.y), scale_(move.end_position.z))); + polyline.append(Vec3crd(scale_(move.end_position.x()), scale_(move.end_position.y()), scale_(move.end_position.z()))); // update current values position = move.end_position; @@ -804,7 +804,7 @@ void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_da for (const GCodeMove& move : retraction_moves->second) { // store position - Point3 position(scale_(move.start_position.x), scale_(move.start_position.y), scale_(move.start_position.z)); + Vec3crd position(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z())); preview_data.retraction.positions.emplace_back(position, move.data.width, move.data.height); } } @@ -818,7 +818,7 @@ void GCodeAnalyzer::_calc_gcode_preview_unretractions(GCodePreviewData& preview_ for (const GCodeMove& move : unretraction_moves->second) { // store position - Point3 position(scale_(move.start_position.x), scale_(move.start_position.y), scale_(move.start_position.z)); + Vec3crd position(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z())); preview_data.unretraction.positions.emplace_back(position, move.data.width, move.data.height); } } diff --git a/xs/src/libslic3r/GCode/Analyzer.hpp b/xs/src/libslic3r/GCode/Analyzer.hpp index 03dbab338..27a49b869 100644 --- a/xs/src/libslic3r/GCode/Analyzer.hpp +++ b/xs/src/libslic3r/GCode/Analyzer.hpp @@ -75,12 +75,12 @@ public: EType type; Metadata data; - Pointf3 start_position; - Pointf3 end_position; + Vec3d start_position; + Vec3d end_position; float delta_extruder; - GCodeMove(EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, const Pointf3& start_position, const Pointf3& end_position, float delta_extruder); - GCodeMove(EType type, const Metadata& data, const Pointf3& start_position, const Pointf3& end_position, float delta_extruder); + GCodeMove(EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, const Vec3d& start_position, const Vec3d& end_position, float delta_extruder); + GCodeMove(EType type, const Metadata& data, const Vec3d& start_position, const Vec3d& end_position, float delta_extruder); }; typedef std::vector GCodeMovesList; @@ -93,7 +93,7 @@ private: EPositioningType global_positioning_type; EPositioningType e_local_positioning_type; Metadata data; - Pointf3 start_position; + Vec3d start_position = Vec3d::Zero(); float start_extrusion; float position[Num_Axis]; }; @@ -206,15 +206,15 @@ private: // Sets axes position to zero void _reset_axes_position(); - void _set_start_position(const Pointf3& position); - const Pointf3& _get_start_position() const; + void _set_start_position(const Vec3d& position); + const Vec3d& _get_start_position() const; void _set_start_extrusion(float extrusion); float _get_start_extrusion() const; float _get_delta_extrusion() const; // Returns current xyz position (from m_state.position[]) - Pointf3 _get_end_position() const; + Vec3d _get_end_position() const; // Adds a new move with the given data void _store_move(GCodeMove::EType type); diff --git a/xs/src/libslic3r/GCode/CoolingBuffer.cpp b/xs/src/libslic3r/GCode/CoolingBuffer.cpp index a15247693..40ccc7b09 100644 --- a/xs/src/libslic3r/GCode/CoolingBuffer.cpp +++ b/xs/src/libslic3r/GCode/CoolingBuffer.cpp @@ -23,10 +23,10 @@ CoolingBuffer::CoolingBuffer(GCode &gcodegen) : m_gcodegen(gcodegen), m_current_ void CoolingBuffer::reset() { m_current_pos.assign(5, 0.f); - Pointf3 pos = m_gcodegen.writer().get_position(); - m_current_pos[0] = float(pos.x); - m_current_pos[1] = float(pos.y); - m_current_pos[2] = float(pos.z); + Vec3d pos = m_gcodegen.writer().get_position(); + m_current_pos[0] = float(pos(0)); + m_current_pos[1] = float(pos(1)); + m_current_pos[2] = float(pos(2)); m_current_pos[4] = float(m_gcodegen.config().travel_speed.value); } diff --git a/xs/src/libslic3r/GCode/PreviewData.cpp b/xs/src/libslic3r/GCode/PreviewData.cpp index 3833bca06..9cf9716e0 100644 --- a/xs/src/libslic3r/GCode/PreviewData.cpp +++ b/xs/src/libslic3r/GCode/PreviewData.cpp @@ -226,7 +226,7 @@ void GCodePreviewData::Travel::set_default() const GCodePreviewData::Color GCodePreviewData::Retraction::Default_Color = GCodePreviewData::Color(1.0f, 1.0f, 1.0f, 1.0f); -GCodePreviewData::Retraction::Position::Position(const Point3& position, float width, float height) +GCodePreviewData::Retraction::Position::Position(const Vec3crd& position, float width, float height) : position(position) , width(width) , height(height) diff --git a/xs/src/libslic3r/GCode/PreviewData.hpp b/xs/src/libslic3r/GCode/PreviewData.hpp index ea8ca6d58..ab74993f5 100644 --- a/xs/src/libslic3r/GCode/PreviewData.hpp +++ b/xs/src/libslic3r/GCode/PreviewData.hpp @@ -151,11 +151,11 @@ public: struct Position { - Point3 position; + Vec3crd position; float width; float height; - Position(const Point3& position, float width, float height); + Position(const Vec3crd& position, float width, float height); }; typedef std::vector PositionsList; diff --git a/xs/src/libslic3r/GCode/PrintExtents.cpp b/xs/src/libslic3r/GCode/PrintExtents.cpp index 37b79f343..2ed607769 100644 --- a/xs/src/libslic3r/GCode/PrintExtents.cpp +++ b/xs/src/libslic3r/GCode/PrintExtents.cpp @@ -19,10 +19,10 @@ static inline BoundingBox extrusion_polyline_extents(const Polyline &polyline, c if (! polyline.points.empty()) bbox.merge(polyline.points.front()); for (const Point &pt : polyline.points) { - bbox.min.x = std::min(bbox.min.x, pt.x - radius); - bbox.min.y = std::min(bbox.min.y, pt.y - radius); - bbox.max.x = std::max(bbox.max.x, pt.x + radius); - bbox.max.y = std::max(bbox.max.y, pt.y + radius); + bbox.min(0) = std::min(bbox.min(0), pt(0) - radius); + bbox.min(1) = std::min(bbox.min(1), pt(1) - radius); + bbox.max(0) = std::max(bbox.max(0), pt(0) + radius); + bbox.max(1) = std::max(bbox.max(1), pt(1) + radius); } return bbox; } @@ -32,8 +32,8 @@ static inline BoundingBoxf extrusionentity_extents(const ExtrusionPath &extrusio BoundingBox bbox = extrusion_polyline_extents(extrusion_path.polyline, scale_(0.5 * extrusion_path.width)); BoundingBoxf bboxf; if (! empty(bbox)) { - bboxf.min = Pointf::new_unscale(bbox.min); - bboxf.max = Pointf::new_unscale(bbox.max); + bboxf.min = unscale(bbox.min); + bboxf.max = unscale(bbox.max); bboxf.defined = true; } return bboxf; @@ -46,8 +46,8 @@ static inline BoundingBoxf extrusionentity_extents(const ExtrusionLoop &extrusio bbox.merge(extrusion_polyline_extents(extrusion_path.polyline, scale_(0.5 * extrusion_path.width))); BoundingBoxf bboxf; if (! empty(bbox)) { - bboxf.min = Pointf::new_unscale(bbox.min); - bboxf.max = Pointf::new_unscale(bbox.max); + bboxf.min = unscale(bbox.min); + bboxf.max = unscale(bbox.max); bboxf.defined = true; } return bboxf; @@ -60,8 +60,8 @@ static inline BoundingBoxf extrusionentity_extents(const ExtrusionMultiPath &ext bbox.merge(extrusion_polyline_extents(extrusion_path.polyline, scale_(0.5 * extrusion_path.width))); BoundingBoxf bboxf; if (! empty(bbox)) { - bboxf.min = Pointf::new_unscale(bbox.min); - bboxf.max = Pointf::new_unscale(bbox.max); + bboxf.min = unscale(bbox.min); + bboxf.max = unscale(bbox.max); bboxf.defined = true; } return bboxf; @@ -123,7 +123,7 @@ BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object bbox_this.merge(extrusionentity_extents(extrusion_entity)); for (const Point &offset : print_object._shifted_copies) { BoundingBoxf bbox_translated(bbox_this); - bbox_translated.translate(Pointf::new_unscale(offset)); + bbox_translated.translate(unscale(offset)); bbox.merge(bbox_translated); } } @@ -136,8 +136,9 @@ BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coordf_ { // Wipe tower extrusions are saved as if the tower was at the origin with no rotation // We need to get position and angle of the wipe tower to transform them to actual position. - Pointf wipe_tower_pos(print.config.wipe_tower_x.value, print.config.wipe_tower_y.value); - float wipe_tower_angle = print.config.wipe_tower_rotation_angle.value; + Transform2d trafo = + Eigen::Translation2d(print.config.wipe_tower_x.value, print.config.wipe_tower_y.value) * + Eigen::Rotation2Dd(print.config.wipe_tower_rotation_angle.value); BoundingBoxf bbox; for (const std::vector &tool_changes : print.m_wipe_tower_tool_changes) { @@ -147,19 +148,11 @@ BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coordf_ for (size_t i = 1; i < tcr.extrusions.size(); ++ i) { const WipeTower::Extrusion &e = tcr.extrusions[i]; if (e.width > 0) { - Pointf p1((&e - 1)->pos.x, (&e - 1)->pos.y); - Pointf p2(e.pos.x, e.pos.y); - p1.rotate(wipe_tower_angle); - p1.translate(wipe_tower_pos); - p2.rotate(wipe_tower_angle); - p2.translate(wipe_tower_pos); - - bbox.merge(p1); - coordf_t radius = 0.5 * e.width; - bbox.min.x = std::min(bbox.min.x, std::min(p1.x, p2.x) - radius); - bbox.min.y = std::min(bbox.min.y, std::min(p1.y, p2.y) - radius); - bbox.max.x = std::max(bbox.max.x, std::max(p1.x, p2.x) + radius); - bbox.max.y = std::max(bbox.max.y, std::max(p1.y, p2.y) + radius); + Vec2d delta = 0.5 * Vec2d(e.width, e.width); + Vec2d p1 = trafo * Vec2d((&e - 1)->pos.x, (&e - 1)->pos.y); + Vec2d p2 = trafo * Vec2d(e.pos.x, e.pos.y); + bbox.merge(p1.cwiseMin(p2) - delta); + bbox.merge(p1.cwiseMax(p2) + delta); } } } @@ -176,14 +169,14 @@ BoundingBoxf get_wipe_tower_priming_extrusions_extents(const Print &print) for (size_t i = 1; i < tcr.extrusions.size(); ++ i) { const WipeTower::Extrusion &e = tcr.extrusions[i]; if (e.width > 0) { - Pointf p1((&e - 1)->pos.x, (&e - 1)->pos.y); - Pointf p2(e.pos.x, e.pos.y); + Vec2d p1((&e - 1)->pos.x, (&e - 1)->pos.y); + Vec2d p2(e.pos.x, e.pos.y); bbox.merge(p1); coordf_t radius = 0.5 * e.width; - bbox.min.x = std::min(bbox.min.x, std::min(p1.x, p2.x) - radius); - bbox.min.y = std::min(bbox.min.y, std::min(p1.y, p2.y) - radius); - bbox.max.x = std::max(bbox.max.x, std::max(p1.x, p2.x) + radius); - bbox.max.y = std::max(bbox.max.y, std::max(p1.y, p2.y) + radius); + bbox.min(0) = std::min(bbox.min(0), std::min(p1(0), p2(0)) - radius); + bbox.min(1) = std::min(bbox.min(1), std::min(p1(1), p2(1)) - radius); + bbox.max(0) = std::max(bbox.max(0), std::max(p1(0), p2(0)) + radius); + bbox.max(1) = std::max(bbox.max(1), std::max(p1(1), p2(1)) + radius); } } } diff --git a/xs/src/libslic3r/GCode/WipeTower.hpp b/xs/src/libslic3r/GCode/WipeTower.hpp index 9bf350328..c35a0feb3 100644 --- a/xs/src/libslic3r/GCode/WipeTower.hpp +++ b/xs/src/libslic3r/GCode/WipeTower.hpp @@ -30,10 +30,9 @@ public: xy out(0,0); float temp_x = x - width / 2.f; float temp_y = y - depth / 2.f; - angle *= M_PI/180.; + angle *= float(M_PI/180.); out.x += temp_x * cos(angle) - temp_y * sin(angle) + width / 2.f; out.y += temp_x * sin(angle) + temp_y * cos(angle) + depth / 2.f; - return out; } diff --git a/xs/src/libslic3r/GCodeWriter.cpp b/xs/src/libslic3r/GCodeWriter.cpp index 34e6b7ec3..6ef17f4f4 100644 --- a/xs/src/libslic3r/GCodeWriter.cpp +++ b/xs/src/libslic3r/GCodeWriter.cpp @@ -276,30 +276,30 @@ std::string GCodeWriter::set_speed(double F, const std::string &comment, const s return gcode.str(); } -std::string GCodeWriter::travel_to_xy(const Pointf &point, const std::string &comment) +std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &comment) { - m_pos.x = point.x; - m_pos.y = point.y; + m_pos(0) = point(0); + m_pos(1) = point(1); std::ostringstream gcode; - gcode << "G1 X" << XYZF_NUM(point.x) - << " Y" << XYZF_NUM(point.y) + gcode << "G1 X" << XYZF_NUM(point(0)) + << " Y" << XYZF_NUM(point(1)) << " F" << XYZF_NUM(this->config.travel_speed.value * 60.0); COMMENT(comment); gcode << "\n"; return gcode.str(); } -std::string GCodeWriter::travel_to_xyz(const Pointf3 &point, const std::string &comment) +std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &comment) { /* If target Z is lower than current Z but higher than nominal Z we don't perform the Z move but we only move in the XY plane and adjust the nominal Z by reducing the lift amount that will be used for unlift. */ - if (!this->will_move_z(point.z)) { - double nominal_z = m_pos.z - m_lifted; - m_lifted = m_lifted - (point.z - nominal_z); - return this->travel_to_xy(point); + if (!this->will_move_z(point(2))) { + double nominal_z = m_pos(2) - m_lifted; + m_lifted = m_lifted - (point(2) - nominal_z); + return this->travel_to_xy(to_2d(point)); } /* In all the other cases, we perform an actual XYZ move and cancel @@ -308,9 +308,9 @@ std::string GCodeWriter::travel_to_xyz(const Pointf3 &point, const std::string & m_pos = point; std::ostringstream gcode; - gcode << "G1 X" << XYZF_NUM(point.x) - << " Y" << XYZF_NUM(point.y) - << " Z" << XYZF_NUM(point.z) + gcode << "G1 X" << XYZF_NUM(point(0)) + << " Y" << XYZF_NUM(point(1)) + << " Z" << XYZF_NUM(point(2)) << " F" << XYZF_NUM(this->config.travel_speed.value * 60.0); COMMENT(comment); gcode << "\n"; @@ -323,7 +323,7 @@ std::string GCodeWriter::travel_to_z(double z, const std::string &comment) we don't perform the move but we only adjust the nominal Z by reducing the lift amount that will be used for unlift. */ if (!this->will_move_z(z)) { - double nominal_z = m_pos.z - m_lifted; + double nominal_z = m_pos(2) - m_lifted; m_lifted = m_lifted - (z - nominal_z); return ""; } @@ -336,7 +336,7 @@ std::string GCodeWriter::travel_to_z(double z, const std::string &comment) std::string GCodeWriter::_travel_to_z(double z, const std::string &comment) { - m_pos.z = z; + m_pos(2) = z; std::ostringstream gcode; gcode << "G1 Z" << XYZF_NUM(z) @@ -351,38 +351,38 @@ bool GCodeWriter::will_move_z(double z) const /* If target Z is lower than current Z but higher than nominal Z we don't perform an actual Z move. */ if (m_lifted > 0) { - double nominal_z = m_pos.z - m_lifted; - if (z >= nominal_z && z <= m_pos.z) + double nominal_z = m_pos(2) - m_lifted; + if (z >= nominal_z && z <= m_pos(2)) return false; } return true; } -std::string GCodeWriter::extrude_to_xy(const Pointf &point, double dE, const std::string &comment) +std::string GCodeWriter::extrude_to_xy(const Vec2d &point, double dE, const std::string &comment) { - m_pos.x = point.x; - m_pos.y = point.y; + m_pos(0) = point(0); + m_pos(1) = point(1); m_extruder->extrude(dE); std::ostringstream gcode; - gcode << "G1 X" << XYZF_NUM(point.x) - << " Y" << XYZF_NUM(point.y) + gcode << "G1 X" << XYZF_NUM(point(0)) + << " Y" << XYZF_NUM(point(1)) << " " << m_extrusion_axis << E_NUM(m_extruder->E()); COMMENT(comment); gcode << "\n"; return gcode.str(); } -std::string GCodeWriter::extrude_to_xyz(const Pointf3 &point, double dE, const std::string &comment) +std::string GCodeWriter::extrude_to_xyz(const Vec3d &point, double dE, const std::string &comment) { m_pos = point; m_lifted = 0; m_extruder->extrude(dE); std::ostringstream gcode; - gcode << "G1 X" << XYZF_NUM(point.x) - << " Y" << XYZF_NUM(point.y) - << " Z" << XYZF_NUM(point.z) + gcode << "G1 X" << XYZF_NUM(point(0)) + << " Y" << XYZF_NUM(point(1)) + << " Z" << XYZF_NUM(point(2)) << " " << m_extrusion_axis << E_NUM(m_extruder->E()); COMMENT(comment); gcode << "\n"; @@ -486,12 +486,12 @@ std::string GCodeWriter::lift() { double above = this->config.retract_lift_above.get_at(m_extruder->id()); double below = this->config.retract_lift_below.get_at(m_extruder->id()); - if (m_pos.z >= above && (below == 0 || m_pos.z <= below)) + if (m_pos(2) >= above && (below == 0 || m_pos(2) <= below)) target_lift = this->config.retract_lift.get_at(m_extruder->id()); } if (m_lifted == 0 && target_lift > 0) { m_lifted = target_lift; - return this->_travel_to_z(m_pos.z + target_lift, "lift Z"); + return this->_travel_to_z(m_pos(2) + target_lift, "lift Z"); } return ""; } @@ -500,7 +500,7 @@ std::string GCodeWriter::unlift() { std::string gcode; if (m_lifted > 0) { - gcode += this->_travel_to_z(m_pos.z - m_lifted, "restore layer Z"); + gcode += this->_travel_to_z(m_pos(2) - m_lifted, "restore layer Z"); m_lifted = 0; } return gcode; diff --git a/xs/src/libslic3r/GCodeWriter.hpp b/xs/src/libslic3r/GCodeWriter.hpp index f706b8768..664b0e3a1 100644 --- a/xs/src/libslic3r/GCodeWriter.hpp +++ b/xs/src/libslic3r/GCodeWriter.hpp @@ -55,18 +55,18 @@ public: std::string toolchange_prefix() const; std::string toolchange(unsigned int extruder_id); std::string set_speed(double F, const std::string &comment = std::string(), const std::string &cooling_marker = std::string()) const; - std::string travel_to_xy(const Pointf &point, const std::string &comment = std::string()); - std::string travel_to_xyz(const Pointf3 &point, const std::string &comment = std::string()); + std::string travel_to_xy(const Vec2d &point, const std::string &comment = std::string()); + std::string travel_to_xyz(const Vec3d &point, const std::string &comment = std::string()); std::string travel_to_z(double z, const std::string &comment = std::string()); bool will_move_z(double z) const; - std::string extrude_to_xy(const Pointf &point, double dE, const std::string &comment = std::string()); - std::string extrude_to_xyz(const Pointf3 &point, double dE, const std::string &comment = std::string()); + std::string extrude_to_xy(const Vec2d &point, double dE, const std::string &comment = std::string()); + std::string extrude_to_xyz(const Vec3d &point, double dE, const std::string &comment = std::string()); std::string retract(bool before_wipe = false); std::string retract_for_toolchange(bool before_wipe = false); std::string unretract(); std::string lift(); std::string unlift(); - Pointf3 get_position() const { return m_pos; } + Vec3d get_position() const { return m_pos; } private: std::vector m_extruders; @@ -81,7 +81,7 @@ private: unsigned int m_last_bed_temperature; bool m_last_bed_temperature_reached; double m_lifted; - Pointf3 m_pos; + Vec3d m_pos = Vec3d::Zero(); std::string _travel_to_z(double z, const std::string &comment); std::string _retract(double length, double restart_extra, const std::string &comment); diff --git a/xs/src/libslic3r/Geometry.cpp b/xs/src/libslic3r/Geometry.cpp index 39b626ee3..c978d46b6 100644 --- a/xs/src/libslic3r/Geometry.cpp +++ b/xs/src/libslic3r/Geometry.cpp @@ -198,7 +198,7 @@ namespace Slic3r { namespace Geometry { static bool sort_points (Point a, Point b) { - return (a.x < b.x) || (a.x == b.x && a.y < b.y); + return (a(0) < b(0)) || (a(0) == b(0) && a(1) < b(1)); } /* This implementation is based on Andrew's monotone chain 2D convex hull algorithm */ @@ -229,7 +229,7 @@ convex_hull(Points points) hull.points.resize(k); - assert( hull.points.front().coincides_with(hull.points.back()) ); + assert( hull.points.front() == hull.points.back() ); hull.points.pop_back(); } @@ -345,54 +345,54 @@ linint(double value, double oldmin, double oldmax, double newmin, double newmax) // If the points have the same weight, sort them lexicographically by their positions. struct ArrangeItem { ArrangeItem() {} - Pointf pos; + Vec2d pos; coordf_t weight; bool operator<(const ArrangeItem &other) const { return weight < other.weight || - ((weight == other.weight) && (pos.y < other.pos.y || (pos.y == other.pos.y && pos.x < other.pos.x))); + ((weight == other.weight) && (pos(1) < other.pos(1) || (pos(1) == other.pos(1) && pos(0) < other.pos(0)))); } }; -Pointfs arrange(size_t num_parts, const Pointf &part_size, coordf_t gap, const BoundingBoxf* bed_bounding_box) +Pointfs arrange(size_t num_parts, const Vec2d &part_size, coordf_t gap, const BoundingBoxf* bed_bounding_box) { // Use actual part size (the largest) plus separation distance (half on each side) in spacing algorithm. - const Pointf cell_size(part_size.x + gap, part_size.y + gap); + const Vec2d cell_size(part_size(0) + gap, part_size(1) + gap); const BoundingBoxf bed_bbox = (bed_bounding_box != NULL && bed_bounding_box->defined) ? *bed_bounding_box : // Bogus bed size, large enough not to trigger the unsufficient bed size error. BoundingBoxf( - Pointf(0, 0), - Pointf(cell_size.x * num_parts, cell_size.y * num_parts)); + Vec2d(0, 0), + Vec2d(cell_size(0) * num_parts, cell_size(1) * num_parts)); // This is how many cells we have available into which to put parts. - size_t cellw = size_t(floor((bed_bbox.size().x + gap) / cell_size.x)); - size_t cellh = size_t(floor((bed_bbox.size().y + gap) / cell_size.y)); + size_t cellw = size_t(floor((bed_bbox.size()(0) + gap) / cell_size(0))); + size_t cellh = size_t(floor((bed_bbox.size()(1) + gap) / cell_size(1))); if (num_parts > cellw * cellh) CONFESS(PRINTF_ZU " parts won't fit in your print area!\n", num_parts); // Get a bounding box of cellw x cellh cells, centered at the center of the bed. - Pointf cells_size(cellw * cell_size.x - gap, cellh * cell_size.y - gap); - Pointf cells_offset(bed_bbox.center() - 0.5 * cells_size); + Vec2d cells_size(cellw * cell_size(0) - gap, cellh * cell_size(1) - gap); + Vec2d cells_offset(bed_bbox.center() - 0.5 * cells_size); BoundingBoxf cells_bb(cells_offset, cells_size + cells_offset); // List of cells, sorted by distance from center. std::vector cellsorder(cellw * cellh, ArrangeItem()); for (size_t j = 0; j < cellh; ++ j) { // Center of the jth row on the bed. - coordf_t cy = linint(j + 0.5, 0., double(cellh), cells_bb.min.y, cells_bb.max.y); + coordf_t cy = linint(j + 0.5, 0., double(cellh), cells_bb.min(1), cells_bb.max(1)); // Offset from the bed center. - coordf_t yd = cells_bb.center().y - cy; + coordf_t yd = cells_bb.center()(1) - cy; for (size_t i = 0; i < cellw; ++ i) { // Center of the ith column on the bed. - coordf_t cx = linint(i + 0.5, 0., double(cellw), cells_bb.min.x, cells_bb.max.x); + coordf_t cx = linint(i + 0.5, 0., double(cellw), cells_bb.min(0), cells_bb.max(0)); // Offset from the bed center. - coordf_t xd = cells_bb.center().x - cx; + coordf_t xd = cells_bb.center()(0) - cx; // Cell with a distance from the bed center. ArrangeItem &ci = cellsorder[j * cellw + i]; // Cell center - ci.pos.x = cx; - ci.pos.y = cy; + ci.pos(0) = cx; + ci.pos(1) = cy; // Square distance of the cell center to the bed center. ci.weight = xd * xd + yd * yd; } @@ -405,61 +405,61 @@ Pointfs arrange(size_t num_parts, const Pointf &part_size, coordf_t gap, const B Pointfs positions; positions.reserve(num_parts); for (std::vector::const_iterator it = cellsorder.begin(); it != cellsorder.end(); ++ it) - positions.push_back(Pointf(it->pos.x - 0.5 * part_size.x, it->pos.y - 0.5 * part_size.y)); + positions.push_back(Vec2d(it->pos(0) - 0.5 * part_size(0), it->pos(1) - 0.5 * part_size(1))); return positions; } #else class ArrangeItem { - public: - Pointf pos; +public: + Vec2d pos = Vec2d::Zero(); size_t index_x, index_y; coordf_t dist; }; class ArrangeItemIndex { - public: +public: coordf_t index; ArrangeItem item; ArrangeItemIndex(coordf_t _index, ArrangeItem _item) : index(_index), item(_item) {}; }; bool -arrange(size_t total_parts, const Pointf &part_size, coordf_t dist, const BoundingBoxf* bb, Pointfs &positions) +arrange(size_t total_parts, const Vec2d &part_size, coordf_t dist, const BoundingBoxf* bb, Pointfs &positions) { positions.clear(); - Pointf part = part_size; + Vec2d part = part_size; // use actual part size (the largest) plus separation distance (half on each side) in spacing algorithm - part.x += dist; - part.y += dist; + part(0) += dist; + part(1) += dist; - Pointf area; + Vec2d area(Vec2d::Zero()); if (bb != NULL && bb->defined) { area = bb->size(); } else { // bogus area size, large enough not to trigger the error below - area.x = part.x * total_parts; - area.y = part.y * total_parts; + area(0) = part(0) * total_parts; + area(1) = part(1) * total_parts; } // this is how many cells we have available into which to put parts - size_t cellw = floor((area.x + dist) / part.x); - size_t cellh = floor((area.y + dist) / part.y); + size_t cellw = floor((area(0) + dist) / part(0)); + size_t cellh = floor((area(1) + dist) / part(1)); if (total_parts > (cellw * cellh)) return false; // total space used by cells - Pointf cells(cellw * part.x, cellh * part.y); + Vec2d cells(cellw * part(0), cellh * part(1)); // bounding box of total space used by cells BoundingBoxf cells_bb; - cells_bb.merge(Pointf(0,0)); // min + cells_bb.merge(Vec2d(0,0)); // min cells_bb.merge(cells); // max // center bounding box to area cells_bb.translate( - (area.x - cells.x) / 2, - (area.y - cells.y) / 2 + (area(0) - cells(0)) / 2, + (area(1) - cells(1)) / 2 ); // list of cells, sorted by distance from center @@ -468,15 +468,15 @@ arrange(size_t total_parts, const Pointf &part_size, coordf_t dist, const Boundi // work out distance for all cells, sort into list for (size_t i = 0; i <= cellw-1; ++i) { for (size_t j = 0; j <= cellh-1; ++j) { - coordf_t cx = linint(i + 0.5, 0, cellw, cells_bb.min.x, cells_bb.max.x); - coordf_t cy = linint(j + 0.5, 0, cellh, cells_bb.min.y, cells_bb.max.y); + coordf_t cx = linint(i + 0.5, 0, cellw, cells_bb.min(0), cells_bb.max(0)); + coordf_t cy = linint(j + 0.5, 0, cellh, cells_bb.min(1), cells_bb.max(1)); - coordf_t xd = fabs((area.x / 2) - cx); - coordf_t yd = fabs((area.y / 2) - cy); + coordf_t xd = fabs((area(0) / 2) - cx); + coordf_t yd = fabs((area(1) / 2) - cy); ArrangeItem c; - c.pos.x = cx; - c.pos.y = cy; + c.pos(0) = cx; + c.pos(1) = cy; c.index_x = i; c.index_y = j; c.dist = xd * xd + yd * yd - fabs((cellw / 2) - (i + 0.5)); @@ -533,13 +533,13 @@ arrange(size_t total_parts, const Pointf &part_size, coordf_t dist, const Boundi coordf_t cx = c.item.index_x - lx; coordf_t cy = c.item.index_y - ty; - positions.push_back(Pointf(cx * part.x, cy * part.y)); + positions.push_back(Vec2d(cx * part(0), cy * part(1))); } if (bb != NULL && bb->defined) { for (Pointfs::iterator p = positions.begin(); p != positions.end(); ++p) { - p->x += bb->min.x; - p->y += bb->min.y; + p->x() += bb->min(0); + p->y() += bb->min(1); } } @@ -608,15 +608,15 @@ namespace Voronoi { namespace Internal { if (cell1.contains_point() && cell2.contains_point()) { point_type p1 = retrieve_point(segments, cell1); point_type p2 = retrieve_point(segments, cell2); - origin.x((p1.x() + p2.x()) * 0.5); - origin.y((p1.y() + p2.y()) * 0.5); - direction.x(p1.y() - p2.y()); - direction.y(p2.x() - p1.x()); + origin.x((p1(0) + p2(0)) * 0.5); + origin.y((p1(1) + p2(1)) * 0.5); + direction.x(p1(1) - p2(1)); + direction.y(p2(0) - p1(0)); } else { origin = cell1.contains_segment() ? retrieve_point(segments, cell2) : retrieve_point(segments, cell1); segment_type segment = cell1.contains_segment() ? segments[cell1.source_index()] : segments[cell2.source_index()]; - coordinate_type dx = high(segment).x() - low(segment).x(); - coordinate_type dy = high(segment).y() - low(segment).y(); + coordinate_type dx = high(segment)(0) - low(segment)(0); + coordinate_type dy = high(segment)(1) - low(segment)(1); if ((low(segment) == origin) ^ cell1.contains_point()) { direction.x(dy); direction.y(-dx); @@ -625,19 +625,19 @@ namespace Voronoi { namespace Internal { direction.y(dx); } } - coordinate_type koef = bbox_max_size / (std::max)(fabs(direction.x()), fabs(direction.y())); + coordinate_type koef = bbox_max_size / (std::max)(fabs(direction(0)), fabs(direction(1))); if (edge.vertex0() == NULL) { clipped_edge->push_back(point_type( - origin.x() - direction.x() * koef, - origin.y() - direction.y() * koef)); + origin(0) - direction(0) * koef, + origin(1) - direction(1) * koef)); } else { clipped_edge->push_back( point_type(edge.vertex0()->x(), edge.vertex0()->y())); } if (edge.vertex1() == NULL) { clipped_edge->push_back(point_type( - origin.x() + direction.x() * koef, - origin.y() + direction.y() * koef)); + origin(0) + direction(0) * koef, + origin(1) + direction(1) * koef)); } else { clipped_edge->push_back( point_type(edge.vertex1()->x(), edge.vertex1()->y())); @@ -676,10 +676,10 @@ static inline void dump_voronoi_to_svg(const Lines &lines, /* const */ voronoi_d const bool primaryEdgesOnly = false; BoundingBox bbox = BoundingBox(lines); - bbox.min.x -= coord_t(1. / SCALING_FACTOR); - bbox.min.y -= coord_t(1. / SCALING_FACTOR); - bbox.max.x += coord_t(1. / SCALING_FACTOR); - bbox.max.y += coord_t(1. / SCALING_FACTOR); + bbox.min(0) -= coord_t(1. / SCALING_FACTOR); + bbox.min(1) -= coord_t(1. / SCALING_FACTOR); + bbox.max(0) += coord_t(1. / SCALING_FACTOR); + bbox.max(1) += coord_t(1. / SCALING_FACTOR); ::Slic3r::SVG svg(path, bbox); @@ -689,7 +689,7 @@ static inline void dump_voronoi_to_svg(const Lines &lines, /* const */ voronoi_d // bbox.scale(1.2); // For clipping of half-lines to some reasonable value. // The line will then be clipped by the SVG viewer anyway. - const double bbox_dim_max = double(bbox.max.x - bbox.min.x) + double(bbox.max.y - bbox.min.y); + const double bbox_dim_max = double(bbox.max(0) - bbox.min(0)) + double(bbox.max(1) - bbox.min(1)); // For the discretization of the Voronoi parabolic segments. const double discretization_step = 0.0005 * bbox_dim_max; @@ -697,8 +697,8 @@ static inline void dump_voronoi_to_svg(const Lines &lines, /* const */ voronoi_d std::vector segments; for (Lines::const_iterator it = lines.begin(); it != lines.end(); ++ it) segments.push_back(Voronoi::Internal::segment_type( - Voronoi::Internal::point_type(double(it->a.x), double(it->a.y)), - Voronoi::Internal::point_type(double(it->b.x), double(it->b.y)))); + Voronoi::Internal::point_type(double(it->a(0)), double(it->a(1))), + Voronoi::Internal::point_type(double(it->b(0)), double(it->b(1))))); // Color exterior edges. for (voronoi_diagram::const_edge_iterator it = vd.edges().begin(); it != vd.edges().end(); ++it) @@ -712,13 +712,13 @@ static inline void dump_voronoi_to_svg(const Lines &lines, /* const */ voronoi_d } // Draw the input polygon. for (Lines::const_iterator it = lines.begin(); it != lines.end(); ++it) - svg.draw(Line(Point(coord_t(it->a.x), coord_t(it->a.y)), Point(coord_t(it->b.x), coord_t(it->b.y))), inputSegmentColor, inputSegmentLineWidth); + svg.draw(Line(Point(coord_t(it->a(0)), coord_t(it->a(1))), Point(coord_t(it->b(0)), coord_t(it->b(1)))), inputSegmentColor, inputSegmentLineWidth); #if 1 // Draw voronoi vertices. for (voronoi_diagram::const_vertex_iterator it = vd.vertices().begin(); it != vd.vertices().end(); ++it) if (! internalEdgesOnly || it->color() != Voronoi::Internal::EXTERNAL_COLOR) - svg.draw(Point(coord_t(it->x()), coord_t(it->y())), voronoiPointColor, voronoiPointRadius); + svg.draw(Point(coord_t((*it)(0)), coord_t((*it)(1))), voronoiPointColor, voronoiPointRadius); for (voronoi_diagram::const_edge_iterator it = vd.edges().begin(); it != vd.edges().end(); ++it) { if (primaryEdgesOnly && !it->is_primary()) @@ -743,7 +743,7 @@ static inline void dump_voronoi_to_svg(const Lines &lines, /* const */ voronoi_d color = voronoiLineColorSecondary; } for (std::size_t i = 0; i + 1 < samples.size(); ++i) - svg.draw(Line(Point(coord_t(samples[i].x()), coord_t(samples[i].y())), Point(coord_t(samples[i+1].x()), coord_t(samples[i+1].y()))), color, voronoiLineWidth); + svg.draw(Line(Point(coord_t(samples[i](0)), coord_t(samples[i](1))), Point(coord_t(samples[i+1](0)), coord_t(samples[i+1](1)))), color, voronoiLineWidth); } #endif @@ -758,8 +758,8 @@ static inline void dump_voronoi_to_svg(const Lines &lines, /* const */ voronoi_d template T dist(const boost::polygon::point_data &p1,const boost::polygon::point_data &p2) { - T dx = p2.x() - p1.x(); - T dy = p2.y() - p1.y(); + T dx = p2(0) - p1(0); + T dy = p2(1) - p1(1); return sqrt(dx*dx+dy*dy); } @@ -770,11 +770,11 @@ inline point_type project_point_to_segment(segment_type &seg, point_type &px) typedef typename point_type::coordinate_type T; const point_type &p0 = low(seg); const point_type &p1 = high(seg); - const point_type dir(p1.x()-p0.x(), p1.y()-p0.y()); - const point_type dproj(px.x()-p0.x(), px.y()-p0.y()); - const T t = (dir.x()*dproj.x() + dir.y()*dproj.y()) / (dir.x()*dir.x() + dir.y()*dir.y()); + const point_type dir(p1(0)-p0(0), p1(1)-p0(1)); + const point_type dproj(px(0)-p0(0), px(1)-p0(1)); + const T t = (dir(0)*dproj(0) + dir(1)*dproj(1)) / (dir(0)*dir(0) + dir(1)*dir(1)); assert(t >= T(-1e-6) && t <= T(1. + 1e-6)); - return point_type(p0.x() + t*dir.x(), p0.y() + t*dir.y()); + return point_type(p0(0) + t*dir(0), p0(1) + t*dir(1)); } template @@ -828,8 +828,8 @@ public: Lines2VDSegments(const Lines &alines) : lines(alines) {} typename VD::segment_type operator[](size_t idx) const { return typename VD::segment_type( - typename VD::point_type(typename VD::coord_type(lines[idx].a.x), typename VD::coord_type(lines[idx].a.y)), - typename VD::point_type(typename VD::coord_type(lines[idx].b.x), typename VD::coord_type(lines[idx].b.y))); + typename VD::point_type(typename VD::coord_type(lines[idx].a(0)), typename VD::coord_type(lines[idx].a(1))), + typename VD::point_type(typename VD::coord_type(lines[idx].b(0)), typename VD::coord_type(lines[idx].b(1)))); } private: const Lines &lines; @@ -910,7 +910,7 @@ MedialAxis::build(ThickPolylines* polylines) assert(polyline.width.size() == polyline.points.size()*2 - 2); // prevent loop endpoints from being extended - if (polyline.first_point().coincides_with(polyline.last_point())) { + if (polyline.first_point() == polyline.last_point()) { polyline.endpoints.first = false; polyline.endpoints.second = false; } @@ -1003,7 +1003,7 @@ MedialAxis::validate_edge(const VD::edge_type* edge) // this could maybe be optimized (checking inclusion of the endpoints // might give false positives as they might belong to the contour itself) if (this->expolygon != NULL) { - if (line.a.coincides_with(line.b)) { + if (line.a == line.b) { // in this case, contains(line) returns a false positive if (!this->expolygon->contains(line.a)) return false; } else { @@ -1042,12 +1042,12 @@ MedialAxis::validate_edge(const VD::edge_type* edge) calculate the distance to that endpoint instead. */ coordf_t w0 = cell_r->contains_segment() - ? line.a.distance_to(segment_r)*2 - : line.a.distance_to(this->retrieve_endpoint(cell_r))*2; + ? segment_r.distance_to(line.a)*2 + : (this->retrieve_endpoint(cell_r) - line.a).cast().norm()*2; coordf_t w1 = cell_l->contains_segment() - ? line.b.distance_to(segment_l)*2 - : line.b.distance_to(this->retrieve_endpoint(cell_l))*2; + ? segment_l.distance_to(line.b)*2 + : (this->retrieve_endpoint(cell_l) - line.b).cast().norm()*2; if (cell_l->contains_segment() && cell_r->contains_segment()) { // calculate the relative angle between the two boundary segments diff --git a/xs/src/libslic3r/Geometry.hpp b/xs/src/libslic3r/Geometry.hpp index c2c3dc8b7..194534007 100644 --- a/xs/src/libslic3r/Geometry.hpp +++ b/xs/src/libslic3r/Geometry.hpp @@ -30,9 +30,9 @@ enum Orientation static inline Orientation orient(const Point &a, const Point &b, const Point &c) { // BOOST_STATIC_ASSERT(sizeof(coord_t) * 2 == sizeof(int64_t)); - int64_t u = int64_t(b.x) * int64_t(c.y) - int64_t(b.y) * int64_t(c.x); - int64_t v = int64_t(a.x) * int64_t(c.y) - int64_t(a.y) * int64_t(c.x); - int64_t w = int64_t(a.x) * int64_t(b.y) - int64_t(a.y) * int64_t(b.x); + int64_t u = int64_t(b(0)) * int64_t(c(1)) - int64_t(b(1)) * int64_t(c(0)); + int64_t v = int64_t(a(0)) * int64_t(c(1)) - int64_t(a(1)) * int64_t(c(0)); + int64_t w = int64_t(a(0)) * int64_t(b(1)) - int64_t(a(1)) * int64_t(b(0)); int64_t d = u - v + w; return (d > 0) ? ORIENTATION_CCW : ((d == 0) ? ORIENTATION_COLINEAR : ORIENTATION_CW); } @@ -52,7 +52,7 @@ static inline bool is_ccw(const Polygon &poly) for (unsigned int i = 1; i < poly.points.size(); ++ i) { const Point &pmin = poly.points[imin]; const Point &p = poly.points[i]; - if (p.x < pmin.x || (p.x == pmin.x && p.y < pmin.y)) + if (p(0) < pmin(0) || (p(0) == pmin(0) && p(1) < pmin(1))) imin = i; } @@ -66,26 +66,26 @@ static inline bool is_ccw(const Polygon &poly) return o == ORIENTATION_CCW; } -inline bool ray_ray_intersection(const Pointf &p1, const Vectorf &v1, const Pointf &p2, const Vectorf &v2, Pointf &res) +inline bool ray_ray_intersection(const Vec2d &p1, const Vec2d &v1, const Vec2d &p2, const Vec2d &v2, Vec2d &res) { - double denom = v1.x * v2.y - v2.x * v1.y; + double denom = v1(0) * v2(1) - v2(0) * v1(1); if (std::abs(denom) < EPSILON) return false; - double t = (v2.x * (p1.y - p2.y) - v2.y * (p1.x - p2.x)) / denom; - res.x = p1.x + t * v1.x; - res.y = p1.y + t * v1.y; + double t = (v2(0) * (p1(1) - p2(1)) - v2(1) * (p1(0) - p2(0))) / denom; + res(0) = p1(0) + t * v1(0); + res(1) = p1(1) + t * v1(1); return true; } -inline bool segment_segment_intersection(const Pointf &p1, const Vectorf &v1, const Pointf &p2, const Vectorf &v2, Pointf &res) +inline bool segment_segment_intersection(const Vec2d &p1, const Vec2d &v1, const Vec2d &p2, const Vec2d &v2, Vec2d &res) { - double denom = v1.x * v2.y - v2.x * v1.y; + double denom = v1(0) * v2(1) - v2(0) * v1(1); if (std::abs(denom) < EPSILON) // Lines are collinear. return false; - double s12_x = p1.x - p2.x; - double s12_y = p1.y - p2.y; - double s_numer = v1.x * s12_y - v1.y * s12_x; + double s12_x = p1(0) - p2(0); + double s12_y = p1(1) - p2(1); + double s_numer = v1(0) * s12_y - v1(1) * s12_x; bool denom_is_positive = false; if (denom < 0.) { denom_is_positive = true; @@ -95,7 +95,7 @@ inline bool segment_segment_intersection(const Pointf &p1, const Vectorf &v1, co if (s_numer < 0.) // Intersection outside of the 1st segment. return false; - double t_numer = v2.x * s12_y - v2.y * s12_x; + double t_numer = v2(0) * s12_y - v2(1) * s12_x; if (! denom_is_positive) t_numer = - t_numer; if (t_numer < 0. || s_numer > denom || t_numer > denom) @@ -103,8 +103,8 @@ inline bool segment_segment_intersection(const Pointf &p1, const Vectorf &v1, co return false; // Intersection inside both of the segments. double t = t_numer / denom; - res.x = p1.x + t * v1.x; - res.y = p1.y + t * v1.y; + res(0) = p1(0) + t * v1(0); + res(1) = p1(1) + t * v1(1); return true; } @@ -123,7 +123,7 @@ void simplify_polygons(const Polygons &polygons, double tolerance, Polygons* ret double linint(double value, double oldmin, double oldmax, double newmin, double newmax); bool arrange( // input - size_t num_parts, const Pointf &part_size, coordf_t gap, const BoundingBoxf* bed_bounding_box, + size_t num_parts, const Vec2d &part_size, coordf_t gap, const BoundingBoxf* bed_bounding_box, // output Pointfs &positions); diff --git a/xs/src/libslic3r/Layer.cpp b/xs/src/libslic3r/Layer.cpp index 652bcdaa0..20e8f8ae1 100644 --- a/xs/src/libslic3r/Layer.cpp +++ b/xs/src/libslic3r/Layer.cpp @@ -168,8 +168,8 @@ void Layer::export_region_slices_to_svg(const char *path) const for (Surfaces::const_iterator surface = (*region)->slices.surfaces.begin(); surface != (*region)->slices.surfaces.end(); ++surface) bbox.merge(get_extents(surface->expolygon)); Point legend_size = export_surface_type_legend_to_svg_box_size(); - Point legend_pos(bbox.min.x, bbox.max.y); - bbox.merge(Point(std::max(bbox.min.x + legend_size.x, bbox.max.x), bbox.max.y + legend_size.y)); + Point legend_pos(bbox.min(0), bbox.max(1)); + bbox.merge(Point(std::max(bbox.min(0) + legend_size(0), bbox.max(0)), bbox.max(1) + legend_size(1))); SVG svg(path, bbox); const float transparency = 0.5f; @@ -194,8 +194,8 @@ void Layer::export_region_fill_surfaces_to_svg(const char *path) const for (Surfaces::const_iterator surface = (*region)->fill_surfaces.surfaces.begin(); surface != (*region)->fill_surfaces.surfaces.end(); ++surface) bbox.merge(get_extents(surface->expolygon)); Point legend_size = export_surface_type_legend_to_svg_box_size(); - Point legend_pos(bbox.min.x, bbox.max.y); - bbox.merge(Point(std::max(bbox.min.x + legend_size.x, bbox.max.x), bbox.max.y + legend_size.y)); + Point legend_pos(bbox.min(0), bbox.max(1)); + bbox.merge(Point(std::max(bbox.min(0) + legend_size(0), bbox.max(0)), bbox.max(1) + legend_size(1))); SVG svg(path, bbox); const float transparency = 0.5f; diff --git a/xs/src/libslic3r/LayerRegion.cpp b/xs/src/libslic3r/LayerRegion.cpp index 68e17407e..afdc9c5a2 100644 --- a/xs/src/libslic3r/LayerRegion.cpp +++ b/xs/src/libslic3r/LayerRegion.cpp @@ -395,8 +395,8 @@ void LayerRegion::export_region_slices_to_svg(const char *path) const for (Surfaces::const_iterator surface = this->slices.surfaces.begin(); surface != this->slices.surfaces.end(); ++surface) bbox.merge(get_extents(surface->expolygon)); Point legend_size = export_surface_type_legend_to_svg_box_size(); - Point legend_pos(bbox.min.x, bbox.max.y); - bbox.merge(Point(std::max(bbox.min.x + legend_size.x, bbox.max.x), bbox.max.y + legend_size.y)); + Point legend_pos(bbox.min(0), bbox.max(1)); + bbox.merge(Point(std::max(bbox.min(0) + legend_size(0), bbox.max(0)), bbox.max(1) + legend_size(1))); SVG svg(path, bbox); const float transparency = 0.5f; @@ -422,8 +422,8 @@ void LayerRegion::export_region_fill_surfaces_to_svg(const char *path) const for (Surfaces::const_iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) bbox.merge(get_extents(surface->expolygon)); Point legend_size = export_surface_type_legend_to_svg_box_size(); - Point legend_pos(bbox.min.x, bbox.max.y); - bbox.merge(Point(std::max(bbox.min.x + legend_size.x, bbox.max.x), bbox.max.y + legend_size.y)); + Point legend_pos(bbox.min(0), bbox.max(1)); + bbox.merge(Point(std::max(bbox.min(0) + legend_size(0), bbox.max(0)), bbox.max(1) + legend_size(1))); SVG svg(path, bbox); const float transparency = 0.5f; diff --git a/xs/src/libslic3r/Line.cpp b/xs/src/libslic3r/Line.cpp index e9d5d7742..a29e4ce4e 100644 --- a/xs/src/libslic3r/Line.cpp +++ b/xs/src/libslic3r/Line.cpp @@ -7,133 +7,58 @@ namespace Slic3r { -std::string -Line::wkt() const +bool Line::intersection_infinite(const Line &other, Point* point) const { - std::ostringstream ss; - ss << "LINESTRING(" << this->a.x << " " << this->a.y << "," - << this->b.x << " " << this->b.y << ")"; - return ss.str(); -} - -Line::operator Lines() const -{ - Lines lines; - lines.push_back(*this); - return lines; -} - -Line::operator Polyline() const -{ - Polyline pl; - pl.points.push_back(this->a); - pl.points.push_back(this->b); - return pl; -} - -void -Line::scale(double factor) -{ - this->a.scale(factor); - this->b.scale(factor); -} - -void -Line::translate(double x, double y) -{ - this->a.translate(x, y); - this->b.translate(x, y); -} - -void -Line::rotate(double angle, const Point ¢er) -{ - this->a.rotate(angle, center); - this->b.rotate(angle, center); -} - -void -Line::reverse() -{ - std::swap(this->a, this->b); -} - -double -Line::length() const -{ - return this->a.distance_to(this->b); -} - -Point -Line::midpoint() const -{ - return Point((this->a.x + this->b.x) / 2.0, (this->a.y + this->b.y) / 2.0); -} - -void -Line::point_at(double distance, Point* point) const -{ - double len = this->length(); - *point = this->a; - if (this->a.x != this->b.x) - point->x = this->a.x + (this->b.x - this->a.x) * distance / len; - if (this->a.y != this->b.y) - point->y = this->a.y + (this->b.y - this->a.y) * distance / len; -} - -Point -Line::point_at(double distance) const -{ - Point p; - this->point_at(distance, &p); - return p; -} - -bool -Line::intersection_infinite(const Line &other, Point* point) const -{ - Vector x = this->a.vector_to(other.a); - Vector d1 = this->vector(); - Vector d2 = other.vector(); - - double cross = d1.x * d2.y - d1.y * d2.x; - if (std::fabs(cross) < EPSILON) + Vec2d a1 = this->a.cast(); + Vec2d a2 = other.a.cast(); + Vec2d v12 = (other.a - this->a).cast(); + Vec2d v1 = (this->b - this->a).cast(); + Vec2d v2 = (other.b - other.a).cast(); + double denom = cross2(v1, v2); + if (std::fabs(denom) < EPSILON) return false; - - double t1 = (x.x * d2.y - x.y * d2.x)/cross; - point->x = this->a.x + d1.x * t1; - point->y = this->a.y + d1.y * t1; + double t1 = cross2(v12, v2) / denom; + *point = (a1 + t1 * v1).cast(); return true; } -bool -Line::coincides_with(const Line &line) const +/* distance to the closest point of line */ +double Line::distance_to(const Point &point) const { - return this->a.coincides_with(line.a) && this->b.coincides_with(line.b); + const Line &line = *this; + const Vec2d v = (line.b - line.a).cast(); + const Vec2d va = (point - line.a).cast(); + const double l2 = v.squaredNorm(); // avoid a sqrt + if (l2 == 0.0) + // line.a == line.b case + return va.norm(); + // Consider the line extending the segment, parameterized as line.a + t (line.b - line.a). + // We find projection of this point onto the line. + // It falls where t = [(this-line.a) . (line.b-line.a)] / |line.b-line.a|^2 + const double t = va.dot(v) / l2; + if (t < 0.0) return va.norm(); // beyond the 'a' end of the segment + else if (t > 1.0) return (point - line.b).cast().norm(); // beyond the 'b' end of the segment + return (t * v - va).norm(); } -double -Line::distance_to(const Point &point) const +double Line::perp_distance_to(const Point &point) const { - return point.distance_to(*this); + const Line &line = *this; + const Vec2d v = (line.b - line.a).cast(); + const Vec2d va = (point - line.a).cast(); + if (line.a == line.b) + return va.norm(); + return std::abs(cross2(v, va)) / v.norm(); } -double -Line::atan2_() const -{ - return atan2(this->b.y - this->a.y, this->b.x - this->a.x); -} - -double -Line::orientation() const +double Line::orientation() const { double angle = this->atan2_(); if (angle < 0) angle = 2*PI + angle; return angle; } -double -Line::direction() const +double Line::direction() const { double atan2 = this->atan2_(); return (fabs(atan2 - PI) < EPSILON) ? 0 @@ -141,108 +66,42 @@ Line::direction() const : atan2; } -bool -Line::parallel_to(double angle) const { +bool Line::parallel_to(double angle) const +{ return Slic3r::Geometry::directions_parallel(this->direction(), angle); } -bool -Line::parallel_to(const Line &line) const { - return this->parallel_to(line.direction()); -} - -Vector -Line::vector() const +bool Line::intersection(const Line &l2, Point *intersection) const { - return Vector(this->b.x - this->a.x, this->b.y - this->a.y); -} - -Vector -Line::normal() const -{ - return Vector((this->b.y - this->a.y), -(this->b.x - this->a.x)); -} - -void -Line::extend_end(double distance) -{ - // relocate last point by extending the segment by the specified length - Line line = *this; - line.reverse(); - this->b = line.point_at(-distance); -} - -void -Line::extend_start(double distance) -{ - // relocate first point by extending the first segment by the specified length - this->a = this->point_at(-distance); -} - -bool -Line::intersection(const Line& line, Point* intersection) const -{ - double denom = ((double)(line.b.y - line.a.y)*(this->b.x - this->a.x)) - - ((double)(line.b.x - line.a.x)*(this->b.y - this->a.y)); - - double nume_a = ((double)(line.b.x - line.a.x)*(this->a.y - line.a.y)) - - ((double)(line.b.y - line.a.y)*(this->a.x - line.a.x)); - - double nume_b = ((double)(this->b.x - this->a.x)*(this->a.y - line.a.y)) - - ((double)(this->b.y - this->a.y)*(this->a.x - line.a.x)); - - if (fabs(denom) < EPSILON) { - if (fabs(nume_a) < EPSILON && fabs(nume_b) < EPSILON) { - return false; // coincident - } - return false; // parallel - } - - double ua = nume_a / denom; - double ub = nume_b / denom; - - if (ua >= 0 && ua <= 1.0f && ub >= 0 && ub <= 1.0f) - { + const Line &l1 = *this; + const Vec2d v1 = (l1.b - l1.a).cast(); + const Vec2d v2 = (l2.b - l2.a).cast(); + const Vec2d v12 = (l1.a - l2.a).cast(); + double denom = cross2(v1, v2); + double nume_a = cross2(v2, v12); + double nume_b = cross2(v1, v12); + if (fabs(denom) < EPSILON) +#if 0 + // Lines are collinear. Return true if they are coincident (overlappign). + return ! (fabs(nume_a) < EPSILON && fabs(nume_b) < EPSILON); +#else + return false; +#endif + double t1 = nume_a / denom; + double t2 = nume_b / denom; + if (t1 >= 0 && t1 <= 1.0f && t2 >= 0 && t2 <= 1.0f) { // Get the intersection point. - intersection->x = this->a.x + ua*(this->b.x - this->a.x); - intersection->y = this->a.y + ua*(this->b.y - this->a.y); + (*intersection) = (l1.a.cast() + t1 * v1).cast(); return true; } - return false; // not intersecting } -double -Line::ccw(const Point& point) const +Vec3d Linef3::intersect_plane(double z) const { - return point.ccw(*this); -} - -double Line3::length() const -{ - return a.distance_to(b); -} - -Vector3 Line3::vector() const -{ - return Vector3(b.x - a.x, b.y - a.y, b.z - a.z); -} - -Pointf3 -Linef3::intersect_plane(double z) const -{ - return Pointf3( - this->a.x + (this->b.x - this->a.x) * (z - this->a.z) / (this->b.z - this->a.z), - this->a.y + (this->b.y - this->a.y) * (z - this->a.z) / (this->b.z - this->a.z), - z - ); -} - -void -Linef3::scale(double factor) -{ - this->a.scale(factor); - this->b.scale(factor); + auto v = (this->b - this->a).cast(); + double t = (z - this->a(2)) / v(2); + return Vec3d(this->a(0) + v(0) * t, this->a(1) + v(1) * t, z); } } diff --git a/xs/src/libslic3r/Line.hpp b/xs/src/libslic3r/Line.hpp index 7dd1a83d5..5b77a4b61 100644 --- a/xs/src/libslic3r/Line.hpp +++ b/xs/src/libslic3r/Line.hpp @@ -18,81 +18,80 @@ typedef std::vector ThickLines; class Line { public: - Point a; - Point b; - Line() {}; - explicit Line(Point _a, Point _b): a(_a), b(_b) {}; - std::string wkt() const; - operator Lines() const; - operator Polyline() const; - void scale(double factor); - void translate(double x, double y); - void rotate(double angle, const Point ¢er); - void reverse(); - double length() const; - Point midpoint() const; - void point_at(double distance, Point* point) const; - Point point_at(double distance) const; - bool intersection_infinite(const Line &other, Point* point) const; - bool coincides_with(const Line &line) const; + Line() {} + Line(const Point& _a, const Point& _b) : a(_a), b(_b) {} + explicit operator Lines() const { Lines lines; lines.emplace_back(*this); return lines; } + void scale(double factor) { this->a *= factor; this->b *= factor; } + void translate(double x, double y) { Vector v(x, y); this->a += v; this->b += v; } + void rotate(double angle, const Point ¢er) { this->a.rotate(angle, center); this->b.rotate(angle, center); } + void reverse() { std::swap(this->a, this->b); } + double length() const { return (b - a).cast().norm(); } + Point midpoint() const { return (this->a + this->b) / 2; } + bool intersection_infinite(const Line &other, Point* point) const; + bool operator==(const Line &rhs) const { return this->a == rhs.a && this->b == rhs.b; } double distance_to(const Point &point) const; - bool parallel_to(double angle) const; - bool parallel_to(const Line &line) const; - double atan2_() const; + double perp_distance_to(const Point &point) const; + bool parallel_to(double angle) const; + bool parallel_to(const Line &line) const { return this->parallel_to(line.direction()); } + double atan2_() const { return atan2(this->b(1) - this->a(1), this->b(0) - this->a(0)); } double orientation() const; double direction() const; - Vector vector() const; - Vector normal() const; - void extend_end(double distance); - void extend_start(double distance); - bool intersection(const Line& line, Point* intersection) const; - double ccw(const Point& point) const; + Vector vector() const { return this->b - this->a; } + Vector normal() const { return Vector((this->b(1) - this->a(1)), -(this->b(0) - this->a(0))); } + bool intersection(const Line& line, Point* intersection) const; + double ccw(const Point& point) const { return point.ccw(*this); } + + Point a; + Point b; }; class ThickLine : public Line { - public: - coordf_t a_width, b_width; - - ThickLine() : a_width(0), b_width(0) {}; - ThickLine(Point _a, Point _b) : Line(_a, _b), a_width(0), b_width(0) {}; +public: + ThickLine() : a_width(0), b_width(0) {} + ThickLine(const Point& a, const Point& b) : Line(a, b), a_width(0), b_width(0) {} + ThickLine(const Point& a, const Point& b, double wa, double wb) : Line(a, b), a_width(wa), b_width(wb) {} + + double a_width, b_width; }; class Line3 { public: - Point3 a; - Point3 b; + Line3() : a(Vec3crd::Zero()), b(Vec3crd::Zero()) {} + Line3(const Vec3crd& _a, const Vec3crd& _b) : a(_a), b(_b) {} - Line3() {} - Line3(const Point3& _a, const Point3& _b) : a(_a), b(_b) {} + double length() const { return (this->a - this->b).cast().norm(); } + Vec3crd vector() const { return this->b - this->a; } - double length() const; - Vector3 vector() const; + Vec3crd a; + Vec3crd b; }; class Linef { - public: - Pointf a; - Pointf b; - Linef() {}; - explicit Linef(Pointf _a, Pointf _b): a(_a), b(_b) {}; +public: + Linef() : a(Vec2d::Zero()), b(Vec2d::Zero()) {} + Linef(const Vec2d& _a, const Vec2d& _b) : a(_a), b(_b) {} + + Vec2d a; + Vec2d b; }; class Linef3 { - public: - Pointf3 a; - Pointf3 b; - Linef3() {}; - explicit Linef3(Pointf3 _a, Pointf3 _b): a(_a), b(_b) {}; - Pointf3 intersect_plane(double z) const; - void scale(double factor); +public: + Linef3() : a(Vec3d::Zero()), b(Vec3d::Zero()) {} + Linef3(const Vec3d& _a, const Vec3d& _b) : a(_a), b(_b) {} - double length() const { return this->a.distance_to(this->b); } - Vectorf3 vector() const { return Vectorf3(this->b.x - this->a.x, this->b.y - this->a.y, this->b.z - this->a.z); } - Vectorf3 unit_vector() const { return (length() == 0.0) ? Vectorf3(0.0, 0.0, 0.0) : normalize(vector()); } + Vec3d intersect_plane(double z) const; + void scale(double factor) { this->a *= factor; this->b *= factor; } + Vec3d vector() const { return this->b - this->a; } + Vec3d unit_vector() const { return (length() == 0.0) ? Vec3d::Zero() : vector().normalized(); } + double length() const { return vector().norm(); } + + Vec3d a; + Vec3d b; }; } // namespace Slic3r diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp index 23d447748..d046a8ef2 100644 --- a/xs/src/libslic3r/Model.cpp +++ b/xs/src/libslic3r/Model.cpp @@ -17,11 +17,6 @@ #include "SVG.hpp" #include -static const float UNIT_MATRIX[] = { 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f }; - namespace Slic3r { unsigned int Model::s_auto_extruder_id = 1; @@ -240,7 +235,7 @@ BoundingBoxf3 Model::bounding_box() const return bb; } -void Model::center_instances_around_point(const Pointf &point) +void Model::center_instances_around_point(const Vec2d &point) { // BoundingBoxf3 bb = this->bounding_box(); BoundingBoxf3 bb; @@ -248,12 +243,10 @@ void Model::center_instances_around_point(const Pointf &point) for (size_t i = 0; i < o->instances.size(); ++ i) bb.merge(o->instance_bounding_box(i, false)); - Sizef3 size = bb.size(); - coordf_t shift_x = -bb.min.x + point.x - size.x/2; - coordf_t shift_y = -bb.min.y + point.y - size.y/2; + Vec2d shift = point - 0.5 * to_2d(bb.size()) - to_2d(bb.min); for (ModelObject *o : this->objects) { for (ModelInstance *i : o->instances) - i->offset.translate(shift_x, shift_y); + i->offset += shift; o->invalidate_bounding_box(); } } @@ -308,8 +301,8 @@ bool Model::arrange_objects(coordf_t dist, const BoundingBoxf* bb) for (size_t i = 0; i < o->instances.size(); ++ i) { // an accurate snug bounding box around the transformed mesh. BoundingBoxf3 bbox(o->instance_bounding_box(i, true)); - instance_sizes.push_back(bbox.size()); - instance_centers.push_back(bbox.center()); + instance_sizes.emplace_back(to_2d(bbox.size())); + instance_centers.emplace_back(to_2d(bbox.center())); } Pointfs positions; @@ -331,7 +324,7 @@ bool Model::arrange_objects(coordf_t dist, const BoundingBoxf* bb) // Duplicate the entire model preserving instance relative positions. void Model::duplicate(size_t copies_num, coordf_t dist, const BoundingBoxf* bb) { - Pointfs model_sizes(copies_num-1, this->bounding_box().size()); + Pointfs model_sizes(copies_num-1, to_2d(this->bounding_box().size())); Pointfs positions; if (! _arrange(model_sizes, dist, bb, positions)) CONFESS("Cannot duplicate part as the resulting objects would not fit on the print bed.\n"); @@ -342,9 +335,9 @@ void Model::duplicate(size_t copies_num, coordf_t dist, const BoundingBoxf* bb) // make a copy of the pointers in order to avoid recursion when appending their copies ModelInstancePtrs instances = o->instances; for (const ModelInstance *i : instances) { - for (const Pointf &pos : positions) { + for (const Vec2d &pos : positions) { ModelInstance *instance = o->add_instance(*i); - instance->offset.translate(pos); + instance->offset += pos; } } o->invalidate_bounding_box(); @@ -374,13 +367,13 @@ void Model::duplicate_objects_grid(size_t x, size_t y, coordf_t dist) ModelObject* object = this->objects.front(); object->clear_instances(); - Sizef3 size = object->bounding_box().size(); + Vec3d size = object->bounding_box().size(); for (size_t x_copy = 1; x_copy <= x; ++x_copy) { for (size_t y_copy = 1; y_copy <= y; ++y_copy) { ModelInstance* instance = object->add_instance(); - instance->offset.x = (size.x + dist) * (x_copy-1); - instance->offset.y = (size.y + dist) * (y_copy-1); + instance->offset(0) = (size(0) + dist) * (x_copy-1); + instance->offset(1) = (size(1) + dist) * (y_copy-1); } } } @@ -394,7 +387,7 @@ bool Model::looks_like_multipart_object() const if (obj->volumes.size() > 1 || obj->config.keys().size() > 1) return false; for (const ModelVolume *vol : obj->volumes) { - double zmin_this = vol->mesh.bounding_box().min.z; + double zmin_this = vol->mesh.bounding_box().min(2); if (zmin == std::numeric_limits::max()) zmin = zmin_this; else if (std::abs(zmin - zmin_this) > EPSILON) @@ -438,13 +431,13 @@ void Model::adjust_min_z() if (objects.empty()) return; - if (bounding_box().min.z < 0.0) + if (bounding_box().min(2) < 0.0) { for (ModelObject* obj : objects) { if (obj != nullptr) { - coordf_t obj_min_z = obj->bounding_box().min.z; + coordf_t obj_min_z = obj->bounding_box().min(2); if (obj_min_z < 0.0) obj->translate(0.0, 0.0, -obj_min_z); } @@ -677,25 +670,22 @@ void ModelObject::center_around_origin() if (! v->modifier) bb.merge(v->mesh.bounding_box()); - // first align to origin on XYZ - Vectorf3 vector(-bb.min.x, -bb.min.y, -bb.min.z); + // First align to origin on XYZ, then center it on XY. + Vec3d size = bb.size(); + size(2) = 0.; + Vec3d shift3 = - bb.min - 0.5 * size; + // Unaligned vector, for the Rotation2D to work on Visual Studio 2013. + Eigen::Vector2d shift2 = to_2d(shift3); - // then center it on XY - Sizef3 size = bb.size(); - vector.x -= size.x/2; - vector.y -= size.y/2; - - this->translate(vector); - this->origin_translation.translate(vector); + this->translate(shift3); + this->origin_translation += shift3; if (!this->instances.empty()) { for (ModelInstance *i : this->instances) { // apply rotation and scaling to vector as well before translating instance, // in order to leave final position unaltered - Vectorf3 v = vector.negative(); - v.rotate(i->rotation); - v.scale(i->scaling_factor); - i->offset.translate(v.x, v.y); + Eigen::Rotation2Dd rot(i->rotation); + i->offset -= rot * shift2 * i->scaling_factor; } this->invalidate_bounding_box(); } @@ -713,7 +703,7 @@ void ModelObject::translate(coordf_t x, coordf_t y, coordf_t z) m_bounding_box.translate(x, y, z); } -void ModelObject::scale(const Pointf3 &versor) +void ModelObject::scale(const Vec3d &versor) { for (ModelVolume *v : this->volumes) { @@ -721,7 +711,7 @@ void ModelObject::scale(const Pointf3 &versor) v->m_convex_hull.scale(versor); } // reset origin translation since it doesn't make sense anymore - this->origin_translation = Pointf3(0,0,0); + this->origin_translation = Vec3d::Zero(); this->invalidate_bounding_box(); } @@ -735,7 +725,7 @@ void ModelObject::rotate(float angle, const Axis &axis) center_around_origin(); - this->origin_translation = Pointf3(0, 0, 0); + this->origin_translation = Vec3d::Zero(); this->invalidate_bounding_box(); } @@ -750,8 +740,8 @@ void ModelObject::transform(const float* matrix3x4) v->m_convex_hull.transform(matrix3x4); } - origin_translation = Pointf3(0.0, 0.0, 0.0); - invalidate_bounding_box(); + this->origin_translation = Vec3d::Zero(); + this->invalidate_bounding_box(); } void ModelObject::mirror(const Axis &axis) @@ -762,7 +752,7 @@ void ModelObject::mirror(const Axis &axis) v->m_convex_hull.mirror(axis); } - this->origin_translation = Pointf3(0, 0, 0); + this->origin_translation = Vec3d::Zero(); this->invalidate_bounding_box(); } @@ -872,14 +862,12 @@ void ModelObject::check_instances_print_volume_state(const BoundingBoxf3& print_ { for (ModelInstance* inst : this->instances) { - std::vector world_mat(UNIT_MATRIX, std::end(UNIT_MATRIX)); - Eigen::Transform m = Eigen::Transform::Identity(); - m.translate(Eigen::Vector3f((float)inst->offset.x, (float)inst->offset.y, 0.0f)); - m.rotate(Eigen::AngleAxisf(inst->rotation, Eigen::Vector3f::UnitZ())); + Transform3d m = Transform3d::Identity(); + m.translate(Vec3d(inst->offset(0), inst->offset(1), 0.0)); + m.rotate(Eigen::AngleAxisd(inst->rotation, Vec3d::UnitZ())); m.scale(inst->scaling_factor); - ::memcpy((void*)world_mat.data(), (const void*)m.data(), 16 * sizeof(float)); - BoundingBoxf3 bb = vol->get_convex_hull().transformed_bounding_box(world_mat); + BoundingBoxf3 bb = vol->get_convex_hull().transformed_bounding_box(m); if (print_volume.contains(bb)) inst->print_volume_state = ModelInstance::PVS_Inside; @@ -901,16 +889,16 @@ void ModelObject::print_info() const TriangleMesh mesh = this->raw_mesh(); mesh.check_topology(); BoundingBoxf3 bb = mesh.bounding_box(); - Sizef3 size = bb.size(); - cout << "size_x = " << size.x << endl; - cout << "size_y = " << size.y << endl; - cout << "size_z = " << size.z << endl; - cout << "min_x = " << bb.min.x << endl; - cout << "min_y = " << bb.min.y << endl; - cout << "min_z = " << bb.min.z << endl; - cout << "max_x = " << bb.max.x << endl; - cout << "max_y = " << bb.max.y << endl; - cout << "max_z = " << bb.max.z << endl; + Vec3d size = bb.size(); + cout << "size_x = " << size(0) << endl; + cout << "size_y = " << size(1) << endl; + cout << "size_z = " << size(2) << endl; + cout << "min_x = " << bb.min(0) << endl; + cout << "min_y = " << bb.min(1) << endl; + cout << "min_z = " << bb.min(2) << endl; + cout << "max_x = " << bb.max(0) << endl; + cout << "max_y = " << bb.max(1) << endl; + cout << "max_z = " << bb.max(2) << endl; cout << "number_of_facets = " << mesh.stl.stats.number_of_facets << endl; cout << "manifold = " << (mesh.is_manifold() ? "yes" : "no") << endl; @@ -1011,7 +999,7 @@ void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) cons mesh->rotate_z(this->rotation); // rotate around mesh origin mesh->scale(this->scaling_factor); // scale around mesh origin if (!dont_translate) - mesh->translate(this->offset.x, this->offset.y, 0); + mesh->translate(this->offset(0), this->offset(1), 0); } BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh* mesh, bool dont_translate) const @@ -1023,30 +1011,20 @@ BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh* mes for (int i = 0; i < mesh->stl.stats.number_of_facets; ++ i) { const stl_facet &facet = mesh->stl.facet_start[i]; for (int j = 0; j < 3; ++ j) { - stl_vertex v = facet.vertex[j]; - double xold = v.x; - double yold = v.y; - v.x = float(c * xold - s * yold); - v.y = float(s * xold + c * yold); - bbox.merge(Pointf3(v.x, v.y, v.z)); + const stl_vertex &v = facet.vertex[j]; + bbox.merge(Vec3d(c * v(0) - s * v(1), s * v(0) + c * v(1), v(2))); } } if (! empty(bbox)) { // Scale the bounding box uniformly. if (std::abs(this->scaling_factor - 1.) > EPSILON) { - bbox.min.x *= float(this->scaling_factor); - bbox.min.y *= float(this->scaling_factor); - bbox.min.z *= float(this->scaling_factor); - bbox.max.x *= float(this->scaling_factor); - bbox.max.y *= float(this->scaling_factor); - bbox.max.z *= float(this->scaling_factor); + bbox.min *= this->scaling_factor; + bbox.max *= this->scaling_factor; } // Translate the bounding box. if (! dont_translate) { - bbox.min.x += float(this->offset.x); - bbox.min.y += float(this->offset.y); - bbox.max.x += float(this->offset.x); - bbox.max.y += float(this->offset.y); + Eigen::Map(bbox.min.data()) += this->offset; + Eigen::Map(bbox.max.data()) += this->offset; } } return bbox; @@ -1054,16 +1032,13 @@ BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh* mes BoundingBoxf3 ModelInstance::transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate) const { - Eigen::Transform matrix = Eigen::Transform::Identity(); + Transform3d matrix = Transform3d::Identity(); if (!dont_translate) - matrix.translate(Eigen::Vector3f((float)offset.x, (float)offset.y, 0.0f)); + matrix.translate(Vec3d(offset(0), offset(1), 0.0)); - matrix.rotate(Eigen::AngleAxisf(rotation, Eigen::Vector3f::UnitZ())); + matrix.rotate(Eigen::AngleAxisd(rotation, Vec3d::UnitZ())); matrix.scale(scaling_factor); - - std::vector m(16, 0.0f); - ::memcpy((void*)m.data(), (const void*)matrix.data(), 16 * sizeof(float)); - return bbox.transformed(m); + return bbox.transformed(matrix); } void ModelInstance::transform_polygon(Polygon* polygon) const diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp index 23af9fb1c..468e6f833 100644 --- a/xs/src/libslic3r/Model.hpp +++ b/xs/src/libslic3r/Model.hpp @@ -84,7 +84,7 @@ public: center_around_origin() method. Callers might want to apply the same translation to new volumes before adding them to this object in order to preserve alignment when user expects that. */ - Pointf3 origin_translation; + Vec3d origin_translation; Model* get_model() const { return m_model; }; @@ -117,9 +117,9 @@ public: // A snug bounding box around the transformed non-modifier object volumes. BoundingBoxf3 instance_bounding_box(size_t instance_idx, bool dont_translate = false) const; void center_around_origin(); - void translate(const Vectorf3 &vector) { this->translate(vector.x, vector.y, vector.z); } + void translate(const Vec3d &vector) { this->translate(vector(0), vector(1), vector(2)); } void translate(coordf_t x, coordf_t y, coordf_t z); - void scale(const Pointf3 &versor); + void scale(const Vec3d &versor); void rotate(float angle, const Axis &axis); void transform(const float* matrix3x4); void mirror(const Axis &axis); @@ -135,7 +135,7 @@ public: void print_info() const; private: - ModelObject(Model *model) : layer_height_profile_valid(false), m_model(model), m_bounding_box_valid(false) {} + ModelObject(Model *model) : layer_height_profile_valid(false), m_model(model), origin_translation(Vec3d::Zero()), m_bounding_box_valid(false) {} ModelObject(Model *model, const ModelObject &other, bool copy_volumes = true); ModelObject& operator= (ModelObject other); void swap(ModelObject &other); @@ -224,9 +224,10 @@ public: friend class ModelObject; +// Transform3d transform; double rotation; // Rotation around the Z axis, in radians around mesh center point double scaling_factor; - Pointf offset; // in unscaled coordinates + Vec2d offset; // in unscaled coordinates // flag showing the position of this instance with respect to the print volume (set by Print::validate() using ModelObject::check_instances_print_volume_state()) EPrintVolumeState print_volume_state; @@ -248,7 +249,7 @@ private: // Parent object, owning this instance. ModelObject* object; - ModelInstance(ModelObject *object) : rotation(0), scaling_factor(1), object(object), print_volume_state(PVS_Inside) {} + ModelInstance(ModelObject *object) : rotation(0), scaling_factor(1), offset(Vec2d::Zero()), object(object), print_volume_state(PVS_Inside) {} ModelInstance(ModelObject *object, const ModelInstance &other) : rotation(other.rotation), scaling_factor(other.scaling_factor), offset(other.offset), object(object), print_volume_state(PVS_Inside) {} }; @@ -299,7 +300,7 @@ public: bool add_default_instances(); // Returns approximate axis aligned bounding box of this model BoundingBoxf3 bounding_box() const; - void center_instances_around_point(const Pointf &point); + void center_instances_around_point(const Vec2d &point); void translate(coordf_t x, coordf_t y, coordf_t z) { for (ModelObject *o : this->objects) o->translate(x, y, z); } TriangleMesh mesh() const; bool arrange_objects(coordf_t dist, const BoundingBoxf* bb = NULL); diff --git a/xs/src/libslic3r/ModelArrange.hpp b/xs/src/libslic3r/ModelArrange.hpp index f2d399ac6..db18e6731 100644 --- a/xs/src/libslic3r/ModelArrange.hpp +++ b/xs/src/libslic3r/ModelArrange.hpp @@ -44,11 +44,11 @@ std::string toString(const Model& model, bool holes = true) { ss << "\t\t{\n"; for(auto v : expoly.contour.points) ss << "\t\t\t{" - << v.x << ", " - << v.y << "},\n"; + << v(0) << ", " + << v(1) << "},\n"; { auto v = expoly.contour.points.front(); - ss << "\t\t\t{" << v.x << ", " << v.y << "},\n"; + ss << "\t\t\t{" << v(0) << ", " << v(1) << "},\n"; } ss << "\t\t},\n"; @@ -57,11 +57,11 @@ std::string toString(const Model& model, bool holes = true) { if(holes) for(auto h : expoly.holes) { ss << "\t\t\t{\n"; for(auto v : h.points) ss << "\t\t\t\t{" - << v.x << ", " - << v.y << "},\n"; + << v(0) << ", " + << v(1) << "},\n"; { auto v = h.points.front(); - ss << "\t\t\t\t{" << v.x << ", " << v.y << "},\n"; + ss << "\t\t\t\t{" << v(0) << ", " << v(1) << "},\n"; } ss << "\t\t\t},\n"; } @@ -427,8 +427,8 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) { if(item.vertexCount() > 3) { item.rotation(objinst->rotation); item.translation( { - ClipperLib::cInt(objinst->offset.x/SCALING_FACTOR), - ClipperLib::cInt(objinst->offset.y/SCALING_FACTOR) + ClipperLib::cInt(objinst->offset(0)/SCALING_FACTOR), + ClipperLib::cInt(objinst->offset(1)/SCALING_FACTOR) }); ret.emplace_back(objinst, item); } @@ -468,7 +468,7 @@ void applyResult( // appropriately auto off = item.translation(); Radians rot = item.rotation(); - Pointf foff(off.X*SCALING_FACTOR + batch_offset, + Vec2d foff(off.X*SCALING_FACTOR + batch_offset, off.Y*SCALING_FACTOR); // write the tranformation data into the model instance @@ -528,12 +528,12 @@ bool arrange(Model &model, coordf_t min_obj_distance, BoundingBox bbb(bed.points); auto binbb = Box({ - static_cast(bbb.min.x), - static_cast(bbb.min.y) + static_cast(bbb.min(0)), + static_cast(bbb.min(1)) }, { - static_cast(bbb.max.x), - static_cast(bbb.max.y) + static_cast(bbb.max(0)), + static_cast(bbb.max(1)) }); switch(bedhint) { diff --git a/xs/src/libslic3r/MotionPlanner.cpp b/xs/src/libslic3r/MotionPlanner.cpp index e8605d68c..ff3475ed8 100644 --- a/xs/src/libslic3r/MotionPlanner.cpp +++ b/xs/src/libslic3r/MotionPlanner.cpp @@ -58,7 +58,7 @@ Polyline MotionPlanner::shortest_path(const Point &from, const Point &to) { // If we have an empty configuration space, return a straight move. if (m_islands.empty()) - return Line(from, to); + return Polyline(from, to); // Are both points in the same island? int island_idx_from = -1; @@ -74,7 +74,7 @@ Polyline MotionPlanner::shortest_path(const Point &from, const Point &to) // Since both points are in the same island, is a direct move possible? // If so, we avoid generating the visibility environment. if (island.m_island.contains(Line(from, to))) - return Line(from, to); + return Polyline(from, to); // Both points are inside a single island, but the straight line crosses the island boundary. island_idx = idx; break; @@ -90,7 +90,7 @@ Polyline MotionPlanner::shortest_path(const Point &from, const Point &to) if (env.m_env.expolygons.empty()) { // if this environment is empty (probably because it's too small), perform straight move // and avoid running the algorithms on empty dataset - return Line(from, to); + return Polyline(from, to); } // Now check whether points are inside the environment. @@ -224,7 +224,7 @@ const MotionPlannerGraph& MotionPlanner::init_graph(int island_idx) else v1_idx = i_v1->second; // Euclidean distance is used as weight for the graph edge - graph->add_edge(v0_idx, v1_idx, p0.distance_to(p1)); + graph->add_edge(v0_idx, v1_idx, (p1 - p0).cast().norm()); } } } @@ -238,7 +238,7 @@ static inline size_t nearest_waypoint_index(const Point &start_point, const Poin size_t idx = size_t(-1); double dmin = std::numeric_limits::infinity(); for (const Point &p : middle_points) { - double d = start_point.distance_to(p) + p.distance_to(end_point); + double d = (p - start_point).cast().norm() + (end_point - p).cast().norm(); if (d < dmin) { idx = &p - middle_points.data(); dmin = d; diff --git a/xs/src/libslic3r/MultiPoint.cpp b/xs/src/libslic3r/MultiPoint.cpp index 2e65492cd..f44897a04 100644 --- a/xs/src/libslic3r/MultiPoint.cpp +++ b/xs/src/libslic3r/MultiPoint.cpp @@ -8,59 +8,52 @@ MultiPoint::operator Points() const return this->points; } -void -MultiPoint::scale(double factor) +void MultiPoint::scale(double factor) { - for (Points::iterator it = points.begin(); it != points.end(); ++it) { - (*it).scale(factor); - } + for (Point &pt : points) + pt *= factor; } -void -MultiPoint::translate(double x, double y) +void MultiPoint::translate(double x, double y) { - for (Points::iterator it = points.begin(); it != points.end(); ++it) { - (*it).translate(x, y); - } + Vector v(x, y); + for (Point &pt : points) + pt += v; } -void -MultiPoint::translate(const Point &vector) +void MultiPoint::translate(const Point &v) { - this->translate(vector.x, vector.y); + for (Point &pt : points) + pt += v; } void MultiPoint::rotate(double cos_angle, double sin_angle) { for (Point &pt : this->points) { - double cur_x = double(pt.x); - double cur_y = double(pt.y); - pt.x = coord_t(round(cos_angle * cur_x - sin_angle * cur_y)); - pt.y = coord_t(round(cos_angle * cur_y + sin_angle * cur_x)); + double cur_x = double(pt(0)); + double cur_y = double(pt(1)); + pt(0) = coord_t(round(cos_angle * cur_x - sin_angle * cur_y)); + pt(1) = coord_t(round(cos_angle * cur_y + sin_angle * cur_x)); } } -void -MultiPoint::rotate(double angle, const Point ¢er) +void MultiPoint::rotate(double angle, const Point ¢er) { double s = sin(angle); double c = cos(angle); - for (Points::iterator it = points.begin(); it != points.end(); ++it) { - double dx = double(it->x - center.x); - double dy = double(it->y - center.y); - it->x = (coord_t)round(double(center.x) + c * dx - s * dy); - it->y = (coord_t)round(double(center.y) + c * dy + s * dx); + for (Point &pt : points) { + Vec2crd v(pt - center); + pt(0) = (coord_t)round(double(center(0)) + c * v[0] - s * v[1]); + pt(1) = (coord_t)round(double(center(1)) + c * v[1] + s * v[0]); } } -void -MultiPoint::reverse() +void MultiPoint::reverse() { std::reverse(this->points.begin(), this->points.end()); } -Point -MultiPoint::first_point() const +Point MultiPoint::first_point() const { return this->points.front(); } @@ -79,16 +72,16 @@ MultiPoint::length() const int MultiPoint::find_point(const Point &point) const { - for (Points::const_iterator it = this->points.begin(); it != this->points.end(); ++it) { - if (it->coincides_with(point)) return it - this->points.begin(); - } + for (const Point &pt : this->points) + if (pt == point) + return &pt - &this->points.front(); return -1; // not found } bool MultiPoint::has_boundary_point(const Point &point) const { - double dist = point.distance_to(point.projection_onto(*this)); + double dist = (point.projection_onto(*this) - point).cast().norm(); return dist < SCALED_EPSILON; } @@ -102,7 +95,7 @@ bool MultiPoint::has_duplicate_points() const { for (size_t i = 1; i < points.size(); ++i) - if (points[i-1].coincides_with(points[i])) + if (points[i-1] == points[i]) return true; return false; } @@ -112,7 +105,7 @@ MultiPoint::remove_duplicate_points() { size_t j = 0; for (size_t i = 1; i < points.size(); ++i) { - if (points[j].coincides_with(points[i])) { + if (points[j] == points[i]) { // Just increase index i. } else { ++ j; @@ -146,10 +139,10 @@ bool MultiPoint::first_intersection(const Line& line, Point* intersection) const if (l.intersection(line, &ip)) { if (! found) { found = true; - dmin = ip.distance_to(line.a); + dmin = (line.a - ip).cast().norm(); *intersection = ip; } else { - double d = ip.distance_to(line.a); + double d = (line.a - ip).cast().norm(); if (d < dmin) { dmin = d; *intersection = ip; @@ -160,19 +153,6 @@ bool MultiPoint::first_intersection(const Line& line, Point* intersection) const return found; } -std::string -MultiPoint::dump_perl() const -{ - std::ostringstream ret; - ret << "["; - for (Points::const_iterator p = this->points.begin(); p != this->points.end(); ++p) { - ret << p->dump_perl(); - if (p != this->points.end()-1) ret << ","; - } - ret << "]"; - return ret.str(); -} - //FIXME This is very inefficient in term of memory use. // The recursive algorithm shall run in place, not allocating temporary data in each recursion. Points @@ -185,7 +165,7 @@ MultiPoint::_douglas_peucker(const Points &points, const double tolerance) Line full(points.front(), points.back()); for (Points::const_iterator it = points.begin() + 1; it != points.end(); ++it) { // we use shortest distance, not perpendicular distance - double d = it->distance_to(full); + double d = full.distance_to(*it); if (d > dmax) { index = it - points.begin(); dmax = d; @@ -216,25 +196,22 @@ MultiPoint::_douglas_peucker(const Points &points, const double tolerance) void MultiPoint3::translate(double x, double y) { - for (Point3& p : points) - { - p.translate(x, y); + for (Vec3crd &p : points) { + p(0) += x; + p(1) += y; } } void MultiPoint3::translate(const Point& vector) { - translate(vector.x, vector.y); + this->translate(vector(0), vector(1)); } double MultiPoint3::length() const { - Lines3 lines = this->lines(); double len = 0.0; - for (const Line3& line : lines) - { + for (const Line3& line : this->lines()) len += line.length(); - } return len; } @@ -246,15 +223,11 @@ BoundingBox3 MultiPoint3::bounding_box() const bool MultiPoint3::remove_duplicate_points() { size_t j = 0; - for (size_t i = 1; i < points.size(); ++i) - { - if (points[j].coincides_with(points[i])) - { + for (size_t i = 1; i < points.size(); ++i) { + if (points[j] == points[i]) { // Just increase index i. - } - else - { - ++j; + } else { + ++ j; if (j < i) points[j] = points[i]; } @@ -281,19 +254,19 @@ BoundingBox get_extents_rotated(const Points &points, double angle) double s = sin(angle); double c = cos(angle); Points::const_iterator it = points.begin(); - double cur_x = (double)it->x; - double cur_y = (double)it->y; - bbox.min.x = bbox.max.x = (coord_t)round(c * cur_x - s * cur_y); - bbox.min.y = bbox.max.y = (coord_t)round(c * cur_y + s * cur_x); + double cur_x = (double)(*it)(0); + double cur_y = (double)(*it)(1); + bbox.min(0) = bbox.max(0) = (coord_t)round(c * cur_x - s * cur_y); + bbox.min(1) = bbox.max(1) = (coord_t)round(c * cur_y + s * cur_x); for (++it; it != points.end(); ++it) { - double cur_x = (double)it->x; - double cur_y = (double)it->y; + double cur_x = (double)(*it)(0); + double cur_y = (double)(*it)(1); coord_t x = (coord_t)round(c * cur_x - s * cur_y); coord_t y = (coord_t)round(c * cur_y + s * cur_x); - bbox.min.x = std::min(x, bbox.min.x); - bbox.min.y = std::min(y, bbox.min.y); - bbox.max.x = std::max(x, bbox.max.x); - bbox.max.y = std::max(y, bbox.max.y); + bbox.min(0) = std::min(x, bbox.min(0)); + bbox.min(1) = std::min(y, bbox.min(1)); + bbox.max(0) = std::max(x, bbox.max(0)); + bbox.max(1) = std::max(y, bbox.max(1)); } bbox.defined = true; } diff --git a/xs/src/libslic3r/MultiPoint.hpp b/xs/src/libslic3r/MultiPoint.hpp index 0970e9a67..1fef4083b 100644 --- a/xs/src/libslic3r/MultiPoint.hpp +++ b/xs/src/libslic3r/MultiPoint.hpp @@ -18,10 +18,11 @@ public: Points points; operator Points() const; - MultiPoint() {}; + MultiPoint() {} MultiPoint(const MultiPoint &other) : points(other.points) {} MultiPoint(MultiPoint &&other) : points(std::move(other.points)) {} - explicit MultiPoint(const Points &_points): points(_points) {} + MultiPoint(std::initializer_list list) : points(list) {} + explicit MultiPoint(const Points &_points) : points(_points) {} MultiPoint& operator=(const MultiPoint &other) { points = other.points; return *this; } MultiPoint& operator=(MultiPoint &&other) { points = std::move(other.points); return *this; } void scale(double factor); @@ -43,9 +44,9 @@ public: int idx = -1; if (! this->points.empty()) { idx = 0; - double dist_min = this->points.front().distance_to(point); + double dist_min = (point - this->points.front()).cast().norm(); for (int i = 1; i < int(this->points.size()); ++ i) { - double d = this->points[i].distance_to(point); + double d = (this->points[i] - point).cast().norm(); if (d < dist_min) { dist_min = d; idx = i; @@ -75,7 +76,6 @@ public: bool intersection(const Line& line, Point* intersection) const; bool first_intersection(const Line& line, Point* intersection) const; - std::string dump_perl() const; static Points _douglas_peucker(const Points &points, const double tolerance); }; @@ -85,7 +85,7 @@ class MultiPoint3 public: Points3 points; - void append(const Point3& point) { this->points.push_back(point); } + void append(const Vec3crd& point) { this->points.push_back(point); } void translate(double x, double y); void translate(const Point& vector); diff --git a/xs/src/libslic3r/PerimeterGenerator.cpp b/xs/src/libslic3r/PerimeterGenerator.cpp index 1d2e6248f..de8aeeb2a 100644 --- a/xs/src/libslic3r/PerimeterGenerator.cpp +++ b/xs/src/libslic3r/PerimeterGenerator.cpp @@ -243,7 +243,7 @@ void PerimeterGenerator::process() perimeter_spacing / 2; // only apply infill overlap if we actually have one perimeter if (inset > 0) - inset -= scale_(this->config->get_abs_value("infill_overlap", unscale(inset + solid_infill_spacing / 2))); + inset -= scale_(this->config->get_abs_value("infill_overlap", unscale(inset + solid_infill_spacing / 2))); // simplify infill contours according to resolution Polygons pp; for (ExPolygon &ex : last) @@ -366,99 +366,103 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops( return entities; } -ExtrusionEntityCollection PerimeterGenerator::_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow flow) const +static inline ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_polyline, ExtrusionRole role, Flow &flow, const float tolerance) { - // this value determines granularity of adaptive width, as G-code does not allow - // variable extrusion within a single move; this value shall only affect the amount - // of segments, and any pruning shall be performed before we apply this tolerance - const double tolerance = scale_(0.05); + ExtrusionPaths paths; + ExtrusionPath path(role); + ThickLines lines = thick_polyline.thicklines(); - ExtrusionEntityCollection coll; - for (const ThickPolyline &p : polylines) { - ExtrusionPaths paths; - ExtrusionPath path(role); - ThickLines lines = p.thicklines(); + for (int i = 0; i < (int)lines.size(); ++i) { + const ThickLine& line = lines[i]; - for (int i = 0; i < (int)lines.size(); ++i) { - const ThickLine& line = lines[i]; - - const coordf_t line_len = line.length(); - if (line_len < SCALED_EPSILON) continue; - - double thickness_delta = fabs(line.a_width - line.b_width); - if (thickness_delta > tolerance) { - const unsigned short segments = ceil(thickness_delta / tolerance); - const coordf_t seg_len = line_len / segments; - Points pp; - std::vector width; - { - pp.push_back(line.a); - width.push_back(line.a_width); - for (size_t j = 1; j < segments; ++j) { - pp.push_back(line.point_at(j*seg_len)); - - coordf_t w = line.a_width + (j*seg_len) * (line.b_width-line.a_width) / line_len; - width.push_back(w); - width.push_back(w); - } - pp.push_back(line.b); - width.push_back(line.b_width); + const coordf_t line_len = line.length(); + if (line_len < SCALED_EPSILON) continue; + + double thickness_delta = fabs(line.a_width - line.b_width); + if (thickness_delta > tolerance) { + const unsigned short segments = ceil(thickness_delta / tolerance); + const coordf_t seg_len = line_len / segments; + Points pp; + std::vector width; + { + pp.push_back(line.a); + width.push_back(line.a_width); + for (size_t j = 1; j < segments; ++j) { + pp.push_back((line.a.cast() + (line.b - line.a).cast().normalized() * (j * seg_len)).cast()); - assert(pp.size() == segments + 1); - assert(width.size() == segments*2); + coordf_t w = line.a_width + (j*seg_len) * (line.b_width-line.a_width) / line_len; + width.push_back(w); + width.push_back(w); } + pp.push_back(line.b); + width.push_back(line.b_width); - // delete this line and insert new ones - lines.erase(lines.begin() + i); - for (size_t j = 0; j < segments; ++j) { - ThickLine new_line(pp[j], pp[j+1]); - new_line.a_width = width[2*j]; - new_line.b_width = width[2*j+1]; - lines.insert(lines.begin() + i + j, new_line); - } - - -- i; - continue; + assert(pp.size() == segments + 1); + assert(width.size() == segments*2); } - const double w = fmax(line.a_width, line.b_width); - if (path.polyline.points.empty()) { - path.polyline.append(line.a); - path.polyline.append(line.b); - // Convert from spacing to extrusion width based on the extrusion model - // of a square extrusion ended with semi circles. - flow.width = unscale(w) + flow.height * (1. - 0.25 * PI); - #ifdef SLIC3R_DEBUG - printf(" filling %f gap\n", flow.width); - #endif - path.mm3_per_mm = flow.mm3_per_mm(); - path.width = flow.width; - path.height = flow.height; - } else { - thickness_delta = fabs(scale_(flow.width) - w); - if (thickness_delta <= tolerance) { - // the width difference between this line and the current flow width is - // within the accepted tolerance - path.polyline.append(line.b); - } else { - // we need to initialize a new line - paths.emplace_back(std::move(path)); - path = ExtrusionPath(role); - -- i; - } + // delete this line and insert new ones + lines.erase(lines.begin() + i); + for (size_t j = 0; j < segments; ++j) { + ThickLine new_line(pp[j], pp[j+1]); + new_line.a_width = width[2*j]; + new_line.b_width = width[2*j+1]; + lines.insert(lines.begin() + i + j, new_line); } + + -- i; + continue; } - if (path.polyline.is_valid()) - paths.emplace_back(std::move(path)); - // Append paths to collection. - if (! paths.empty()) { - if (paths.front().first_point().coincides_with(paths.back().last_point())) - coll.append(ExtrusionLoop(paths)); - else - coll.append(paths); + + const double w = fmax(line.a_width, line.b_width); + if (path.polyline.points.empty()) { + path.polyline.append(line.a); + path.polyline.append(line.b); + // Convert from spacing to extrusion width based on the extrusion model + // of a square extrusion ended with semi circles. + flow.width = unscale(w) + flow.height * (1. - 0.25 * PI); + #ifdef SLIC3R_DEBUG + printf(" filling %f gap\n", flow.width); + #endif + path.mm3_per_mm = flow.mm3_per_mm(); + path.width = flow.width; + path.height = flow.height; + } else { + thickness_delta = fabs(scale_(flow.width) - w); + if (thickness_delta <= tolerance) { + // the width difference between this line and the current flow width is + // within the accepted tolerance + path.polyline.append(line.b); + } else { + // we need to initialize a new line + paths.emplace_back(std::move(path)); + path = ExtrusionPath(role); + -- i; + } + } + } + if (path.polyline.is_valid()) + paths.emplace_back(std::move(path)); + return paths; +} + +ExtrusionEntityCollection PerimeterGenerator::_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow flow) const +{ + // This value determines granularity of adaptive width, as G-code does not allow + // variable extrusion within a single move; this value shall only affect the amount + // of segments, and any pruning shall be performed before we apply this tolerance. + ExtrusionEntityCollection coll; + const double tolerance = scale_(0.05); + for (const ThickPolyline &p : polylines) { + ExtrusionPaths paths = thick_polyline_to_extrusion_paths(p, role, flow, tolerance); + // Append paths to collection. + if (! paths.empty()) { + if (paths.front().first_point() == paths.back().last_point()) + coll.append(ExtrusionLoop(std::move(paths))); + else + coll.append(std::move(paths)); } } - return coll; } diff --git a/xs/src/libslic3r/PlaceholderParser.cpp b/xs/src/libslic3r/PlaceholderParser.cpp index 80740b20d..1cfd51141 100644 --- a/xs/src/libslic3r/PlaceholderParser.cpp +++ b/xs/src/libslic3r/PlaceholderParser.cpp @@ -693,7 +693,7 @@ namespace client case coInts: output.set_i(static_cast(opt.opt)->values[idx]); break; case coStrings: output.set_s(static_cast(opt.opt)->values[idx]); break; case coPercents: output.set_d(static_cast(opt.opt)->values[idx]); break; - case coPoints: output.set_s(static_cast(opt.opt)->values[idx].dump_perl()); break; + case coPoints: output.set_s(to_string(static_cast(opt.opt)->values[idx])); break; case coBools: output.set_b(static_cast(opt.opt)->values[idx] != 0); break; default: ctx->throw_exception("Unknown vector variable type", opt.it_range); diff --git a/xs/src/libslic3r/Point.cpp b/xs/src/libslic3r/Point.cpp index 2abcd26af..ec6c28fe8 100644 --- a/xs/src/libslic3r/Point.cpp +++ b/xs/src/libslic3r/Point.cpp @@ -3,84 +3,32 @@ #include "MultiPoint.hpp" #include "Int128.hpp" #include -#include namespace Slic3r { -Point::Point(double x, double y) +void Point::rotate(double angle) { - this->x = lrint(x); - this->y = lrint(y); + double cur_x = (double)(*this)(0); + double cur_y = (double)(*this)(1); + double s = ::sin(angle); + double c = ::cos(angle); + (*this)(0) = (coord_t)round(c * cur_x - s * cur_y); + (*this)(1) = (coord_t)round(c * cur_y + s * cur_x); } -std::string -Point::wkt() const +void Point::rotate(double angle, const Point ¢er) { - std::ostringstream ss; - ss << "POINT(" << this->x << " " << this->y << ")"; - return ss.str(); + double cur_x = (double)(*this)(0); + double cur_y = (double)(*this)(1); + double s = ::sin(angle); + double c = ::cos(angle); + double dx = cur_x - (double)center(0); + double dy = cur_y - (double)center(1); + (*this)(0) = (coord_t)round( (double)center(0) + c * dx - s * dy ); + (*this)(1) = (coord_t)round( (double)center(1) + c * dy + s * dx ); } -std::string -Point::dump_perl() const -{ - std::ostringstream ss; - ss << "[" << this->x << "," << this->y << "]"; - return ss.str(); -} - -void -Point::scale(double factor) -{ - this->x *= factor; - this->y *= factor; -} - -void -Point::translate(double x, double y) -{ - this->x += x; - this->y += y; -} - -void -Point::translate(const Vector &vector) -{ - this->translate(vector.x, vector.y); -} - -void -Point::rotate(double angle) -{ - double cur_x = (double)this->x; - double cur_y = (double)this->y; - double s = sin(angle); - double c = cos(angle); - this->x = (coord_t)round(c * cur_x - s * cur_y); - this->y = (coord_t)round(c * cur_y + s * cur_x); -} - -void -Point::rotate(double angle, const Point ¢er) -{ - double cur_x = (double)this->x; - double cur_y = (double)this->y; - double s = sin(angle); - double c = cos(angle); - double dx = cur_x - (double)center.x; - double dy = cur_y - (double)center.y; - this->x = (coord_t)round( (double)center.x + c * dx - s * dy ); - this->y = (coord_t)round( (double)center.y + c * dy + s * dx ); -} - -bool -Point::coincides_with_epsilon(const Point &point) const -{ - return std::abs(this->x - point.x) < SCALED_EPSILON && std::abs(this->y - point.y) < SCALED_EPSILON; -} - -int -Point::nearest_point_index(const Points &points) const +int Point::nearest_point_index(const Points &points) const { PointConstPtrs p; p.reserve(points.size()); @@ -97,12 +45,12 @@ int Point::nearest_point_index(const PointConstPtrs &points) const for (PointConstPtrs::const_iterator it = points.begin(); it != points.end(); ++it) { /* If the X distance of the candidate is > than the total distance of the best previous candidate, we know we don't want it */ - double d = sqr(this->x - (*it)->x); + double d = sqr((*this)(0) - (*it)->x()); if (distance != -1 && d > distance) continue; /* If the Y distance of the candidate is > than the total distance of the best previous candidate, we know we don't want it */ - d += sqr(this->y - (*it)->y); + d += sqr((*this)(1) - (*it)->y()); if (distance != -1 && d > distance) continue; idx = it - points.begin(); @@ -114,8 +62,7 @@ int Point::nearest_point_index(const PointConstPtrs &points) const return idx; } -int -Point::nearest_point_index(const PointPtrs &points) const +int Point::nearest_point_index(const PointPtrs &points) const { PointConstPtrs p; p.reserve(points.size()); @@ -124,8 +71,7 @@ Point::nearest_point_index(const PointPtrs &points) const return this->nearest_point_index(p); } -bool -Point::nearest_point(const Points &points, Point* point) const +bool Point::nearest_point(const Points &points, Point* point) const { int idx = this->nearest_point_index(points); if (idx == -1) return false; @@ -133,40 +79,6 @@ Point::nearest_point(const Points &points, Point* point) const return true; } -/* distance to the closest point of line */ -double -Point::distance_to(const Line &line) const -{ - const double dx = line.b.x - line.a.x; - const double dy = line.b.y - line.a.y; - - const double l2 = dx*dx + dy*dy; // avoid a sqrt - if (l2 == 0.0) return this->distance_to(line.a); // line.a == line.b case - - // Consider the line extending the segment, parameterized as line.a + t (line.b - line.a). - // We find projection of this point onto the line. - // It falls where t = [(this-line.a) . (line.b-line.a)] / |line.b-line.a|^2 - const double t = ((this->x - line.a.x) * dx + (this->y - line.a.y) * dy) / l2; - if (t < 0.0) return this->distance_to(line.a); // beyond the 'a' end of the segment - else if (t > 1.0) return this->distance_to(line.b); // beyond the 'b' end of the segment - Point projection( - line.a.x + t * dx, - line.a.y + t * dy - ); - return this->distance_to(projection); -} - -double -Point::perp_distance_to(const Line &line) const -{ - if (line.a.coincides_with(line.b)) return this->distance_to(line.a); - - double n = (double)(line.b.x - line.a.x) * (double)(line.a.y - this->y) - - (double)(line.a.x - this->x) * (double)(line.b.y - line.a.y); - - return std::abs(n) / line.length(); -} - /* Three points are a counter-clockwise turn if ccw > 0, clockwise if * ccw < 0, and collinear if ccw = 0 because ccw is a determinant that * gives the signed area of the triangle formed by p1, p2 and this point. @@ -174,51 +86,46 @@ Point::perp_distance_to(const Line &line) const * z-component of their 3D cross product. * We return double because it must be big enough to hold 2*max(|coordinate|)^2 */ -double -Point::ccw(const Point &p1, const Point &p2) const +double Point::ccw(const Point &p1, const Point &p2) const { - return (double)(p2.x - p1.x)*(double)(this->y - p1.y) - (double)(p2.y - p1.y)*(double)(this->x - p1.x); + return (double)(p2(0) - p1(0))*(double)((*this)(1) - p1(1)) - (double)(p2(1) - p1(1))*(double)((*this)(0) - p1(0)); } -double -Point::ccw(const Line &line) const +double Point::ccw(const Line &line) const { return this->ccw(line.a, line.b); } // returns the CCW angle between this-p1 and this-p2 // i.e. this assumes a CCW rotation from p1 to p2 around this -double -Point::ccw_angle(const Point &p1, const Point &p2) const +double Point::ccw_angle(const Point &p1, const Point &p2) const { - double angle = atan2(p1.x - this->x, p1.y - this->y) - - atan2(p2.x - this->x, p2.y - this->y); + double angle = atan2(p1(0) - (*this)(0), p1(1) - (*this)(1)) + - atan2(p2(0) - (*this)(0), p2(1) - (*this)(1)); // we only want to return only positive angles return angle <= 0 ? angle + 2*PI : angle; } -Point -Point::projection_onto(const MultiPoint &poly) const +Point Point::projection_onto(const MultiPoint &poly) const { Point running_projection = poly.first_point(); - double running_min = this->distance_to(running_projection); + double running_min = (running_projection - *this).cast().norm(); Lines lines = poly.lines(); for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) { Point point_temp = this->projection_onto(*line); - if (this->distance_to(point_temp) < running_min) { + if ((point_temp - *this).cast().norm() < running_min) { running_projection = point_temp; - running_min = this->distance_to(running_projection); + running_min = (running_projection - *this).cast().norm(); } } return running_projection; } -Point -Point::projection_onto(const Line &line) const +Point Point::projection_onto(const Line &line) const { - if (line.a.coincides_with(line.b)) return line.a; + if (line.a == line.b) return line.a; /* (Ported from VisiLibity by Karl J. Obermeyer) @@ -229,165 +136,35 @@ Point::projection_onto(const Line &line) const If theta is outside the interval [0,1], then one of the Line_Segment's endpoints must be closest to calling Point. */ - double lx = (double)(line.b.x - line.a.x); - double ly = (double)(line.b.y - line.a.y); - double theta = ( (double)(line.b.x - this->x)*lx + (double)(line.b.y- this->y)*ly ) + double lx = (double)(line.b(0) - line.a(0)); + double ly = (double)(line.b(1) - line.a(1)); + double theta = ( (double)(line.b(0) - (*this)(0))*lx + (double)(line.b(1)- (*this)(1))*ly ) / ( sqr(lx) + sqr(ly) ); if (0.0 <= theta && theta <= 1.0) - return theta * line.a + (1.0-theta) * line.b; + return (theta * line.a.cast() + (1.0-theta) * line.b.cast()).cast(); // Else pick closest endpoint. - if (this->distance_to(line.a) < this->distance_to(line.b)) { - return line.a; - } else { - return line.b; - } + return ((line.a - *this).cast().squaredNorm() < (line.b - *this).cast().squaredNorm()) ? line.a : line.b; } -Point -Point::negative() const +std::ostream& operator<<(std::ostream &stm, const Vec2d &pointf) { - return Point(-this->x, -this->y); -} - -Vector -Point::vector_to(const Point &point) const -{ - return Vector(point.x - this->x, point.y - this->y); -} - -std::ostream& -operator<<(std::ostream &stm, const Pointf &pointf) -{ - return stm << pointf.x << "," << pointf.y; -} - -std::string -Pointf::wkt() const -{ - std::ostringstream ss; - ss << "POINT(" << this->x << " " << this->y << ")"; - return ss.str(); -} - -std::string -Pointf::dump_perl() const -{ - std::ostringstream ss; - ss << "[" << this->x << "," << this->y << "]"; - return ss.str(); -} - -void -Pointf::scale(double factor) -{ - this->x *= factor; - this->y *= factor; -} - -void -Pointf::translate(double x, double y) -{ - this->x += x; - this->y += y; -} - -void -Pointf::translate(const Vectorf &vector) -{ - this->translate(vector.x, vector.y); -} - -void -Pointf::rotate(double angle) -{ - double cur_x = this->x; - double cur_y = this->y; - double s = sin(angle); - double c = cos(angle); - this->x = c * cur_x - s * cur_y; - this->y = c * cur_y + s * cur_x; -} - -void -Pointf::rotate(double angle, const Pointf ¢er) -{ - double cur_x = this->x; - double cur_y = this->y; - double s = sin(angle); - double c = cos(angle); - double dx = cur_x - center.x; - double dy = cur_y - center.y; - this->x = center.x + c * dx - s * dy; - this->y = center.y + c * dy + s * dx; -} - -Pointf -Pointf::negative() const -{ - return Pointf(-this->x, -this->y); -} - -Vectorf -Pointf::vector_to(const Pointf &point) const -{ - return Vectorf(point.x - this->x, point.y - this->y); -} - -void -Pointf3::scale(double factor) -{ - Pointf::scale(factor); - this->z *= factor; -} - -void -Pointf3::translate(const Vectorf3 &vector) -{ - this->translate(vector.x, vector.y, vector.z); -} - -void -Pointf3::translate(double x, double y, double z) -{ - Pointf::translate(x, y); - this->z += z; -} - -double -Pointf3::distance_to(const Pointf3 &point) const -{ - double dx = ((double)point.x - this->x); - double dy = ((double)point.y - this->y); - double dz = ((double)point.z - this->z); - return sqrt(dx*dx + dy*dy + dz*dz); -} - -Pointf3 -Pointf3::negative() const -{ - return Pointf3(-this->x, -this->y, -this->z); -} - -Vectorf3 -Pointf3::vector_to(const Pointf3 &point) const -{ - return Vectorf3(point.x - this->x, point.y - this->y, point.z - this->z); + return stm << pointf(0) << "," << pointf(1); } namespace int128 { -int orient(const Point &p1, const Point &p2, const Point &p3) +int orient(const Vec2crd &p1, const Vec2crd &p2, const Vec2crd &p3) { Slic3r::Vector v1(p2 - p1); Slic3r::Vector v2(p3 - p1); - return Int128::sign_determinant_2x2_filtered(v1.x, v1.y, v2.x, v2.y); + return Int128::sign_determinant_2x2_filtered(v1(0), v1(1), v2(0), v2(1)); } -int cross(const Point &v1, const Point &v2) +int cross(const Vec2crd &v1, const Vec2crd &v2) { - return Int128::sign_determinant_2x2_filtered(v1.x, v1.y, v2.x, v2.y); + return Int128::sign_determinant_2x2_filtered(v1(0), v1(1), v2(0), v2(1)); } } diff --git a/xs/src/libslic3r/Point.hpp b/xs/src/libslic3r/Point.hpp index 8aee65a93..b969b9839 100644 --- a/xs/src/libslic3r/Point.hpp +++ b/xs/src/libslic3r/Point.hpp @@ -2,100 +2,128 @@ #define slic3r_Point_hpp_ #include "libslic3r.h" +#include #include -#include +#include #include #include #include +#include + namespace Slic3r { class Line; -class Linef; class MultiPoint; class Point; -class Point3; -class Pointf; -class Pointf3; typedef Point Vector; -typedef Point3 Vector3; -typedef Pointf Vectorf; -typedef Pointf3 Vectorf3; -typedef std::vector Points; -typedef std::vector PointPtrs; -typedef std::vector PointConstPtrs; -typedef std::vector Points3; -typedef std::vector Pointfs; -typedef std::vector Pointf3s; -class Point +// Eigen types, to replace the Slic3r's own types in the future. +// Vector types with a fixed point coordinate base type. +typedef Eigen::Matrix Vec2crd; +typedef Eigen::Matrix Vec3crd; +typedef Eigen::Matrix Vec2i64; +typedef Eigen::Matrix Vec3i64; + +// Vector types with a double coordinate base type. +typedef Eigen::Matrix Vec2f; +typedef Eigen::Matrix Vec3f; +typedef Eigen::Matrix Vec2d; +typedef Eigen::Matrix Vec3d; + +typedef std::vector Points; +typedef std::vector PointPtrs; +typedef std::vector PointConstPtrs; +typedef std::vector Points3; +typedef std::vector Pointfs; +typedef std::vector Pointf3s; + +typedef Eigen::Transform Transform2f; +typedef Eigen::Transform Transform2d; +typedef Eigen::Transform Transform3f; +typedef Eigen::Transform Transform3d; + +inline bool operator<(const Vec2d &lhs, const Vec2d &rhs) { return lhs(0) < rhs(0) || (lhs(0) == rhs(0) && lhs(1) < rhs(1)); } + +inline int64_t cross2(const Vec2i64 &v1, const Vec2i64 &v2) { return v1(0) * v2(1) - v1(1) * v2(0); } +inline coord_t cross2(const Vec2crd &v1, const Vec2crd &v2) { return v1(0) * v2(1) - v1(1) * v2(0); } +inline float cross2(const Vec2f &v1, const Vec2f &v2) { return v1(0) * v2(1) - v1(1) * v2(0); } +inline double cross2(const Vec2d &v1, const Vec2d &v2) { return v1(0) * v2(1) - v1(1) * v2(0); } + +inline Vec2crd to_2d(const Vec3crd &pt3) { return Vec2crd(pt3(0), pt3(1)); } +inline Vec2i64 to_2d(const Vec3i64 &pt3) { return Vec2i64(pt3(0), pt3(1)); } +inline Vec2f to_2d(const Vec3f &pt3) { return Vec2f (pt3(0), pt3(1)); } +inline Vec2d to_2d(const Vec3d &pt3) { return Vec2d (pt3(0), pt3(1)); } + +inline Vec2d unscale(coord_t x, coord_t y) { return Vec2d(unscale(x), unscale(y)); } +inline Vec2d unscale(const Vec2crd &pt) { return Vec2d(unscale(pt(0)), unscale(pt(1))); } +inline Vec2d unscale(const Vec2d &pt) { return Vec2d(unscale(pt(0)), unscale(pt(1))); } +inline Vec3d unscale(coord_t x, coord_t y, coord_t z) { return Vec3d(unscale(x), unscale(y), unscale(z)); } +inline Vec3d unscale(const Vec3crd &pt) { return Vec3d(unscale(pt(0)), unscale(pt(1)), unscale(pt(2))); } +inline Vec3d unscale(const Vec3d &pt) { return Vec3d(unscale(pt(0)), unscale(pt(1)), unscale(pt(2))); } + +inline std::string to_string(const Vec2crd &pt) { return std::string("[") + std::to_string(pt(0)) + ", " + std::to_string(pt(1)) + "]"; } +inline std::string to_string(const Vec2d &pt) { return std::string("[") + std::to_string(pt(0)) + ", " + std::to_string(pt(1)) + "]"; } +inline std::string to_string(const Vec3crd &pt) { return std::string("[") + std::to_string(pt(0)) + ", " + std::to_string(pt(1)) + ", " + std::to_string(pt(2)) + "]"; } +inline std::string to_string(const Vec3d &pt) { return std::string("[") + std::to_string(pt(0)) + ", " + std::to_string(pt(1)) + ", " + std::to_string(pt(2)) + "]"; } + +class Point : public Vec2crd { public: typedef coord_t coord_type; - coord_t x; - coord_t y; - Point(coord_t _x = 0, coord_t _y = 0): x(_x), y(_y) {}; - Point(int64_t _x, int64_t _y): x(coord_t(_x)), y(coord_t(_y)) {}; // for Clipper - Point(double x, double y); + + Point() : Vec2crd() { (*this)(0) = 0; (*this)(1) = 0; } + Point(coord_t x, coord_t y) { (*this)(0) = x; (*this)(1) = y; } + Point(int64_t x, int64_t y) { (*this)(0) = coord_t(x); (*this)(1) = coord_t(y); } // for Clipper + Point(double x, double y) { (*this)(0) = coord_t(lrint(x)); (*this)(1) = coord_t(lrint(y)); } + Point(const Point &rhs) { *this = rhs; } + // This constructor allows you to construct Point from Eigen expressions + template + Point(const Eigen::MatrixBase &other) : Vec2crd(other) {} static Point new_scale(coordf_t x, coordf_t y) { return Point(coord_t(scale_(x)), coord_t(scale_(y))); } - bool operator==(const Point& rhs) const { return this->x == rhs.x && this->y == rhs.y; } - bool operator!=(const Point& rhs) const { return ! (*this == rhs); } - bool operator<(const Point& rhs) const { return this->x < rhs.x || (this->x == rhs.x && this->y < rhs.y); } + // This method allows you to assign Eigen expressions to MyVectorType + template + Point& operator=(const Eigen::MatrixBase &other) + { + this->Vec2crd::operator=(other); + return *this; + } - Point& operator+=(const Point& rhs) { this->x += rhs.x; this->y += rhs.y; return *this; } - Point& operator-=(const Point& rhs) { this->x -= rhs.x; this->y -= rhs.y; return *this; } - Point& operator*=(const coord_t& rhs) { this->x *= rhs; this->y *= rhs; return *this; } + bool operator< (const Point& rhs) const { return (*this)(0) < rhs(0) || ((*this)(0) == rhs(0) && (*this)(1) < rhs(1)); } - std::string wkt() const; - std::string dump_perl() const; - void scale(double factor); - void translate(double x, double y); - void translate(const Vector &vector); - void rotate(double angle); - void rotate(double angle, const Point ¢er); - Point rotated(double angle) const { Point res(*this); res.rotate(angle); return res; } - Point rotated(double angle, const Point ¢er) const { Point res(*this); res.rotate(angle, center); return res; } - bool coincides_with(const Point &point) const { return this->x == point.x && this->y == point.y; } - bool coincides_with_epsilon(const Point &point) const; - int nearest_point_index(const Points &points) const; - int nearest_point_index(const PointConstPtrs &points) const; - int nearest_point_index(const PointPtrs &points) const; - bool nearest_point(const Points &points, Point* point) const; - double distance_to(const Point &point) const { return sqrt(distance_to_sq(point)); } - double distance_to_sq(const Point &point) const { double dx = double(point.x - this->x); double dy = double(point.y - this->y); return dx*dx + dy*dy; } - double distance_to(const Line &line) const; - double perp_distance_to(const Line &line) const; + Point& operator+=(const Point& rhs) { (*this)(0) += rhs(0); (*this)(1) += rhs(1); return *this; } + Point& operator-=(const Point& rhs) { (*this)(0) -= rhs(0); (*this)(1) -= rhs(1); return *this; } + Point& operator*=(const double &rhs) { (*this)(0) *= rhs; (*this)(1) *= rhs; return *this; } + + void rotate(double angle); + void rotate(double angle, const Point ¢er); + Point rotated(double angle) const { Point res(*this); res.rotate(angle); return res; } + Point rotated(double angle, const Point ¢er) const { Point res(*this); res.rotate(angle, center); return res; } + int nearest_point_index(const Points &points) const; + int nearest_point_index(const PointConstPtrs &points) const; + int nearest_point_index(const PointPtrs &points) const; + bool nearest_point(const Points &points, Point* point) const; double ccw(const Point &p1, const Point &p2) const; double ccw(const Line &line) const; double ccw_angle(const Point &p1, const Point &p2) const; - Point projection_onto(const MultiPoint &poly) const; - Point projection_onto(const Line &line) const; - Point negative() const; - Vector vector_to(const Point &point) const; + Point projection_onto(const MultiPoint &poly) const; + Point projection_onto(const Line &line) const; }; -inline Point operator+(const Point& point1, const Point& point2) { return Point(point1.x + point2.x, point1.y + point2.y); } -inline Point operator-(const Point& point1, const Point& point2) { return Point(point1.x - point2.x, point1.y - point2.y); } -inline Point operator*(double scalar, const Point& point2) { return Point(scalar * point2.x, scalar * point2.y); } -inline int64_t cross(const Point &v1, const Point &v2) { return int64_t(v1.x) * int64_t(v2.y) - int64_t(v1.y) * int64_t(v2.x); } -inline int64_t dot(const Point &v1, const Point &v2) { return int64_t(v1.x) * int64_t(v2.x) + int64_t(v1.y) * int64_t(v2.y); } - namespace int128 { - -// Exact orientation predicate, -// returns +1: CCW, 0: collinear, -1: CW. -int orient(const Point &p1, const Point &p2, const Point &p3); - -// Exact orientation predicate, -// returns +1: CCW, 0: collinear, -1: CW. -int cross(const Point &v1, const Slic3r::Point &v2); + // Exact orientation predicate, + // returns +1: CCW, 0: collinear, -1: CW. + int orient(const Vec2crd &p1, const Vec2crd &p2, const Vec2crd &p3); + // Exact orientation predicate, + // returns +1: CCW, 0: collinear, -1: CW. + int cross(const Vec2crd &v1, const Vec2crd &v2); } // To be used by std::unordered_map, std::unordered_multimap and friends. struct PointHash { - size_t operator()(const Point &pt) const { - return std::hash()(pt.x) ^ std::hash()(pt.y); + size_t operator()(const Vec2crd &pt) const { + return std::hash()(pt(0)) ^ std::hash()(pt(1)); } }; @@ -139,36 +167,36 @@ public: } void insert(const ValueType &value) { - const Point *pt = m_point_accessor(value); + const Vec2crd *pt = m_point_accessor(value); if (pt != nullptr) - m_map.emplace(std::make_pair(Point(pt->x>>m_grid_log2, pt->y>>m_grid_log2), value)); + m_map.emplace(std::make_pair(Vec2crd(pt->x()>>m_grid_log2, pt->y()>>m_grid_log2), value)); } void insert(ValueType &&value) { - const Point *pt = m_point_accessor(value); + const Vec2crd *pt = m_point_accessor(value); if (pt != nullptr) - m_map.emplace(std::make_pair(Point(pt->x>>m_grid_log2, pt->y>>m_grid_log2), std::move(value))); + m_map.emplace(std::make_pair(Vec2crd(pt->x()>>m_grid_log2, pt->y()>>m_grid_log2), std::move(value))); } // Return a pair of - std::pair find(const Point &pt) { + std::pair find(const Vec2crd &pt) { // Iterate over 4 closest grid cells around pt, // find the closest start point inside these cells to pt. const ValueType *value_min = nullptr; double dist_min = std::numeric_limits::max(); // Round pt to a closest grid_cell corner. - Point grid_corner((pt.x+(m_grid_resolution>>1))>>m_grid_log2, (pt.y+(m_grid_resolution>>1))>>m_grid_log2); + Vec2crd grid_corner((pt(0)+(m_grid_resolution>>1))>>m_grid_log2, (pt(1)+(m_grid_resolution>>1))>>m_grid_log2); // For four neighbors of grid_corner: for (coord_t neighbor_y = -1; neighbor_y < 1; ++ neighbor_y) { for (coord_t neighbor_x = -1; neighbor_x < 1; ++ neighbor_x) { // Range of fragment starts around grid_corner, close to pt. - auto range = m_map.equal_range(Point(grid_corner.x + neighbor_x, grid_corner.y + neighbor_y)); + auto range = m_map.equal_range(Vec2crd(grid_corner(0) + neighbor_x, grid_corner(1) + neighbor_y)); // Find the map entry closest to pt. for (auto it = range.first; it != range.second; ++it) { const ValueType &value = it->second; - const Point *pt2 = m_point_accessor(value); + const Vec2crd *pt2 = m_point_accessor(value); if (pt2 != nullptr) { - const double d2 = pt.distance_to_sq(*pt2); + const double d2 = (pt - *pt2).squaredNorm(); if (d2 < dist_min) { dist_min = d2; value_min = &value; @@ -183,7 +211,7 @@ public: } private: - typedef typename std::unordered_multimap map_type; + typedef typename std::unordered_multimap map_type; PointAccessor m_point_accessor; map_type m_map; coord_t m_search_radius; @@ -191,113 +219,7 @@ private: coord_t m_grid_log2; }; -class Point3 : public Point -{ -public: - coord_t z; - explicit Point3(coord_t _x = 0, coord_t _y = 0, coord_t _z = 0): Point(_x, _y), z(_z) {}; - static Point3 new_scale(coordf_t x, coordf_t y, coordf_t z) { return Point3(coord_t(scale_(x)), coord_t(scale_(y)), coord_t(scale_(z))); } - bool operator==(const Point3 &rhs) const { return this->x == rhs.x && this->y == rhs.y && this->z == rhs.z; } - bool operator!=(const Point3 &rhs) const { return ! (*this == rhs); } - bool coincides_with(const Point3& rhs) const { return this->x == rhs.x && this->y == rhs.y && this->z == rhs.z; } -private: - // Hide the following inherited methods: - bool operator==(const Point &rhs) const; - bool operator!=(const Point &rhs) const; -}; - -std::ostream& operator<<(std::ostream &stm, const Pointf &pointf); - -class Pointf -{ -public: - typedef coordf_t coord_type; - coordf_t x; - coordf_t y; - explicit Pointf(coordf_t _x = 0, coordf_t _y = 0): x(_x), y(_y) {}; - static Pointf new_unscale(coord_t x, coord_t y) { - return Pointf(unscale(x), unscale(y)); - }; - static Pointf new_unscale(const Point &p) { - return Pointf(unscale(p.x), unscale(p.y)); - }; - std::string wkt() const; - std::string dump_perl() const; - void scale(double factor); - void translate(double x, double y); - void translate(const Vectorf &vector); - void rotate(double angle); - void rotate(double angle, const Pointf ¢er); - Pointf negative() const; - Vectorf vector_to(const Pointf &point) const; - - Pointf& operator+=(const Pointf& rhs) { this->x += rhs.x; this->y += rhs.y; return *this; } - Pointf& operator-=(const Pointf& rhs) { this->x -= rhs.x; this->y -= rhs.y; return *this; } - Pointf& operator*=(const coordf_t& rhs) { this->x *= rhs; this->y *= rhs; return *this; } - - bool operator==(const Pointf &rhs) const { return this->x == rhs.x && this->y == rhs.y; } - bool operator!=(const Pointf &rhs) const { return ! (*this == rhs); } - bool operator< (const Pointf& rhs) const { return this->x < rhs.x || (this->x == rhs.x && this->y < rhs.y); } -}; - -inline Pointf operator+(const Pointf& point1, const Pointf& point2) { return Pointf(point1.x + point2.x, point1.y + point2.y); } -inline Pointf operator-(const Pointf& point1, const Pointf& point2) { return Pointf(point1.x - point2.x, point1.y - point2.y); } -inline Pointf operator*(double scalar, const Pointf& point2) { return Pointf(scalar * point2.x, scalar * point2.y); } -inline Pointf operator*(const Pointf& point2, double scalar) { return Pointf(scalar * point2.x, scalar * point2.y); } -inline coordf_t cross(const Pointf &v1, const Pointf &v2) { return v1.x * v2.y - v1.y * v2.x; } -inline coordf_t dot(const Pointf &v1, const Pointf &v2) { return v1.x * v2.x + v1.y * v2.y; } -inline coordf_t dot(const Pointf &v) { return v.x * v.x + v.y * v.y; } -inline double length(const Vectorf &v) { return sqrt(dot(v)); } -inline double l2(const Vectorf &v) { return dot(v); } -inline Vectorf normalize(const Vectorf& v) -{ - coordf_t len = ::sqrt(sqr(v.x) + sqr(v.y)); - return (len != 0.0) ? 1.0 / len * v : Vectorf(0.0, 0.0); -} - -class Pointf3 : public Pointf -{ -public: - coordf_t z; - explicit Pointf3(coordf_t _x = 0, coordf_t _y = 0, coordf_t _z = 0): Pointf(_x, _y), z(_z) {}; - static Pointf3 new_unscale(coord_t x, coord_t y, coord_t z) { - return Pointf3(unscale(x), unscale(y), unscale(z)); - }; - static Pointf3 new_unscale(const Point3& p) { return Pointf3(unscale(p.x), unscale(p.y), unscale(p.z)); } - void scale(double factor); - void translate(const Vectorf3 &vector); - void translate(double x, double y, double z); - double distance_to(const Pointf3 &point) const; - Pointf3 negative() const; - Vectorf3 vector_to(const Pointf3 &point) const; - - bool operator==(const Pointf3 &rhs) const { return this->x == rhs.x && this->y == rhs.y && this->z == rhs.z; } - bool operator!=(const Pointf3 &rhs) const { return ! (*this == rhs); } - -private: - // Hide the following inherited methods: - bool operator==(const Pointf &rhs) const; - bool operator!=(const Pointf &rhs) const; -}; - -inline Pointf3 operator+(const Pointf3& p1, const Pointf3& p2) { return Pointf3(p1.x + p2.x, p1.y + p2.y, p1.z + p2.z); } -inline Pointf3 operator-(const Pointf3& p1, const Pointf3& p2) { return Pointf3(p1.x - p2.x, p1.y - p2.y, p1.z - p2.z); } -inline Pointf3 operator-(const Pointf3& p) { return Pointf3(-p.x, -p.y, -p.z); } -inline Pointf3 operator*(double scalar, const Pointf3& p) { return Pointf3(scalar * p.x, scalar * p.y, scalar * p.z); } -inline Pointf3 operator*(const Pointf3& p, double scalar) { return Pointf3(scalar * p.x, scalar * p.y, scalar * p.z); } -inline Pointf3 cross(const Pointf3& v1, const Pointf3& v2) { return Pointf3(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); } -inline coordf_t dot(const Pointf3& v1, const Pointf3& v2) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; } -inline double length(const Vectorf3 &v) { return ::sqrt(sqr(v.x) + sqr(v.y) + sqr(v.z)); } -inline Pointf3 normalize(const Pointf3& v) -{ - coordf_t len = ::sqrt(sqr(v.x) + sqr(v.y) + sqr(v.z)); - return (len != 0.0) ? 1.0 / len * v : Pointf3(0.0, 0.0, 0.0); -} - -template inline TO convert_to(const Point &src) { return TO(typename TO::coord_type(src.x), typename TO::coord_type(src.y)); } -template inline TO convert_to(const Pointf &src) { return TO(typename TO::coord_type(src.x), typename TO::coord_type(src.y)); } -template inline TO convert_to(const Point3 &src) { return TO(typename TO::coord_type(src.x), typename TO::coord_type(src.y), typename TO::coord_type(src.z)); } -template inline TO convert_to(const Pointf3 &src) { return TO(typename TO::coord_type(src.x), typename TO::coord_type(src.y), typename TO::coord_type(src.z)); } +std::ostream& operator<<(std::ostream &stm, const Vec2d &pointf); } // namespace Slic3r @@ -313,7 +235,7 @@ namespace boost { namespace polygon { typedef coord_t coordinate_type; static inline coordinate_type get(const Slic3r::Point& point, orientation_2d orient) { - return (orient == HORIZONTAL) ? point.x : point.y; + return (orient == HORIZONTAL) ? (coordinate_type)point(0) : (coordinate_type)point(1); } }; @@ -322,14 +244,14 @@ namespace boost { namespace polygon { typedef coord_t coordinate_type; static inline void set(Slic3r::Point& point, orientation_2d orient, coord_t value) { if (orient == HORIZONTAL) - point.x = value; + point(0) = value; else - point.y = value; + point(1) = value; } static inline Slic3r::Point construct(coord_t x_value, coord_t y_value) { Slic3r::Point retval; - retval.x = x_value; - retval.y = y_value; + retval(0) = x_value; + retval(1) = y_value; return retval; } }; diff --git a/xs/src/libslic3r/Polygon.cpp b/xs/src/libslic3r/Polygon.cpp index b5fd7e64f..14248d84f 100644 --- a/xs/src/libslic3r/Polygon.cpp +++ b/xs/src/libslic3r/Polygon.cpp @@ -44,11 +44,9 @@ Polyline Polygon::split_at_vertex(const Point &point) const { // find index of point - for (Points::const_iterator it = this->points.begin(); it != this->points.end(); ++it) { - if (it->coincides_with(point)) { - return this->split_at_index(it - this->points.begin()); - } - } + for (const Point &pt : this->points) + if (pt == point) + return this->split_at_index(&pt - &this->points.front()); CONFESS("Point not found"); return Polyline(); } @@ -88,7 +86,7 @@ int64_t Polygon::area2x() const int64_t a = 0; for (size_t i = 0, j = n - 1; i < n; ++i) - a += int64_t(poly[j].x + poly[i].x) * int64_t(poly[j].y - poly[i].y); + a += int64_t(poly[j](0) + poly[i](0)) * int64_t(poly[j](1) - poly[i](1)); j = i; } return -a * 0.5; @@ -103,7 +101,7 @@ double Polygon::area() const double a = 0.; for (size_t i = 0, j = n - 1; i < n; ++i) { - a += ((double)points[j].x + (double)points[i].x) * ((double)points[i].y - (double)points[j].y); + a += ((double)points[j](0) + (double)points[i](0)) * ((double)points[i](1) - (double)points[j](1)); j = i; } return 0.5 * a; @@ -157,17 +155,17 @@ Polygon::contains(const Point &point) const Points::const_iterator i = this->points.begin(); Points::const_iterator j = this->points.end() - 1; for (; i != this->points.end(); j = i++) { - //FIXME this test is not numerically robust. Particularly, it does not handle horizontal segments at y == point.y well. - // Does the ray with y == point.y intersect this line segment? + //FIXME this test is not numerically robust. Particularly, it does not handle horizontal segments at y == point(1) well. + // Does the ray with y == point(1) intersect this line segment? #if 1 - if ( ((i->y > point.y) != (j->y > point.y)) - && ((double)point.x < (double)(j->x - i->x) * (double)(point.y - i->y) / (double)(j->y - i->y) + (double)i->x) ) + if ( (((*i)(1) > point(1)) != ((*j)(1) > point(1))) + && ((double)point(0) < (double)((*j)(0) - (*i)(0)) * (double)(point(1) - (*i)(1)) / (double)((*j)(1) - (*i)(1)) + (double)(*i)(0)) ) result = !result; #else - if ((i->y > point.y) != (j->y > point.y)) { + if (((*i)(1) > point(1)) != ((*j)(1) > point(1))) { // Orientation predicated relative to i-th point. - double orient = (double)(point.x - i->x) * (double)(j->y - i->y) - (double)(point.y - i->y) * (double)(j->x - i->x); - if ((i->y > j->y) ? (orient > 0.) : (orient < 0.)) + double orient = (double)(point(0) - (*i)(0)) * (double)((*j)(1) - (*i)(1)) - (double)(point(1) - (*i)(1)) * (double)((*j)(0) - (*i)(0)); + if (((*i)(1) > (*j)(1)) ? (orient > 0.) : (orient < 0.)) result = !result; } #endif @@ -225,26 +223,13 @@ Polygon::centroid() const Polyline polyline = this->split_at_first_point(); for (Points::const_iterator point = polyline.points.begin(); point != polyline.points.end() - 1; ++point) { - x_temp += (double)( point->x + (point+1)->x ) * ( (double)point->x*(point+1)->y - (double)(point+1)->x*point->y ); - y_temp += (double)( point->y + (point+1)->y ) * ( (double)point->x*(point+1)->y - (double)(point+1)->x*point->y ); + x_temp += (double)( point->x() + (point+1)->x() ) * ( (double)point->x()*(point+1)->y() - (double)(point+1)->x()*point->y() ); + y_temp += (double)( point->y() + (point+1)->y() ) * ( (double)point->x()*(point+1)->y() - (double)(point+1)->x()*point->y() ); } return Point(x_temp/(6*area_temp), y_temp/(6*area_temp)); } -std::string -Polygon::wkt() const -{ - std::ostringstream wkt; - wkt << "POLYGON(("; - for (Points::const_iterator p = this->points.begin(); p != this->points.end(); ++p) { - wkt << p->x << " " << p->y; - if (p != this->points.end()-1) wkt << ","; - } - wkt << "))"; - return wkt.str(); -} - // find all concave vertices (i.e. having an internal angle greater than the supplied angle) // (external = right side, thus we consider ccw orientation) Points @@ -302,24 +287,24 @@ Point Polygon::point_projection(const Point &point) const for (size_t i = 0; i < this->points.size(); ++ i) { const Point &pt0 = this->points[i]; const Point &pt1 = this->points[(i + 1 == this->points.size()) ? 0 : i + 1]; - double d = pt0.distance_to(point); + double d = (point - pt0).cast().norm(); if (d < dmin) { dmin = d; proj = pt0; } - d = pt1.distance_to(point); + d = (point - pt1).cast().norm(); if (d < dmin) { dmin = d; proj = pt1; } - Pointf v1(coordf_t(pt1.x - pt0.x), coordf_t(pt1.y - pt0.y)); - coordf_t div = dot(v1); + Vec2d v1(coordf_t(pt1(0) - pt0(0)), coordf_t(pt1(1) - pt0(1))); + coordf_t div = v1.squaredNorm(); if (div > 0.) { - Pointf v2(coordf_t(point.x - pt0.x), coordf_t(point.y - pt0.y)); - coordf_t t = dot(v1, v2) / div; + Vec2d v2(coordf_t(point(0) - pt0(0)), coordf_t(point(1) - pt0(1))); + coordf_t t = v1.dot(v2) / div; if (t > 0. && t < 1.) { - Point foot(coord_t(floor(coordf_t(pt0.x) + t * v1.x + 0.5)), coord_t(floor(coordf_t(pt0.y) + t * v1.y + 0.5))); - d = foot.distance_to(point); + Point foot(coord_t(floor(coordf_t(pt0(0)) + t * v1(0) + 0.5)), coord_t(floor(coordf_t(pt0(1)) + t * v1(1) + 0.5))); + d = (point - foot).cast().norm(); if (d < dmin) { dmin = d; proj = foot; @@ -376,12 +361,12 @@ static inline bool is_stick(const Point &p1, const Point &p2, const Point &p3) { Point v1 = p2 - p1; Point v2 = p3 - p2; - int64_t dir = int64_t(v1.x) * int64_t(v2.x) + int64_t(v1.y) * int64_t(v2.y); + int64_t dir = int64_t(v1(0)) * int64_t(v2(0)) + int64_t(v1(1)) * int64_t(v2(1)); if (dir > 0) // p3 does not turn back to p1. Do not remove p2. return false; - double l2_1 = double(v1.x) * double(v1.x) + double(v1.y) * double(v1.y); - double l2_2 = double(v2.x) * double(v2.x) + double(v2.y) * double(v2.y); + double l2_1 = double(v1(0)) * double(v1(0)) + double(v1(1)) * double(v1(1)); + double l2_2 = double(v2(0)) * double(v2(0)) + double(v2(1)) * double(v2(1)); if (dir == 0) // p1, p2, p3 may make a perpendicular corner, or there is a zero edge length. // Remove p2 if it is coincident with p1 or p2. @@ -389,7 +374,7 @@ static inline bool is_stick(const Point &p1, const Point &p2, const Point &p3) // p3 turns back to p1 after p2. Are p1, p2, p3 collinear? // Calculate distance from p3 to a segment (p1, p2) or from p1 to a segment(p2, p3), // whichever segment is longer - double cross = double(v1.x) * double(v2.y) - double(v2.x) * double(v1.y); + double cross = double(v1(0)) * double(v2(1)) - double(v2(0)) * double(v1(1)); double dist2 = cross * cross / std::max(l2_1, l2_2); return dist2 < EPSILON * EPSILON; } diff --git a/xs/src/libslic3r/Polygon.hpp b/xs/src/libslic3r/Polygon.hpp index 1a02d78b7..54909352c 100644 --- a/xs/src/libslic3r/Polygon.hpp +++ b/xs/src/libslic3r/Polygon.hpp @@ -24,11 +24,12 @@ public: explicit Polygon(const Points &points): MultiPoint(points) {} Polygon(const Polygon &other) : MultiPoint(other.points) {} Polygon(Polygon &&other) : MultiPoint(std::move(other.points)) {} - static Polygon new_scale(std::vector points) { - Points int_points; - for (auto pt : points) - int_points.push_back(Point::new_scale(pt.x, pt.y)); - return Polygon(int_points); + static Polygon new_scale(const std::vector &points) { + Polygon pgn; + pgn.points.reserve(points.size()); + for (const Vec2d &pt : points) + pgn.points.emplace_back(Point::new_scale(pt(0), pt(1))); + return pgn; } Polygon& operator=(const Polygon &other) { points = other.points; return *this; } Polygon& operator=(Polygon &&other) { points = std::move(other.points); return *this; } @@ -54,7 +55,6 @@ public: void simplify(double tolerance, Polygons &polygons) const; void triangulate_convex(Polygons* polygons) const; Point centroid() const; - std::string wkt() const; Points concave_points(double angle = PI) const; Points convex_points(double angle = PI) const; // Projection of a point onto the polygon. diff --git a/xs/src/libslic3r/Polyline.cpp b/xs/src/libslic3r/Polyline.cpp index 3432506c6..b2e50bca3 100644 --- a/xs/src/libslic3r/Polyline.cpp +++ b/xs/src/libslic3r/Polyline.cpp @@ -33,7 +33,7 @@ Polyline::leftmost_point() const { Point p = this->points.front(); for (Points::const_iterator it = this->points.begin() + 1; it != this->points.end(); ++it) { - if (it->x < p.x) p = *it; + if ((*it)(0) < p(0)) p = *it; } return p; } @@ -52,92 +52,82 @@ Polyline::lines() const } // removes the given distance from the end of the polyline -void -Polyline::clip_end(double distance) +void Polyline::clip_end(double distance) { while (distance > 0) { - Point last_point = this->last_point(); + Vec2d last_point = this->last_point().cast(); this->points.pop_back(); - if (this->points.empty()) break; - - double last_segment_length = last_point.distance_to(this->last_point()); - if (last_segment_length <= distance) { - distance -= last_segment_length; - continue; + if (this->points.empty()) + break; + Vec2d v = this->last_point().cast() - last_point; + double lsqr = v.squaredNorm(); + if (lsqr > distance * distance) { + this->points.emplace_back((last_point + v * (distance / sqrt(lsqr))).cast()); + return; } - - Line segment(last_point, this->last_point()); - this->points.push_back(segment.point_at(distance)); - distance = 0; + distance -= sqrt(lsqr); } } // removes the given distance from the start of the polyline -void -Polyline::clip_start(double distance) +void Polyline::clip_start(double distance) { this->reverse(); this->clip_end(distance); - if (this->points.size() >= 2) this->reverse(); + if (this->points.size() >= 2) + this->reverse(); } -void -Polyline::extend_end(double distance) +void Polyline::extend_end(double distance) { // relocate last point by extending the last segment by the specified length - Line line( - this->points.back(), - *(this->points.end() - 2) - ); - this->points.back() = line.point_at(-distance); + Vec2d v = (this->points.back() - *(this->points.end() - 2)).cast().normalized(); + this->points.back() += (v * distance).cast(); } -void -Polyline::extend_start(double distance) +void Polyline::extend_start(double distance) { // relocate first point by extending the first segment by the specified length - this->points.front() = Line(this->points.front(), this->points[1]).point_at(-distance); + Vec2d v = (this->points.front() - this->points[1]).cast().normalized(); + this->points.front() += (v * distance).cast(); } /* this method returns a collection of points picked on the polygon contour so that they are evenly spaced according to the input distance */ -Points -Polyline::equally_spaced_points(double distance) const +Points Polyline::equally_spaced_points(double distance) const { Points points; - points.push_back(this->first_point()); + points.emplace_back(this->first_point()); double len = 0; for (Points::const_iterator it = this->points.begin() + 1; it != this->points.end(); ++it) { - double segment_length = it->distance_to(*(it-1)); + Vec2d p1 = (it-1)->cast(); + Vec2d v = it->cast() - p1; + double segment_length = v.norm(); len += segment_length; - if (len < distance) continue; - + if (len < distance) + continue; if (len == distance) { - points.push_back(*it); + points.emplace_back(*it); len = 0; continue; } - double take = segment_length - (len - distance); // how much we take of this segment - Line segment(*(it-1), *it); - points.push_back(segment.point_at(take)); - --it; - len = -take; + points.emplace_back((p1 + v * (take / v.norm())).cast()); + -- it; + len = - take; } return points; } -void -Polyline::simplify(double tolerance) +void Polyline::simplify(double tolerance) { this->points = MultiPoint::_douglas_peucker(this->points, tolerance); } /* This method simplifies all *lines* contained in the supplied area */ template -void -Polyline::simplify_by_visibility(const T &area) +void Polyline::simplify_by_visibility(const T &area) { Points &pp = this->points; @@ -157,30 +147,29 @@ Polyline::simplify_by_visibility(const T &area) template void Polyline::simplify_by_visibility(const ExPolygon &area); template void Polyline::simplify_by_visibility(const ExPolygonCollection &area); -void -Polyline::split_at(const Point &point, Polyline* p1, Polyline* p2) const +void Polyline::split_at(const Point &point, Polyline* p1, Polyline* p2) const { if (this->points.empty()) return; // find the line to split at size_t line_idx = 0; Point p = this->first_point(); - double min = point.distance_to(p); + double min = (p - point).cast().norm(); Lines lines = this->lines(); for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) { Point p_tmp = point.projection_onto(*line); - if (point.distance_to(p_tmp) < min) { + if ((p_tmp - point).cast().norm() < min) { p = p_tmp; - min = point.distance_to(p); + min = (p - point).cast().norm(); line_idx = line - lines.begin(); } } // create first half p1->points.clear(); - for (Lines::const_iterator line = lines.begin(); line != lines.begin() + line_idx + 1; ++line) { - if (!line->a.coincides_with(p)) p1->points.push_back(line->a); - } + for (Lines::const_iterator line = lines.begin(); line != lines.begin() + line_idx + 1; ++line) + if (line->a != p) + p1->points.push_back(line->a); // we add point instead of p because they might differ because of numerical issues // and caller might want to rely on point belonging to result polylines p1->points.push_back(point); @@ -193,8 +182,7 @@ Polyline::split_at(const Point &point, Polyline* p1, Polyline* p2) const } } -bool -Polyline::is_straight() const +bool Polyline::is_straight() const { /* Check that each segment's direction is equal to the line connecting first point and last point. (Checking each line against the previous @@ -208,19 +196,6 @@ Polyline::is_straight() const return true; } -std::string -Polyline::wkt() const -{ - std::ostringstream wkt; - wkt << "LINESTRING(("; - for (Points::const_iterator p = this->points.begin(); p != this->points.end(); ++p) { - wkt << p->x << " " << p->y; - if (p != this->points.end()-1) wkt << ","; - } - wkt << "))"; - return wkt.str(); -} - BoundingBox get_extents(const Polyline &polyline) { return polyline.bounding_box(); @@ -254,30 +229,17 @@ bool remove_degenerate(Polylines &polylines) return modified; } -ThickLines -ThickPolyline::thicklines() const +ThickLines ThickPolyline::thicklines() const { ThickLines lines; if (this->points.size() >= 2) { lines.reserve(this->points.size() - 1); - for (size_t i = 0; i < this->points.size()-1; ++i) { - ThickLine line(this->points[i], this->points[i+1]); - line.a_width = this->width[2*i]; - line.b_width = this->width[2*i+1]; - lines.push_back(line); - } + for (size_t i = 0; i + 1 < this->points.size(); ++ i) + lines.emplace_back(this->points[i], this->points[i + 1], this->width[2 * i], this->width[2 * i + 1]); } return lines; } -void -ThickPolyline::reverse() -{ - Polyline::reverse(); - std::reverse(this->width.begin(), this->width.end()); - std::swap(this->endpoints.first, this->endpoints.second); -} - Lines3 Polyline3::lines() const { Lines3 lines; diff --git a/xs/src/libslic3r/Polyline.hpp b/xs/src/libslic3r/Polyline.hpp index b64743d84..0c934e074 100644 --- a/xs/src/libslic3r/Polyline.hpp +++ b/xs/src/libslic3r/Polyline.hpp @@ -19,14 +19,15 @@ public: Polyline() {}; Polyline(const Polyline &other) : MultiPoint(other.points) {} Polyline(Polyline &&other) : MultiPoint(std::move(other.points)) {} + Polyline(std::initializer_list list) : MultiPoint(list) {} + explicit Polyline(const Point &p1, const Point &p2) { points.reserve(2); points.emplace_back(p1); points.emplace_back(p2); } Polyline& operator=(const Polyline &other) { points = other.points; return *this; } Polyline& operator=(Polyline &&other) { points = std::move(other.points); return *this; } - static Polyline new_scale(std::vector points) { + static Polyline new_scale(const std::vector &points) { Polyline pl; - Points int_points; - for (auto pt : points) - int_points.push_back(Point::new_scale(pt.x, pt.y)); - pl.append(int_points); + pl.points.reserve(points.size()); + for (const Vec2d &pt : points) + pl.points.emplace_back(Point::new_scale(pt(0), pt(1))); return pl; } @@ -71,7 +72,6 @@ public: template void simplify_by_visibility(const T &area); void split_at(const Point &point, Polyline* p1, Polyline* p2) const; bool is_straight() const; - std::string wkt() const; }; extern BoundingBox get_extents(const Polyline &polyline); @@ -129,12 +129,17 @@ inline void polylines_append(Polylines &dst, Polylines &&src) bool remove_degenerate(Polylines &polylines); class ThickPolyline : public Polyline { - public: - std::vector width; - std::pair endpoints; - ThickPolyline() : endpoints(std::make_pair(false, false)) {}; +public: + ThickPolyline() : endpoints(std::make_pair(false, false)) {} ThickLines thicklines() const; - void reverse(); + void reverse() { + Polyline::reverse(); + std::reverse(this->width.begin(), this->width.end()); + std::swap(this->endpoints.first, this->endpoints.second); + } + + std::vector width; + std::pair endpoints; }; class Polyline3 : public MultiPoint3 diff --git a/xs/src/libslic3r/PolylineCollection.cpp b/xs/src/libslic3r/PolylineCollection.cpp index ca9c64d23..3f65ea699 100644 --- a/xs/src/libslic3r/PolylineCollection.cpp +++ b/xs/src/libslic3r/PolylineCollection.cpp @@ -15,9 +15,9 @@ inline int nearest_point_index(const std::vector &pairs, const Point & T dmin = std::numeric_limits::max(); int idx = 0; for (std::vector::const_iterator it = pairs.begin(); it != pairs.end(); ++it) { - T d = sqr(T(start_near.x - it->first.x)); + T d = sqr(T(start_near(0) - it->first(0))); if (d <= dmin) { - d += sqr(T(start_near.y - it->first.y)); + d += sqr(T(start_near(1) - it->first(1))); if (d < dmin) { idx = (it - pairs.begin()) * 2; dmin = d; @@ -26,9 +26,9 @@ inline int nearest_point_index(const std::vector &pairs, const Point & } } if (! no_reverse) { - d = sqr(T(start_near.x - it->last.x)); + d = sqr(T(start_near(0) - it->last(0))); if (d <= dmin) { - d += sqr(T(start_near.y - it->last.y)); + d += sqr(T(start_near(1) - it->last(1))); if (d < dmin) { idx = (it - pairs.begin()) * 2 + 1; dmin = d; @@ -82,7 +82,7 @@ Point PolylineCollection::leftmost_point(const Polylines &polylines) Point p = it->leftmost_point(); for (++ it; it != polylines.end(); ++it) { Point p2 = it->leftmost_point(); - if (p2.x < p.x) + if (p2(0) < p(0)) p = p2; } return p; diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 7d2906bcc..230201cc1 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -536,9 +536,9 @@ bool Print::has_skirt() const std::string Print::validate() const { BoundingBox bed_box_2D = get_extents(Polygon::new_scale(config.bed_shape.values)); - BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(unscale(bed_box_2D.max.x), unscale(bed_box_2D.max.y), config.max_print_height)); + BoundingBoxf3 print_volume(unscale(bed_box_2D.min(0), bed_box_2D.min(1), 0.0), unscale(bed_box_2D.max(0), bed_box_2D.max(1), scale_(config.max_print_height))); // Allow the objects to protrude below the print bed, only the part of the object above the print bed will be sliced. - print_volume.min.z = -1e10; + print_volume.min(2) = -1e10; unsigned int printable_count = 0; for (PrintObject *po : this->objects) { po->model_object()->check_instances_print_volume_state(print_volume); @@ -583,7 +583,7 @@ std::string Print::validate() const { std::vector object_height; for (const PrintObject *object : this->objects) - object_height.insert(object_height.end(), object->copies().size(), object->size.z); + object_height.insert(object_height.end(), object->copies().size(), object->size(2)); std::sort(object_height.begin(), object_height.end()); // Ignore the tallest *copy* (this is why we repeat height for all of them): // it will be printed as last one so its height doesn't matter. @@ -724,7 +724,7 @@ BoundingBox Print::bounding_box() const for (const PrintObject *object : this->objects) for (Point copy : object->_shifted_copies) { bb.merge(copy); - copy.translate(object->size); + copy += to_2d(object->size); bb.merge(copy); } return bb; @@ -900,7 +900,7 @@ void Print::_make_skirt() for (const Point &shift : object->_shifted_copies) { Points copy_points = object_points; for (Point &pt : copy_points) - pt.translate(shift); + pt += shift; append(points, copy_points); } } @@ -967,7 +967,7 @@ void Print::_make_skirt() this->skirt.append(eloop); if (this->config.min_skirt_length.value > 0) { // The skirt length is limited. Sum the total amount of filament length extruded, in mm. - extruded_length[extruder_idx] += unscale(loop.length()) * extruders_e_per_mm[extruder_idx]; + extruded_length[extruder_idx] += unscale(loop.length()) * extruders_e_per_mm[extruder_idx]; if (extruded_length[extruder_idx] < this->config.min_skirt_length.value) { // Not extruded enough yet with the current extruder. Add another loop. if (i == 1) @@ -1052,7 +1052,7 @@ void Print::_make_wipe_tower() m_wipe_tower_depth = 0.f; // Get wiping matrix to get number of extruders and convert vector to vector: - std::vector wiping_matrix((this->config.wiping_volumes_matrix.values).begin(),(this->config.wiping_volumes_matrix.values).end()); + std::vector wiping_matrix(cast(this->config.wiping_volumes_matrix.values)); // Extract purging volumes for each extruder pair: std::vector> wipe_volumes; const unsigned int number_of_extruders = (unsigned int)(sqrt(wiping_matrix.size())+EPSILON); diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index e3430ad0e..82fedbc7b 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -118,7 +118,7 @@ public: // so that next call to make_perimeters() performs a union() before computing loops bool typed_slices; - Point3 size; // XYZ in scaled coordinates + Vec3crd size; // XYZ in scaled coordinates // scaled coordinates to add to copies (to compensate for the alignment // operated when creating the object but still preserving a coherent API @@ -138,13 +138,13 @@ public: const ModelObject* model_object() const { return this->_model_object; } const Points& copies() const { return this->_copies; } - bool add_copy(const Pointf &point); + bool add_copy(const Vec2d &point); bool delete_last_copy(); bool delete_all_copies() { return this->set_copies(Points()); } bool set_copies(const Points &points); bool reload_model_instances(); // since the object is aligned to origin, bounding box coincides with size - BoundingBox bounding_box() const { return BoundingBox(Point(0,0), this->size); } + BoundingBox bounding_box() const { return BoundingBox(Point(0,0), to_2d(this->size)); } // adds region_id, too, if necessary void add_region_volume(unsigned int region_id, int volume_id) { diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index bf5f734ac..400530151 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -35,7 +35,7 @@ PrintConfigDef::PrintConfigDef() def = this->add("bed_shape", coPoints); def->label = L("Bed shape"); - def->default_value = new ConfigOptionPoints { Pointf(0,0), Pointf(200,0), Pointf(200,200), Pointf(0,200) }; + def->default_value = new ConfigOptionPoints { Vec2d(0,0), Vec2d(200,0), Vec2d(200,200), Vec2d(0,200) }; def = this->add("bed_temperature", coInts); def->label = L("Other layers"); @@ -392,7 +392,7 @@ PrintConfigDef::PrintConfigDef() "from the XY coordinate)."); def->sidetext = L("mm"); def->cli = "extruder-offset=s@"; - def->default_value = new ConfigOptionPoints { Pointf(0,0) }; + def->default_value = new ConfigOptionPoints { Vec2d(0,0) }; def = this->add("extrusion_axis", coString); def->label = L("Extrusion axis"); @@ -2117,7 +2117,7 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va ConfigOptionPoint p; p.deserialize(value); std::ostringstream oss; - oss << "0x0," << p.value.x << "x0," << p.value.x << "x" << p.value.y << ",0x" << p.value.y; + oss << "0x0," << p.value(0) << "x0," << p.value(0) << "x" << p.value(1) << ",0x" << p.value(1); value = oss.str(); } else if ((opt_key == "perimeter_acceleration" && value == "25") || (opt_key == "infill_acceleration" && value == "50")) { diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index 7150ead59..d03b99416 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -38,6 +38,7 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Bounding typed_slices(false), _print(print), _model_object(model_object), + size(Vec3crd::Zero()), layer_height_profile_valid(false) { // Compute the translation to be applied to our meshes so that we work with smaller coordinates @@ -48,10 +49,9 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Bounding // don't assume it's already aligned and we don't alter the original position in model. // We store the XY translation so that we can place copies correctly in the output G-code // (copies are expressed in G-code coordinates and this translation is not publicly exposed). - this->_copies_shift = Point::new_scale(modobj_bbox.min.x, modobj_bbox.min.y); + this->_copies_shift = Point::new_scale(modobj_bbox.min(0), modobj_bbox.min(1)); // Scale the object size and store it - Pointf3 size = modobj_bbox.size(); - this->size = Point3::new_scale(size.x, size.y, size.z); + this->size = (modobj_bbox.size() * (1. / SCALING_FACTOR)).cast(); } this->reload_model_instances(); @@ -59,10 +59,10 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Bounding this->layer_height_profile = model_object->layer_height_profile; } -bool PrintObject::add_copy(const Pointf &point) +bool PrintObject::add_copy(const Vec2d &point) { Points points = this->_copies; - points.push_back(Point::new_scale(point.x, point.y)); + points.push_back(Point::new_scale(point(0), point(1))); return this->set_copies(points); } @@ -86,11 +86,8 @@ bool PrintObject::set_copies(const Points &points) std::vector ordered_copies; Slic3r::Geometry::chained_path(points, ordered_copies); - for (size_t point_idx : ordered_copies) { - Point copy = points[point_idx]; - copy.translate(this->_copies_shift); - this->_shifted_copies.push_back(copy); - } + for (size_t point_idx : ordered_copies) + this->_shifted_copies.push_back(points[point_idx] + this->_copies_shift); bool invalidated = this->_print->invalidate_step(psSkirt); invalidated |= this->_print->invalidate_step(psBrim); @@ -106,7 +103,7 @@ bool PrintObject::reload_model_instances() for (const ModelInstance *mi : this->_model_object->instances) { if (mi->is_printable()) - copies.emplace_back(Point::new_scale(mi->offset.x, mi->offset.y)); + copies.emplace_back(Point::new_scale(mi->offset(0), mi->offset(1))); } return this->set_copies(copies); } @@ -1124,7 +1121,7 @@ SlicingParameters PrintObject::slicing_parameters() const { return SlicingParameters::create_from_config( this->print()->config, this->config, - unscale(this->size.z), this->print()->object_extruders()); + unscale(this->size(2)), this->print()->object_extruders()); } bool PrintObject::update_layer_height_profile(std::vector &layer_height_profile) const @@ -1338,7 +1335,7 @@ std::vector PrintObject::_slice_region(size_t region_id, const std:: // consider the first one this->model_object()->instances.front()->transform_mesh(&mesh, true); // align mesh to Z = 0 (it should be already aligned actually) and apply XY shift - mesh.translate(- float(unscale(this->_copies_shift.x)), - float(unscale(this->_copies_shift.y)), -float(this->model_object()->bounding_box().min.z)); + mesh.translate(- unscale(this->_copies_shift(0)), - unscale(this->_copies_shift(1)), - float(this->model_object()->bounding_box().min(2))); // perform actual slicing TriangleMeshSlicer mslicer(&mesh); mslicer.slice(z, &layers); diff --git a/xs/src/libslic3r/SVG.cpp b/xs/src/libslic3r/SVG.cpp index c94db8e74..03f55802e 100644 --- a/xs/src/libslic3r/SVG.cpp +++ b/xs/src/libslic3r/SVG.cpp @@ -3,7 +3,7 @@ #include -#define COORD(x) ((float)unscale((x))*10) +#define COORD(x) (unscale((x))*10) namespace Slic3r { @@ -32,8 +32,8 @@ bool SVG::open(const char* afilename, const BoundingBox &bbox, const coord_t bbo this->f = boost::nowide::fopen(afilename, "w"); if (f == NULL) return false; - float w = COORD(bbox.max.x - bbox.min.x + 2 * bbox_offset); - float h = COORD(bbox.max.y - bbox.min.y + 2 * bbox_offset); + float w = COORD(bbox.max(0) - bbox.min(0) + 2 * bbox_offset); + float h = COORD(bbox.max(1) - bbox.min(1) + 2 * bbox_offset); fprintf(this->f, "\n" "\n" @@ -50,7 +50,7 @@ SVG::draw(const Line &line, std::string stroke, coordf_t stroke_width) { fprintf(this->f, " arrows) fprintf(this->f, " marker-end=\"url(#endArrow)\""); fprintf(this->f, "/>\n"); @@ -58,21 +58,21 @@ SVG::draw(const Line &line, std::string stroke, coordf_t stroke_width) void SVG::draw(const ThickLine &line, const std::string &fill, const std::string &stroke, coordf_t stroke_width) { - Pointf dir(line.b.x-line.a.x, line.b.y-line.a.y); - Pointf perp(-dir.y, dir.x); - coordf_t len = sqrt(perp.x*perp.x + perp.y*perp.y); + Vec2d dir(line.b(0)-line.a(0), line.b(1)-line.a(1)); + Vec2d perp(-dir(1), dir(0)); + coordf_t len = sqrt(perp(0)*perp(0) + perp(1)*perp(1)); coordf_t da = coordf_t(0.5)*line.a_width/len; coordf_t db = coordf_t(0.5)*line.b_width/len; fprintf(this->f, " \n", - COORD(line.a.x-da*perp.x-origin.x), - COORD(line.a.y-da*perp.y-origin.y), - COORD(line.b.x-db*perp.x-origin.x), - COORD(line.b.y-db*perp.y-origin.y), - COORD(line.b.x+db*perp.x-origin.x), - COORD(line.b.y+db*perp.y-origin.y), - COORD(line.a.x+da*perp.x-origin.x), - COORD(line.a.y+da*perp.y-origin.y), + COORD(line.a(0)-da*perp(0)-origin(0)), + COORD(line.a(1)-da*perp(1)-origin(1)), + COORD(line.b(0)-db*perp(0)-origin(0)), + COORD(line.b(1)-db*perp(1)-origin(1)), + COORD(line.b(0)+db*perp(0)-origin(0)), + COORD(line.b(1)+db*perp(1)-origin(1)), + COORD(line.a(0)+da*perp(0)-origin(0)), + COORD(line.a(1)+da*perp(1)-origin(1)), fill.c_str(), stroke.c_str(), (stroke_width == 0) ? 1.f : COORD(stroke_width)); } @@ -220,7 +220,7 @@ SVG::draw(const Point &point, std::string fill, coord_t iradius) { float radius = (iradius == 0) ? 3.f : COORD(iradius); std::ostringstream svg; - svg << " "; @@ -287,8 +287,8 @@ SVG::get_path_d(const MultiPoint &mp, bool closed) const std::ostringstream d; d << "M "; for (Points::const_iterator p = mp.points.begin(); p != mp.points.end(); ++p) { - d << COORD(p->x - origin.x) << " "; - d << COORD(p->y - origin.y) << " "; + d << COORD((*p)(0) - origin(0)) << " "; + d << COORD((*p)(1) - origin(1)) << " "; } if (closed) d << "z"; return d.str(); @@ -300,8 +300,8 @@ SVG::get_path_d(const ClipperLib::Path &path, double scale, bool closed) const std::ostringstream d; d << "M "; for (ClipperLib::Path::const_iterator p = path.begin(); p != path.end(); ++p) { - d << COORD(scale * p->X - origin.x) << " "; - d << COORD(scale * p->Y - origin.y) << " "; + d << COORD(scale * p->X - origin(0)) << " "; + d << COORD(scale * p->Y - origin(1)) << " "; } if (closed) d << "z"; return d.str(); @@ -311,8 +311,8 @@ void SVG::draw_text(const Point &pt, const char *text, const char *color) { fprintf(this->f, "%s", - COORD(pt.x-origin.x), - COORD(pt.y-origin.y), + COORD(pt(0)-origin(0)), + COORD(pt(1)-origin(1)), color, text); } @@ -320,13 +320,13 @@ void SVG::draw_legend(const Point &pt, const char *text, const char *color) { fprintf(this->f, "", - COORD(pt.x-origin.x), - COORD(pt.y-origin.y), + COORD(pt(0)-origin(0)), + COORD(pt(1)-origin(1)), color); fprintf(this->f, "%s", - COORD(pt.x-origin.x) + 20.f, - COORD(pt.y-origin.y), + COORD(pt(0)-origin(0)) + 20.f, + COORD(pt(1)-origin(1)), "black", text); } diff --git a/xs/src/libslic3r/Slicing.cpp b/xs/src/libslic3r/Slicing.cpp index e9295d1e3..1bc38502b 100644 --- a/xs/src/libslic3r/Slicing.cpp +++ b/xs/src/libslic3r/Slicing.cpp @@ -561,15 +561,15 @@ int generate_layer_height_texture( void *data, int rows, int cols, bool level_of_detail_2nd_level) { // https://github.com/aschn/gnuplot-colorbrewer - std::vector palette_raw; - palette_raw.push_back(Point3(0x01A, 0x098, 0x050)); - palette_raw.push_back(Point3(0x066, 0x0BD, 0x063)); - palette_raw.push_back(Point3(0x0A6, 0x0D9, 0x06A)); - palette_raw.push_back(Point3(0x0D9, 0x0F1, 0x0EB)); - palette_raw.push_back(Point3(0x0FE, 0x0E6, 0x0EB)); - palette_raw.push_back(Point3(0x0FD, 0x0AE, 0x061)); - palette_raw.push_back(Point3(0x0F4, 0x06D, 0x043)); - palette_raw.push_back(Point3(0x0D7, 0x030, 0x027)); + std::vector palette_raw; + palette_raw.push_back(Vec3crd(0x01A, 0x098, 0x050)); + palette_raw.push_back(Vec3crd(0x066, 0x0BD, 0x063)); + palette_raw.push_back(Vec3crd(0x0A6, 0x0D9, 0x06A)); + palette_raw.push_back(Vec3crd(0x0D9, 0x0F1, 0x0EB)); + palette_raw.push_back(Vec3crd(0x0FE, 0x0E6, 0x0EB)); + palette_raw.push_back(Vec3crd(0x0FD, 0x0AE, 0x061)); + palette_raw.push_back(Vec3crd(0x0F4, 0x06D, 0x043)); + palette_raw.push_back(Vec3crd(0x0D7, 0x030, 0x027)); // Clear the main texture and the 2nd LOD level. // memset(data, 0, rows * cols * (level_of_detail_2nd_level ? 5 : 4)); @@ -600,25 +600,25 @@ int generate_layer_height_texture( int idx1 = clamp(0, int(palette_raw.size() - 1), int(floor(idxf))); int idx2 = std::min(int(palette_raw.size() - 1), idx1 + 1); coordf_t t = idxf - coordf_t(idx1); - const Point3 &color1 = palette_raw[idx1]; - const Point3 &color2 = palette_raw[idx2]; + const Vec3crd &color1 = palette_raw[idx1]; + const Vec3crd &color2 = palette_raw[idx2]; coordf_t z = cell_to_z * coordf_t(cell); assert(z >= lo && z <= hi); // Intensity profile to visualize the layers. coordf_t intensity = cos(M_PI * 0.7 * (mid - z) / h); // Color mapping from layer height to RGB. - Pointf3 color( - intensity * lerp(coordf_t(color1.x), coordf_t(color2.x), t), - intensity * lerp(coordf_t(color1.y), coordf_t(color2.y), t), - intensity * lerp(coordf_t(color1.z), coordf_t(color2.z), t)); + Vec3d color( + intensity * lerp(coordf_t(color1(0)), coordf_t(color2(0)), t), + intensity * lerp(coordf_t(color1(1)), coordf_t(color2(1)), t), + intensity * lerp(coordf_t(color1(2)), coordf_t(color2(2)), t)); int row = cell / (cols - 1); int col = cell - row * (cols - 1); assert(row >= 0 && row < rows); assert(col >= 0 && col < cols); unsigned char *ptr = (unsigned char*)data + (row * cols + col) * 4; - ptr[0] = (unsigned char)clamp(0, 255, int(floor(color.x + 0.5))); - ptr[1] = (unsigned char)clamp(0, 255, int(floor(color.y + 0.5))); - ptr[2] = (unsigned char)clamp(0, 255, int(floor(color.z + 0.5))); + ptr[0] = (unsigned char)clamp(0, 255, int(floor(color(0) + 0.5))); + ptr[1] = (unsigned char)clamp(0, 255, int(floor(color(1) + 0.5))); + ptr[2] = (unsigned char)clamp(0, 255, int(floor(color(2) + 0.5))); ptr[3] = 255; if (col == 0 && row > 0) { // Duplicate the first value in a row as a last value of the preceding row. @@ -636,21 +636,21 @@ int generate_layer_height_texture( int idx1 = clamp(0, int(palette_raw.size() - 1), int(floor(idxf))); int idx2 = std::min(int(palette_raw.size() - 1), idx1 + 1); coordf_t t = idxf - coordf_t(idx1); - const Point3 &color1 = palette_raw[idx1]; - const Point3 &color2 = palette_raw[idx2]; + const Vec3crd &color1 = palette_raw[idx1]; + const Vec3crd &color2 = palette_raw[idx2]; // Color mapping from layer height to RGB. - Pointf3 color( - lerp(coordf_t(color1.x), coordf_t(color2.x), t), - lerp(coordf_t(color1.y), coordf_t(color2.y), t), - lerp(coordf_t(color1.z), coordf_t(color2.z), t)); + Vec3d color( + lerp(coordf_t(color1(0)), coordf_t(color2(0)), t), + lerp(coordf_t(color1(1)), coordf_t(color2(1)), t), + lerp(coordf_t(color1(2)), coordf_t(color2(2)), t)); int row = cell / (cols1 - 1); int col = cell - row * (cols1 - 1); assert(row >= 0 && row < rows/2); assert(col >= 0 && col < cols/2); unsigned char *ptr = data1 + (row * cols1 + col) * 4; - ptr[0] = (unsigned char)clamp(0, 255, int(floor(color.x + 0.5))); - ptr[1] = (unsigned char)clamp(0, 255, int(floor(color.y + 0.5))); - ptr[2] = (unsigned char)clamp(0, 255, int(floor(color.z + 0.5))); + ptr[0] = (unsigned char)clamp(0, 255, int(floor(color(0) + 0.5))); + ptr[1] = (unsigned char)clamp(0, 255, int(floor(color(1) + 0.5))); + ptr[2] = (unsigned char)clamp(0, 255, int(floor(color(2) + 0.5))); ptr[3] = 255; if (col == 0 && row > 0) { // Duplicate the first value in a row as a last value of the preceding row. diff --git a/xs/src/libslic3r/SlicingAdaptive.cpp b/xs/src/libslic3r/SlicingAdaptive.cpp index ff0da7636..2ef4aec8c 100644 --- a/xs/src/libslic3r/SlicingAdaptive.cpp +++ b/xs/src/libslic3r/SlicingAdaptive.cpp @@ -15,8 +15,8 @@ void SlicingAdaptive::clear() std::pair face_z_span(const stl_facet *f) { return std::pair( - std::min(std::min(f->vertex[0].z, f->vertex[1].z), f->vertex[2].z), - std::max(std::max(f->vertex[0].z, f->vertex[1].z), f->vertex[2].z)); + std::min(std::min(f->vertex[0](2), f->vertex[1](2)), f->vertex[2](2)), + std::max(std::max(f->vertex[0](2), f->vertex[1](2)), f->vertex[2](2))); } void SlicingAdaptive::prepare() @@ -40,7 +40,7 @@ void SlicingAdaptive::prepare() // 3) Generate Z components of the facet normals. m_face_normal_z.assign(m_faces.size(), 0.f); for (size_t iface = 0; iface < m_faces.size(); ++ iface) - m_face_normal_z[iface] = m_faces[iface]->normal.z; + m_face_normal_z[iface] = m_faces[iface]->normal(2); } float SlicingAdaptive::cusp_height(float z, float cusp_value, int ¤t_facet) diff --git a/xs/src/libslic3r/SupportMaterial.cpp b/xs/src/libslic3r/SupportMaterial.cpp index 0cecf0014..4b7e78976 100644 --- a/xs/src/libslic3r/SupportMaterial.cpp +++ b/xs/src/libslic3r/SupportMaterial.cpp @@ -67,9 +67,9 @@ Point export_support_surface_type_legend_to_svg_box_size() void export_support_surface_type_legend_to_svg(SVG &svg, const Point &pos) { // 1st row - coord_t pos_x0 = pos.x + scale_(1.); + coord_t pos_x0 = pos(0) + scale_(1.); coord_t pos_x = pos_x0; - coord_t pos_y = pos.y + scale_(1.5); + coord_t pos_y = pos(1) + scale_(1.5); coord_t step_x = scale_(10.); svg.draw_legend(Point(pos_x, pos_y), "top contact" , support_surface_type_to_color_name(PrintObjectSupportMaterial::sltTopContact)); pos_x += step_x; @@ -82,7 +82,7 @@ void export_support_surface_type_legend_to_svg(SVG &svg, const Point &pos) svg.draw_legend(Point(pos_x, pos_y), "bottom contact" , support_surface_type_to_color_name(PrintObjectSupportMaterial::sltBottomContact)); // 2nd row pos_x = pos_x0; - pos_y = pos.y+scale_(2.8); + pos_y = pos(1)+scale_(2.8); svg.draw_legend(Point(pos_x, pos_y), "raft interface" , support_surface_type_to_color_name(PrintObjectSupportMaterial::sltRaftInterface)); pos_x += step_x; svg.draw_legend(Point(pos_x, pos_y), "raft base" , support_surface_type_to_color_name(PrintObjectSupportMaterial::sltRaftBase)); @@ -98,8 +98,8 @@ void export_print_z_polygons_to_svg(const char *path, PrintObjectSupportMaterial for (int i = 0; i < n_layers; ++ i) bbox.merge(get_extents(layers[i]->polygons)); Point legend_size = export_support_surface_type_legend_to_svg_box_size(); - Point legend_pos(bbox.min.x, bbox.max.y); - bbox.merge(Point(std::max(bbox.min.x + legend_size.x, bbox.max.x), bbox.max.y + legend_size.y)); + Point legend_pos(bbox.min(0), bbox.max(1)); + bbox.merge(Point(std::max(bbox.min(0) + legend_size(0), bbox.max(0)), bbox.max(1) + legend_size(1))); SVG svg(path, bbox); const float transparency = 0.5f; for (int i = 0; i < n_layers; ++ i) @@ -120,8 +120,8 @@ void export_print_z_polygons_and_extrusions_to_svg( for (int i = 0; i < n_layers; ++ i) bbox.merge(get_extents(layers[i]->polygons)); Point legend_size = export_support_surface_type_legend_to_svg_box_size(); - Point legend_pos(bbox.min.x, bbox.max.y); - bbox.merge(Point(std::max(bbox.min.x + legend_size.x, bbox.max.x), bbox.max.y + legend_size.y)); + Point legend_pos(bbox.min(0), bbox.max(1)); + bbox.merge(Point(std::max(bbox.min(0) + legend_size(0), bbox.max(0)), bbox.max(1) + legend_size(1))); SVG svg(path, bbox); const float transparency = 0.5f; for (int i = 0; i < n_layers; ++ i) @@ -506,8 +506,8 @@ public: for (ExPolygon &island : islands) { BoundingBox bbox = get_extents(island.contour); - auto it_lower = std::lower_bound(m_island_samples.begin(), m_island_samples.end(), bbox.min - Point(1, 1)); - auto it_upper = std::upper_bound(m_island_samples.begin(), m_island_samples.end(), bbox.max + Point(1, 1)); + auto it_lower = std::lower_bound(m_island_samples.begin(), m_island_samples.end(), Point(bbox.min - Point(1, 1))); + auto it_upper = std::upper_bound(m_island_samples.begin(), m_island_samples.end(), Point(bbox.max + Point(1, 1))); samples_inside.clear(); for (auto it = it_lower; it != it_upper; ++ it) if (bbox.contains(*it)) @@ -519,12 +519,12 @@ public: Points::const_iterator i = contour.points.begin(); Points::const_iterator j = contour.points.end() - 1; for (; i != contour.points.end(); j = i ++) { - //FIXME this test is not numerically robust. Particularly, it does not handle horizontal segments at y == point.y well. - // Does the ray with y == point.y intersect this line segment? + //FIXME this test is not numerically robust. Particularly, it does not handle horizontal segments at y == point(1) well. + // Does the ray with y == point(1) intersect this line segment? for (auto &sample_inside : samples_inside) { - if ((i->y > sample_inside.first.y) != (j->y > sample_inside.first.y)) { - double x1 = (double)sample_inside.first.x; - double x2 = (double)i->x + (double)(j->x - i->x) * (double)(sample_inside.first.y - i->y) / (double)(j->y - i->y); + if (((*i)(1) > sample_inside.first(1)) != ((*j)(1) > sample_inside.first(1))) { + double x1 = (double)sample_inside.first(0); + double x2 = (double)(*i)(0) + (double)((*j)(0) - (*i)(0)) * (double)(sample_inside.first(1) - (*i)(1)) / (double)((*j)(1) - (*i)(1)); if (x1 < x2) sample_inside.second = !sample_inside.second; } @@ -585,11 +585,11 @@ private: const Point &p3 = (pt_min == &expoly.contour.points.back()) ? expoly.contour.points.front() : *(pt_min + 1); Vector v = (p3 - p2) + (p1 - p2); - double l2 = double(v.x)*double(v.x)+double(v.y)*double(v.y); + double l2 = double(v(0))*double(v(0))+double(v(1))*double(v(1)); if (l2 == 0.) return p2; double coef = 20. / sqrt(l2); - return Point(p2.x + coef * v.x, p2.y + coef * v.y); + return Point(p2(0) + coef * v(0), p2(1) + coef * v(1)); } static Points island_samples(const ExPolygons &expolygons) @@ -789,7 +789,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ // workaround for Clipper bug, see Slic3r::Polygon::clip_as_polyline() for (Polyline &polyline : overhang_perimeters) - polyline.points[0].x += 1; + polyline.points[0](0) += 1; // Trim the perimeters of this layer by the lower layer to get the unsupported pieces of perimeters. overhang_perimeters = diff_pl(overhang_perimeters, lower_grown_slices); @@ -2057,11 +2057,11 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const const Point &p1 = *(it-1); const Point &p2 = *it; // Intersection of a ray (p1, p2) with a circle placed at center_last, with radius of circle_distance. - const Pointf v_seg(coordf_t(p2.x) - coordf_t(p1.x), coordf_t(p2.y) - coordf_t(p1.y)); - const Pointf v_cntr(coordf_t(p1.x - center_last.x), coordf_t(p1.y - center_last.y)); - coordf_t a = dot(v_seg); - coordf_t b = 2. * dot(v_seg, v_cntr); - coordf_t c = dot(v_cntr) - circle_distance * circle_distance; + const Vec2d v_seg(coordf_t(p2(0)) - coordf_t(p1(0)), coordf_t(p2(1)) - coordf_t(p1(1))); + const Vec2d v_cntr(coordf_t(p1(0) - center_last(0)), coordf_t(p1(1) - center_last(1))); + coordf_t a = v_seg.squaredNorm(); + coordf_t b = 2. * v_seg.dot(v_cntr); + coordf_t c = v_cntr.squaredNorm() - circle_distance * circle_distance; coordf_t disc = b * b - 4. * a * c; if (disc > 0.) { // The circle intersects a ray. Avoid the parts of the segment inside the circle. @@ -2081,7 +2081,7 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const } seg_current_pt = &p1; seg_current_t = t; - center_last = Point(p1.x + coord_t(v_seg.x * t), p1.y + coord_t(v_seg.y * t)); + center_last = Point(p1(0) + coord_t(v_seg(0) * t), p1(1) + coord_t(v_seg(1) * t)); // It has been verified that the new point is far enough from center_last. // Ensure, that it is far enough from all the centers. std::pair circle_closest = circle_centers_lookup.find(center_last); @@ -2100,9 +2100,9 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const circle_centers.push_back(center_last); } external_loops.push_back(std::move(contour)); - for (Points::const_iterator it_center = circle_centers.begin(); it_center != circle_centers.end(); ++ it_center) { + for (const Point ¢er : circle_centers) { circles.push_back(circle); - circles.back().translate(*it_center); + circles.back().translate(center); } } } @@ -2359,7 +2359,7 @@ void modulate_extrusion_by_overlapping_layers( (fragment_end.is_start ? &polyline.points.front() : &polyline.points.back()); } private: - ExtrusionPathFragmentEndPointAccessor& operator=(const ExtrusionPathFragmentEndPointAccessor&); + ExtrusionPathFragmentEndPointAccessor& operator=(const ExtrusionPathFragmentEndPointAccessor&) = delete; const std::vector &m_path_fragments; }; const coord_t search_radius = 7; @@ -2392,7 +2392,7 @@ void modulate_extrusion_by_overlapping_layers( if (end_and_dist2.first == nullptr) { // New fragment connecting to pt_current was not found. // Verify that the last point found is close to the original end point of the unfragmented path. - //const double d2 = pt_end.distance_to_sq(pt_current); + //const double d2 = (pt_end - pt_current).squaredNorm(); //assert(d2 < coordf_t(search_radius * search_radius)); // End of the path. break; @@ -2887,9 +2887,9 @@ void PrintObjectSupportMaterial::clip_by_pillars( BoundingBox bbox; for (LayersPtr::const_iterator it = top_contacts.begin(); it != top_contacts.end(); ++ it) bbox.merge(get_extents((*it)->polygons)); - grid.reserve(size_t(ceil(bb.size().x / pillar_spacing)) * size_t(ceil(bb.size().y / pillar_spacing))); - for (coord_t x = bb.min.x; x <= bb.max.x - pillar_size; x += pillar_spacing) { - for (coord_t y = bb.min.y; y <= bb.max.y - pillar_size; y += pillar_spacing) { + grid.reserve(size_t(ceil(bb.size()(0) / pillar_spacing)) * size_t(ceil(bb.size()(1) / pillar_spacing))); + for (coord_t x = bb.min(0); x <= bb.max(0) - pillar_size; x += pillar_spacing) { + for (coord_t y = bb.min(1); y <= bb.max(1) - pillar_size; y += pillar_spacing) { grid.push_back(pillar); for (size_t i = 0; i < pillar.points.size(); ++ i) grid.back().points[i].translate(Point(x, y)); diff --git a/xs/src/libslic3r/Surface.cpp b/xs/src/libslic3r/Surface.cpp index 384540d87..0e9eca7fd 100644 --- a/xs/src/libslic3r/Surface.cpp +++ b/xs/src/libslic3r/Surface.cpp @@ -106,9 +106,9 @@ Point export_surface_type_legend_to_svg_box_size() void export_surface_type_legend_to_svg(SVG &svg, const Point &pos) { // 1st row - coord_t pos_x0 = pos.x + scale_(1.); + coord_t pos_x0 = pos(0) + scale_(1.); coord_t pos_x = pos_x0; - coord_t pos_y = pos.y + scale_(1.5); + coord_t pos_y = pos(1) + scale_(1.5); coord_t step_x = scale_(10.); svg.draw_legend(Point(pos_x, pos_y), "perimeter" , surface_type_to_color_name(stPerimeter)); pos_x += step_x; @@ -121,7 +121,7 @@ void export_surface_type_legend_to_svg(SVG &svg, const Point &pos) svg.draw_legend(Point(pos_x, pos_y), "invalid" , surface_type_to_color_name(SurfaceType(-1))); // 2nd row pos_x = pos_x0; - pos_y = pos.y+scale_(2.8); + pos_y = pos(1)+scale_(2.8); svg.draw_legend(Point(pos_x, pos_y), "internal" , surface_type_to_color_name(stInternal)); pos_x += step_x; svg.draw_legend(Point(pos_x, pos_y), "internal solid" , surface_type_to_color_name(stInternalSolid)); diff --git a/xs/src/libslic3r/SurfaceCollection.cpp b/xs/src/libslic3r/SurfaceCollection.cpp index 42ddf9574..6db599306 100644 --- a/xs/src/libslic3r/SurfaceCollection.cpp +++ b/xs/src/libslic3r/SurfaceCollection.cpp @@ -170,8 +170,8 @@ void SurfaceCollection::export_to_svg(const char *path, bool show_labels) for (Surfaces::const_iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) bbox.merge(get_extents(surface->expolygon)); Point legend_size = export_surface_type_legend_to_svg_box_size(); - Point legend_pos(bbox.min.x, bbox.max.y); - bbox.merge(Point(std::max(bbox.min.x + legend_size.x, bbox.max.x), bbox.max.y + legend_size.y)); + Point legend_pos(bbox.min(0), bbox.max(1)); + bbox.merge(Point(std::max(bbox.min(0) + legend_size(0), bbox.max(0)), bbox.max(1) + legend_size(1))); SVG svg(path, bbox); const float transparency = 0.5f; diff --git a/xs/src/libslic3r/TriangleMesh.cpp b/xs/src/libslic3r/TriangleMesh.cpp index fc72a45aa..d559afe52 100644 --- a/xs/src/libslic3r/TriangleMesh.cpp +++ b/xs/src/libslic3r/TriangleMesh.cpp @@ -35,13 +35,7 @@ namespace Slic3r { -TriangleMesh::TriangleMesh() - : repaired(false) -{ - stl_initialize(&this->stl); -} - -TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector& facets ) +TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector& facets ) : repaired(false) { stl_initialize(&this->stl); @@ -56,51 +50,22 @@ TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector& fa for (int i = 0; i < stl.stats.number_of_facets; i++) { stl_facet facet; - - const Pointf3& ref_f1 = points[facets[i].x]; - facet.vertex[0].x = ref_f1.x; - facet.vertex[0].y = ref_f1.y; - facet.vertex[0].z = ref_f1.z; - - const Pointf3& ref_f2 = points[facets[i].y]; - facet.vertex[1].x = ref_f2.x; - facet.vertex[1].y = ref_f2.y; - facet.vertex[1].z = ref_f2.z; - - const Pointf3& ref_f3 = points[facets[i].z]; - facet.vertex[2].x = ref_f3.x; - facet.vertex[2].y = ref_f3.y; - facet.vertex[2].z = ref_f3.z; - + facet.vertex[0] = points[facets[i](0)].cast(); + facet.vertex[1] = points[facets[i](1)].cast(); + facet.vertex[2] = points[facets[i](2)].cast(); facet.extra[0] = 0; facet.extra[1] = 0; - float normal[3]; + stl_normal normal; stl_calculate_normal(normal, &facet); stl_normalize_vector(normal); - facet.normal.x = normal[0]; - facet.normal.y = normal[1]; - facet.normal.z = normal[2]; + facet.normal = normal; stl.facet_start[i] = facet; } stl_get_size(&stl); } -TriangleMesh::TriangleMesh(const TriangleMesh &other) : - repaired(false) -{ - stl_initialize(&this->stl); - *this = other; -} - -TriangleMesh::TriangleMesh(TriangleMesh &&other) : - repaired(false) -{ - stl_initialize(&this->stl); - this->swap(other); -} - TriangleMesh& TriangleMesh::operator=(const TriangleMesh &other) { stl_close(&this->stl); @@ -128,42 +93,8 @@ TriangleMesh& TriangleMesh::operator=(const TriangleMesh &other) return *this; } -TriangleMesh& TriangleMesh::operator=(TriangleMesh &&other) +void TriangleMesh::repair() { - this->swap(other); - return *this; -} - -void -TriangleMesh::swap(TriangleMesh &other) -{ - std::swap(this->stl, other.stl); - std::swap(this->repaired, other.repaired); -} - -TriangleMesh::~TriangleMesh() { - stl_close(&this->stl); -} - -void -TriangleMesh::ReadSTLFile(const char* input_file) { - stl_open(&stl, input_file); -} - -void -TriangleMesh::write_ascii(const char* output_file) -{ - stl_write_ascii(&this->stl, output_file, ""); -} - -void -TriangleMesh::write_binary(const char* output_file) -{ - stl_write_binary(&this->stl, output_file, ""); -} - -void -TriangleMesh::repair() { if (this->repaired) return; // admesh fails when repairing empty meshes @@ -260,13 +191,7 @@ void TriangleMesh::check_topology() } } -bool TriangleMesh::is_manifold() const -{ - return this->stl.stats.connected_facets_3_edge == this->stl.stats.number_of_facets; -} - -void -TriangleMesh::reset_repair_stats() { +void TriangleMesh::reset_repair_stats() { this->stl.stats.degenerate_facets = 0; this->stl.stats.edges_fixed = 0; this->stl.stats.facets_removed = 0; @@ -276,8 +201,7 @@ TriangleMesh::reset_repair_stats() { this->stl.stats.normals_fixed = 0; } -bool -TriangleMesh::needed_repair() const +bool TriangleMesh::needed_repair() const { return this->stl.stats.degenerate_facets > 0 || this->stl.stats.edges_fixed > 0 @@ -287,14 +211,8 @@ TriangleMesh::needed_repair() const || this->stl.stats.backwards_edges > 0; } -size_t -TriangleMesh::facets_count() const +void TriangleMesh::WriteOBJFile(char* output_file) { - return this->stl.stats.number_of_facets; -} - -void -TriangleMesh::WriteOBJFile(char* output_file) { stl_generate_shared_vertices(&stl); stl_write_obj(&stl, output_file); } @@ -305,13 +223,9 @@ void TriangleMesh::scale(float factor) stl_invalidate_shared_vertices(&this->stl); } -void TriangleMesh::scale(const Pointf3 &versor) +void TriangleMesh::scale(const Vec3d &versor) { - float fversor[3]; - fversor[0] = versor.x; - fversor[1] = versor.y; - fversor[2] = versor.z; - stl_scale_versor(&this->stl, fversor); + stl_scale_versor(&this->stl, versor.cast()); stl_invalidate_shared_vertices(&this->stl); } @@ -341,21 +255,6 @@ void TriangleMesh::rotate(float angle, const Axis &axis) stl_invalidate_shared_vertices(&this->stl); } -void TriangleMesh::rotate_x(float angle) -{ - this->rotate(angle, X); -} - -void TriangleMesh::rotate_y(float angle) -{ - this->rotate(angle, Y); -} - -void TriangleMesh::rotate_z(float angle) -{ - this->rotate(angle, Z); -} - void TriangleMesh::mirror(const Axis &axis) { if (axis == X) { @@ -368,21 +267,6 @@ void TriangleMesh::mirror(const Axis &axis) stl_invalidate_shared_vertices(&this->stl); } -void TriangleMesh::mirror_x() -{ - this->mirror(X); -} - -void TriangleMesh::mirror_y() -{ - this->mirror(Y); -} - -void TriangleMesh::mirror_z() -{ - this->mirror(Z); -} - void TriangleMesh::transform(const float* matrix3x4) { if (matrix3x4 == nullptr) @@ -395,19 +279,19 @@ void TriangleMesh::transform(const float* matrix3x4) void TriangleMesh::align_to_origin() { this->translate( - -(this->stl.stats.min.x), - -(this->stl.stats.min.y), - -(this->stl.stats.min.z) - ); + - this->stl.stats.min(0), + - this->stl.stats.min(1), + - this->stl.stats.min(2)); } void TriangleMesh::rotate(double angle, Point* center) { if (angle == 0.) return; - this->translate(float(-center->x), float(-center->y), 0); + Vec2f c = center->cast(); + this->translate(-c(0), -c(1), 0); stl_rotate_z(&(this->stl), (float)angle); - this->translate(float(+center->x), float(+center->y), 0); + this->translate(c(0), c(1), 0); } bool TriangleMesh::has_multiple_patches() const @@ -480,14 +364,14 @@ size_t TriangleMesh::number_of_patches() const return num_bodies; } -TriangleMeshPtrs -TriangleMesh::split() const +TriangleMeshPtrs TriangleMesh::split() const { - TriangleMeshPtrs meshes; - std::set seen_facets; + TriangleMeshPtrs meshes; + std::vector facet_visited(this->stl.stats.number_of_facets, false); // we need neighbors - if (!this->repaired) CONFESS("split() requires repair()"); + if (!this->repaired) + CONFESS("split() requires repair()"); // loop while we have remaining facets for (;;) { @@ -495,46 +379,45 @@ TriangleMesh::split() const std::queue facet_queue; std::deque facets; for (int facet_idx = 0; facet_idx < this->stl.stats.number_of_facets; facet_idx++) { - if (seen_facets.find(facet_idx) == seen_facets.end()) { + if (! facet_visited[facet_idx]) { // if facet was not seen put it into queue and start searching facet_queue.push(facet_idx); break; } } - if (facet_queue.empty()) break; - - while (!facet_queue.empty()) { + if (facet_queue.empty()) + break; + + while (! facet_queue.empty()) { int facet_idx = facet_queue.front(); facet_queue.pop(); - if (seen_facets.find(facet_idx) != seen_facets.end()) continue; - facets.push_back(facet_idx); - for (int j = 0; j <= 2; j++) { - facet_queue.push(this->stl.neighbors_start[facet_idx].neighbor[j]); + if (! facet_visited[facet_idx]) { + facets.emplace_back(facet_idx); + for (int j = 0; j < 3; ++ j) + facet_queue.push(this->stl.neighbors_start[facet_idx].neighbor[j]); + facet_visited[facet_idx] = true; } - seen_facets.insert(facet_idx); } - + TriangleMesh* mesh = new TriangleMesh; - meshes.push_back(mesh); + meshes.emplace_back(mesh); mesh->stl.stats.type = inmemory; mesh->stl.stats.number_of_facets = facets.size(); mesh->stl.stats.original_num_facets = mesh->stl.stats.number_of_facets; stl_clear_error(&mesh->stl); stl_allocate(&mesh->stl); - int first = 1; - for (std::deque::const_iterator facet = facets.begin(); facet != facets.end(); ++facet) { + bool first = true; + for (std::deque::const_iterator facet = facets.begin(); facet != facets.end(); ++ facet) { mesh->stl.facet_start[facet - facets.begin()] = this->stl.facet_start[*facet]; stl_facet_stats(&mesh->stl, this->stl.facet_start[*facet], first); - first = 0; } } return meshes; } -void -TriangleMesh::merge(const TriangleMesh &mesh) +void TriangleMesh::merge(const TriangleMesh &mesh) { // reset stats and metadata int number_of_facets = this->stl.stats.number_of_facets; @@ -565,11 +448,11 @@ ExPolygons TriangleMesh::horizontal_projection() const stl_facet* facet = &this->stl.facet_start[i]; Polygon p; p.points.resize(3); - p.points[0] = Point::new_scale(facet->vertex[0].x, facet->vertex[0].y); - p.points[1] = Point::new_scale(facet->vertex[1].x, facet->vertex[1].y); - p.points[2] = Point::new_scale(facet->vertex[2].x, facet->vertex[2].y); + p.points[0] = Point::new_scale(facet->vertex[0](0), facet->vertex[0](1)); + p.points[1] = Point::new_scale(facet->vertex[1](0), facet->vertex[1](1)); + p.points[2] = Point::new_scale(facet->vertex[2](0), facet->vertex[2](1)); p.make_counter_clockwise(); // do this after scaling, as winding order might change while doing that - pp.push_back(p); + pp.emplace_back(p); } // the offset factor was tuned using groovemount.stl @@ -582,27 +465,22 @@ Polygon TriangleMesh::convex_hull() Points pp; pp.reserve(this->stl.stats.shared_vertices); for (int i = 0; i < this->stl.stats.shared_vertices; ++ i) { - stl_vertex* v = &this->stl.v_shared[i]; - pp.emplace_back(Point::new_scale(v->x, v->y)); + const stl_vertex &v = this->stl.v_shared[i]; + pp.emplace_back(Point::new_scale(v(0), v(1))); } return Slic3r::Geometry::convex_hull(pp); } -BoundingBoxf3 -TriangleMesh::bounding_box() const +BoundingBoxf3 TriangleMesh::bounding_box() const { BoundingBoxf3 bb; bb.defined = true; - bb.min.x = this->stl.stats.min.x; - bb.min.y = this->stl.stats.min.y; - bb.min.z = this->stl.stats.min.z; - bb.max.x = this->stl.stats.max.x; - bb.max.y = this->stl.stats.max.y; - bb.max.z = this->stl.stats.max.z; + bb.min = this->stl.stats.min.cast(); + bb.max = this->stl.stats.max.cast(); return bb; } -BoundingBoxf3 TriangleMesh::transformed_bounding_box(const std::vector& matrix) const +BoundingBoxf3 TriangleMesh::transformed_bounding_box(const Transform3d& t) const { bool has_shared = (stl.v_shared != nullptr); if (!has_shared) @@ -613,16 +491,16 @@ BoundingBoxf3 TriangleMesh::transformed_bounding_box(const std::vector& m if (vertices_count == 0) return BoundingBoxf3(); - Eigen::MatrixXf src_vertices(3, vertices_count); + Eigen::MatrixXd src_vertices(3, vertices_count); if (stl.stats.shared_vertices > 0) { stl_vertex* vertex_ptr = stl.v_shared; for (int i = 0; i < stl.stats.shared_vertices; ++i) { - src_vertices(0, i) = vertex_ptr->x; - src_vertices(1, i) = vertex_ptr->y; - src_vertices(2, i) = vertex_ptr->z; + src_vertices(0, i) = (double)(*vertex_ptr)(0); + src_vertices(1, i) = (double)(*vertex_ptr)(1); + src_vertices(2, i) = (double)(*vertex_ptr)(2); vertex_ptr += 1; } } @@ -634,9 +512,9 @@ BoundingBoxf3 TriangleMesh::transformed_bounding_box(const std::vector& m { for (int i = 0; i < 3; ++i) { - src_vertices(0, v_id) = facet_ptr->vertex[i].x; - src_vertices(1, v_id) = facet_ptr->vertex[i].y; - src_vertices(2, v_id) = facet_ptr->vertex[i].z; + src_vertices(0, v_id) = (double)facet_ptr->vertex[i](0); + src_vertices(1, v_id) = (double)facet_ptr->vertex[i](1); + src_vertices(2, v_id) = (double)facet_ptr->vertex[i](2); } facet_ptr += 1; ++v_id; @@ -646,30 +524,22 @@ BoundingBoxf3 TriangleMesh::transformed_bounding_box(const std::vector& m if (!has_shared && (stl.stats.shared_vertices > 0)) stl_invalidate_shared_vertices(&stl); - Eigen::Transform m; - ::memcpy((void*)m.data(), (const void*)matrix.data(), 16 * sizeof(float)); + Eigen::MatrixXd dst_vertices(3, vertices_count); + dst_vertices = t * src_vertices.colwise().homogeneous(); - Eigen::MatrixXf dst_vertices(3, vertices_count); - dst_vertices = m * src_vertices.colwise().homogeneous(); - - float min_x = dst_vertices(0, 0); - float max_x = dst_vertices(0, 0); - float min_y = dst_vertices(1, 0); - float max_y = dst_vertices(1, 0); - float min_z = dst_vertices(2, 0); - float max_z = dst_vertices(2, 0); + Vec3d v_min(dst_vertices(0, 0), dst_vertices(1, 0), dst_vertices(2, 0)); + Vec3d v_max = v_min; for (int i = 1; i < vertices_count; ++i) { - min_x = std::min(min_x, dst_vertices(0, i)); - max_x = std::max(max_x, dst_vertices(0, i)); - min_y = std::min(min_y, dst_vertices(1, i)); - max_y = std::max(max_y, dst_vertices(1, i)); - min_z = std::min(min_z, dst_vertices(2, i)); - max_z = std::max(max_z, dst_vertices(2, i)); + for (int j = 0; j < 3; ++j) + { + v_min(j) = std::min(v_min(j), dst_vertices(j, i)); + v_max(j) = std::max(v_max(j), dst_vertices(j, i)); + } } - return BoundingBoxf3(Pointf3((coordf_t)min_x, (coordf_t)min_y, (coordf_t)min_z), Pointf3((coordf_t)max_x, (coordf_t)max_y, (coordf_t)max_z)); + return BoundingBoxf3(v_min, v_max); } TriangleMesh TriangleMesh::convex_hull_3d() const @@ -688,7 +558,7 @@ TriangleMesh TriangleMesh::convex_hull_3d() const for (int i = 0; i < 3; ++i) { const stl_vertex& v = facet_ptr->vertex[i]; - src_vertices.emplace_back(v.x, v.y, v.z); + src_vertices.emplace_back(v(0), v(1), v(2)); } facet_ptr += 1; @@ -708,8 +578,8 @@ TriangleMesh TriangleMesh::convex_hull_3d() const } // Let's collect results: - Pointf3s det_vertices; - std::vector facets; + Pointf3s dst_vertices; + std::vector facets; auto facet_list = qhull.facetList().toStdVector(); for (const orgQhull::QhullFacet& facet : facet_list) { // iterate through facets @@ -719,19 +589,18 @@ TriangleMesh TriangleMesh::convex_hull_3d() const orgQhull::QhullPoint p = vertices[i].point(); const float* coords = p.coordinates(); - det_vertices.emplace_back(coords[0], coords[1], coords[2]); + dst_vertices.emplace_back(coords[0], coords[1], coords[2]); } - unsigned int size = (unsigned int)det_vertices.size(); + unsigned int size = (unsigned int)dst_vertices.size(); facets.emplace_back(size - 3, size - 2, size - 1); } - TriangleMesh output_mesh(det_vertices, facets); + TriangleMesh output_mesh(dst_vertices, facets); output_mesh.repair(); return output_mesh; } -void -TriangleMesh::require_shared_vertices() +void TriangleMesh::require_shared_vertices() { BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::require_shared_vertices - start"; if (!this->repaired) @@ -751,11 +620,8 @@ TriangleMeshSlicer::TriangleMeshSlicer(TriangleMesh* _mesh) : facets_edges.assign(_mesh->stl.stats.number_of_facets * 3, -1); v_scaled_shared.assign(_mesh->stl.v_shared, _mesh->stl.v_shared + _mesh->stl.stats.shared_vertices); // Scale the copied vertices. - for (int i = 0; i < this->mesh->stl.stats.shared_vertices; ++ i) { - this->v_scaled_shared[i].x /= float(SCALING_FACTOR); - this->v_scaled_shared[i].y /= float(SCALING_FACTOR); - this->v_scaled_shared[i].z /= float(SCALING_FACTOR); - } + for (int i = 0; i < this->mesh->stl.stats.shared_vertices; ++ i) + this->v_scaled_shared[i] *= float(1. / SCALING_FACTOR); // Create a mapping from triangle edge into face. struct EdgeToFace { @@ -829,8 +695,7 @@ TriangleMeshSlicer::TriangleMeshSlicer(TriangleMesh* _mesh) : } } -void -TriangleMeshSlicer::slice(const std::vector &z, std::vector* layers) const +void TriangleMeshSlicer::slice(const std::vector &z, std::vector* layers) const { BOOST_LOG_TRIVIAL(debug) << "TriangleMeshSlicer::slice"; @@ -911,14 +776,14 @@ void TriangleMeshSlicer::_slice_do(size_t facet_idx, std::vectormesh->stl.facet_start[facet_idx]; // find facet extents - const float min_z = fminf(facet.vertex[0].z, fminf(facet.vertex[1].z, facet.vertex[2].z)); - const float max_z = fmaxf(facet.vertex[0].z, fmaxf(facet.vertex[1].z, facet.vertex[2].z)); + const float min_z = fminf(facet.vertex[0](2), fminf(facet.vertex[1](2), facet.vertex[2](2))); + const float max_z = fmaxf(facet.vertex[0](2), fmaxf(facet.vertex[1](2), facet.vertex[2](2))); #ifdef SLIC3R_DEBUG printf("\n==> FACET %d (%f,%f,%f - %f,%f,%f - %f,%f,%f):\n", facet_idx, - facet.vertex[0].x, facet.vertex[0].y, facet.vertex[0].z, - facet.vertex[1].x, facet.vertex[1].y, facet.vertex[1].z, - facet.vertex[2].x, facet.vertex[2].y, facet.vertex[2].z); + facet.vertex[0].x, facet.vertex[0].y, facet.vertex[0](2), + facet.vertex[1].x, facet.vertex[1].y, facet.vertex[1](2), + facet.vertex[2].x, facet.vertex[2].y, facet.vertex[2](2)); printf("z: min = %.2f, max = %.2f\n", min_z, max_z); #endif @@ -938,24 +803,24 @@ void TriangleMeshSlicer::_slice_do(size_t facet_idx, std::vectormesh->stl.v_indices[facet_idx].vertex; - const bool reverse = this->mesh->stl.facet_start[facet_idx].normal.z < 0; + const bool reverse = this->mesh->stl.facet_start[facet_idx].normal(2) < 0; for (int j = 0; j < 3; ++ j) { int a_id = vertices[j % 3]; int b_id = vertices[(j+1) % 3]; if (reverse) std::swap(a_id, b_id); - const stl_vertex *a = &this->v_scaled_shared[a_id]; - const stl_vertex *b = &this->v_scaled_shared[b_id]; - il.a.x = a->x; - il.a.y = a->y; - il.b.x = b->x; - il.b.y = b->y; + const stl_vertex &a = this->v_scaled_shared[a_id]; + const stl_vertex &b = this->v_scaled_shared[b_id]; + il.a(0) = a(0); + il.a(1) = a(1); + il.b(0) = b(0); + il.b(1) = b(1); il.a_id = a_id; il.b_id = b_id; - (*lines)[layer_idx].push_back(il); + (*lines)[layer_idx].emplace_back(il); } } else - (*lines)[layer_idx].push_back(il); + (*lines)[layer_idx].emplace_back(il); } } } @@ -995,66 +860,63 @@ bool TriangleMeshSlicer::slice_facet( // Reorder vertices so that the first one is the one with lowest Z. // This is needed to get all intersection lines in a consistent order // (external on the right of the line) - int i = (facet.vertex[1].z == min_z) ? 1 : ((facet.vertex[2].z == min_z) ? 2 : 0); + int i = (facet.vertex[1](2) == min_z) ? 1 : ((facet.vertex[2](2) == min_z) ? 2 : 0); for (int j = i; j - i < 3; ++ j) { // loop through facet edges int edge_id = this->facets_edges[facet_idx * 3 + (j % 3)]; const int *vertices = this->mesh->stl.v_indices[facet_idx].vertex; int a_id = vertices[j % 3]; int b_id = vertices[(j+1) % 3]; - const stl_vertex *a = &this->v_scaled_shared[a_id]; - const stl_vertex *b = &this->v_scaled_shared[b_id]; + const stl_vertex &a = this->v_scaled_shared[a_id]; + const stl_vertex &b = this->v_scaled_shared[b_id]; // Is edge or face aligned with the cutting plane? - if (a->z == slice_z && b->z == slice_z) { + if (a(2) == slice_z && b(2) == slice_z) { // Edge is horizontal and belongs to the current layer. const stl_vertex &v0 = this->v_scaled_shared[vertices[0]]; const stl_vertex &v1 = this->v_scaled_shared[vertices[1]]; const stl_vertex &v2 = this->v_scaled_shared[vertices[2]]; + bool swap = false; if (min_z == max_z) { // All three vertices are aligned with slice_z. line_out->edge_type = feHorizontal; - if (this->mesh->stl.facet_start[facet_idx].normal.z < 0) { + if (this->mesh->stl.facet_start[facet_idx].normal(2) < 0) { // If normal points downwards this is a bottom horizontal facet so we reverse its point order. - std::swap(a, b); - std::swap(a_id, b_id); + swap = true; } - } else if (v0.z < slice_z || v1.z < slice_z || v2.z < slice_z) { + } else if (v0(2) < slice_z || v1(2) < slice_z || v2(2) < slice_z) { // Two vertices are aligned with the cutting plane, the third vertex is below the cutting plane. line_out->edge_type = feTop; - std::swap(a, b); - std::swap(a_id, b_id); + swap = true; } else { // Two vertices are aligned with the cutting plane, the third vertex is above the cutting plane. line_out->edge_type = feBottom; } - line_out->a.x = a->x; - line_out->a.y = a->y; - line_out->b.x = b->x; - line_out->b.y = b->y; - line_out->a_id = a_id; - line_out->b_id = b_id; + line_out->a = to_2d(swap ? b : a).cast(); + line_out->b = to_2d(swap ? a : b).cast(); + line_out->a_id = swap ? b_id : a_id; + line_out->b_id = swap ? a_id : b_id; return true; } - if (a->z == slice_z) { + if (a(2) == slice_z) { // Only point a alings with the cutting plane. points_on_layer[num_points_on_layer ++] = num_points; IntersectionPoint &point = points[num_points ++]; - point.x = a->x; - point.y = a->y; + point(0) = a(0); + point(1) = a(1); point.point_id = a_id; - } else if (b->z == slice_z) { + } else if (b(2) == slice_z) { // Only point b alings with the cutting plane. points_on_layer[num_points_on_layer ++] = num_points; IntersectionPoint &point = points[num_points ++]; - point.x = b->x; - point.y = b->y; + point(0) = b(0); + point(1) = b(1); point.point_id = b_id; - } else if ((a->z < slice_z && b->z > slice_z) || (b->z < slice_z && a->z > slice_z)) { + } else if ((a(2) < slice_z && b(2) > slice_z) || (b(2) < slice_z && a(2) > slice_z)) { // A general case. The face edge intersects the cutting plane. Calculate the intersection point. IntersectionPoint &point = points[num_points ++]; - point.x = b->x + (a->x - b->x) * (slice_z - b->z) / (a->z - b->z); - point.y = b->y + (a->y - b->y) * (slice_z - b->z) / (a->z - b->z); + point(0) = b(0) + (a(0) - b(0)) * (slice_z - b(2)) / (a(2) - b(2)); + point(1) = b(1) + (a(1) - b(1)) * (slice_z - b(2)) / (a(2) - b(2)); point.edge_id = edge_id; } } @@ -1335,7 +1197,7 @@ void TriangleMeshSlicer::make_loops(std::vector &lines, Polygo // Orient the patched up polygons CCW. This heuristic may close some holes and cavities. double area = 0.; for (size_t i = 0, j = opl.points.size() - 1; i < opl.points.size(); j = i ++) - area += double(opl.points[j].x + opl.points[i].x) * double(opl.points[i].y - opl.points[j].y); + area += double(opl.points[j](0) + opl.points[i](0)) * double(opl.points[i](1) - opl.points[j](1)); if (area < 0) std::reverse(opl.points.begin(), opl.points.end()); loops->emplace_back(std::move(opl.points)); @@ -1362,9 +1224,9 @@ void TriangleMeshSlicer::make_expolygons_simple(std::vector &l if (loop->area() >= 0.) { ExPolygon ex; ex.contour = *loop; - slices->push_back(ex); + slices->emplace_back(ex); } else { - holes.push_back(*loop); + holes.emplace_back(*loop); } } @@ -1455,8 +1317,8 @@ void TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slic //std::vector area; //std::vector sorted_area; // vector of indices //for (Polygons::const_iterator loop = loops.begin(); loop != loops.end(); ++ loop) { - // area.push_back(loop->area()); - // sorted_area.push_back(loop - loops.begin()); + // area.emplace_back(loop->area()); + // sorted_area.emplace_back(loop - loops.begin()); //} // //// outer first @@ -1471,7 +1333,7 @@ void TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slic // would do the same, thus repeating the calculation */ // Polygons::const_iterator loop = loops.begin() + *loop_idx; // if (area[*loop_idx] > +EPSILON) - // p_slices.push_back(*loop); + // p_slices.emplace_back(*loop); // else if (area[*loop_idx] < -EPSILON) // //FIXME This is arbitrary and possibly very slow. // // If the hole is inside a polygon, then there is no need to diff. @@ -1521,20 +1383,20 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower) stl_facet* facet = &this->mesh->stl.facet_start[facet_idx]; // find facet extents - float min_z = std::min(facet->vertex[0].z, std::min(facet->vertex[1].z, facet->vertex[2].z)); - float max_z = std::max(facet->vertex[0].z, std::max(facet->vertex[1].z, facet->vertex[2].z)); + float min_z = std::min(facet->vertex[0](2), std::min(facet->vertex[1](2), facet->vertex[2](2))); + float max_z = std::max(facet->vertex[0](2), std::max(facet->vertex[1](2), facet->vertex[2](2))); // intersect facet with cutting plane IntersectionLine line; if (this->slice_facet(scaled_z, *facet, facet_idx, min_z, max_z, &line)) { // Save intersection lines for generating correct triangulations. if (line.edge_type == feTop) { - lower_lines.push_back(line); + lower_lines.emplace_back(line); } else if (line.edge_type == feBottom) { - upper_lines.push_back(line); + upper_lines.emplace_back(line); } else if (line.edge_type != feHorizontal) { - lower_lines.push_back(line); - upper_lines.push_back(line); + lower_lines.emplace_back(line); + upper_lines.emplace_back(line); } } @@ -1549,47 +1411,47 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower) // look for the vertex on whose side of the slicing plane there are no other vertices int isolated_vertex; - if ( (facet->vertex[0].z > z) == (facet->vertex[1].z > z) ) { + if ( (facet->vertex[0](2) > z) == (facet->vertex[1](2) > z) ) { isolated_vertex = 2; - } else if ( (facet->vertex[1].z > z) == (facet->vertex[2].z > z) ) { + } else if ( (facet->vertex[1](2) > z) == (facet->vertex[2](2) > z) ) { isolated_vertex = 0; } else { isolated_vertex = 1; } // get vertices starting from the isolated one - stl_vertex* v0 = &facet->vertex[isolated_vertex]; - stl_vertex* v1 = &facet->vertex[(isolated_vertex+1) % 3]; - stl_vertex* v2 = &facet->vertex[(isolated_vertex+2) % 3]; + const stl_vertex &v0 = facet->vertex[isolated_vertex]; + const stl_vertex &v1 = facet->vertex[(isolated_vertex+1) % 3]; + const stl_vertex &v2 = facet->vertex[(isolated_vertex+2) % 3]; // intersect v0-v1 and v2-v0 with cutting plane and make new vertices stl_vertex v0v1, v2v0; - v0v1.x = v1->x + (v0->x - v1->x) * (z - v1->z) / (v0->z - v1->z); - v0v1.y = v1->y + (v0->y - v1->y) * (z - v1->z) / (v0->z - v1->z); - v0v1.z = z; - v2v0.x = v2->x + (v0->x - v2->x) * (z - v2->z) / (v0->z - v2->z); - v2v0.y = v2->y + (v0->y - v2->y) * (z - v2->z) / (v0->z - v2->z); - v2v0.z = z; + v0v1(0) = v1(0) + (v0(0) - v1(0)) * (z - v1(2)) / (v0(2) - v1(2)); + v0v1(1) = v1(1) + (v0(1) - v1(1)) * (z - v1(2)) / (v0(2) - v1(2)); + v0v1(2) = z; + v2v0(0) = v2(0) + (v0(0) - v2(0)) * (z - v2(2)) / (v0(2) - v2(2)); + v2v0(1) = v2(1) + (v0(1) - v2(1)) * (z - v2(2)) / (v0(2) - v2(2)); + v2v0(2) = z; // build the triangular facet stl_facet triangle; triangle.normal = facet->normal; - triangle.vertex[0] = *v0; + triangle.vertex[0] = v0; triangle.vertex[1] = v0v1; triangle.vertex[2] = v2v0; // build the facets forming a quadrilateral on the other side stl_facet quadrilateral[2]; quadrilateral[0].normal = facet->normal; - quadrilateral[0].vertex[0] = *v1; - quadrilateral[0].vertex[1] = *v2; + quadrilateral[0].vertex[0] = v1; + quadrilateral[0].vertex[1] = v2; quadrilateral[0].vertex[2] = v0v1; quadrilateral[1].normal = facet->normal; - quadrilateral[1].vertex[0] = *v2; + quadrilateral[1].vertex[0] = v2; quadrilateral[1].vertex[1] = v2v0; quadrilateral[1].vertex[2] = v0v1; - if (v0->z > z) { + if (v0(2) > z) { if (upper != NULL) stl_add_facet(&upper->stl, &triangle); if (lower != NULL) { stl_add_facet(&lower->stl, &quadrilateral[0]); @@ -1621,13 +1483,11 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower) Polygon p = *polygon; p.reverse(); stl_facet facet; - facet.normal.x = 0; - facet.normal.y = 0; - facet.normal.z = -1; + facet.normal = stl_normal(0, 0, -1.f); for (size_t i = 0; i <= 2; ++i) { - facet.vertex[i].x = unscale(p.points[i].x); - facet.vertex[i].y = unscale(p.points[i].y); - facet.vertex[i].z = z; + facet.vertex[i](0) = unscale(p.points[i](0)); + facet.vertex[i](1) = unscale(p.points[i](1)); + facet.vertex[i](2) = z; } stl_add_facet(&upper->stl, &facet); } @@ -1647,13 +1507,11 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower) // convert triangles to facets and append them to mesh for (Polygons::const_iterator polygon = triangles.begin(); polygon != triangles.end(); ++polygon) { stl_facet facet; - facet.normal.x = 0; - facet.normal.y = 0; - facet.normal.z = 1; + facet.normal = stl_normal(0, 0, 1.f); for (size_t i = 0; i <= 2; ++i) { - facet.vertex[i].x = unscale(polygon->points[i].x); - facet.vertex[i].y = unscale(polygon->points[i].y); - facet.vertex[i].z = z; + facet.vertex[i](0) = unscale(polygon->points[i](0)); + facet.vertex[i](1) = unscale(polygon->points[i](1)); + facet.vertex[i](2) = z; } stl_add_facet(&lower->stl, &facet); } @@ -1666,19 +1524,19 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower) // Generate the vertex list for a cube solid of arbitrary size in X/Y/Z. TriangleMesh make_cube(double x, double y, double z) { - Pointf3 pv[8] = { - Pointf3(x, y, 0), Pointf3(x, 0, 0), Pointf3(0, 0, 0), - Pointf3(0, y, 0), Pointf3(x, y, z), Pointf3(0, y, z), - Pointf3(0, 0, z), Pointf3(x, 0, z) + Vec3d pv[8] = { + Vec3d(x, y, 0), Vec3d(x, 0, 0), Vec3d(0, 0, 0), + Vec3d(0, y, 0), Vec3d(x, y, z), Vec3d(0, y, z), + Vec3d(0, 0, z), Vec3d(x, 0, z) }; - Point3 fv[12] = { - Point3(0, 1, 2), Point3(0, 2, 3), Point3(4, 5, 6), - Point3(4, 6, 7), Point3(0, 4, 7), Point3(0, 7, 1), - Point3(1, 7, 6), Point3(1, 6, 2), Point3(2, 6, 5), - Point3(2, 5, 3), Point3(4, 0, 3), Point3(4, 3, 5) + Vec3crd fv[12] = { + Vec3crd(0, 1, 2), Vec3crd(0, 2, 3), Vec3crd(4, 5, 6), + Vec3crd(4, 6, 7), Vec3crd(0, 4, 7), Vec3crd(0, 7, 1), + Vec3crd(1, 7, 6), Vec3crd(1, 6, 2), Vec3crd(2, 6, 5), + Vec3crd(2, 5, 3), Vec3crd(4, 0, 3), Vec3crd(4, 3, 5) }; - std::vector facets(&fv[0], &fv[0]+12); + std::vector facets(&fv[0], &fv[0]+12); Pointf3s vertices(&pv[0], &pv[0]+8); TriangleMesh mesh(vertices ,facets); @@ -1690,11 +1548,11 @@ TriangleMesh make_cube(double x, double y, double z) { // Default is 360 sides, angle fa is in radians. TriangleMesh make_cylinder(double r, double h, double fa) { Pointf3s vertices; - std::vector facets; + std::vector facets; // 2 special vertices, top and bottom center, rest are relative to this - vertices.push_back(Pointf3(0.0, 0.0, 0.0)); - vertices.push_back(Pointf3(0.0, 0.0, h)); + vertices.emplace_back(Vec3d(0.0, 0.0, 0.0)); + vertices.emplace_back(Vec3d(0.0, 0.0, h)); // adjust via rounding to get an even multiple for any provided angle. double angle = (2*PI / floor(2*PI / fa)); @@ -1704,26 +1562,23 @@ TriangleMesh make_cylinder(double r, double h, double fa) { // top and bottom. // Special case: Last line shares 2 vertices with the first line. unsigned id = vertices.size() - 1; - vertices.push_back(Pointf3(sin(0) * r , cos(0) * r, 0)); - vertices.push_back(Pointf3(sin(0) * r , cos(0) * r, h)); + vertices.emplace_back(Vec3d(sin(0) * r , cos(0) * r, 0)); + vertices.emplace_back(Vec3d(sin(0) * r , cos(0) * r, h)); for (double i = 0; i < 2*PI; i+=angle) { - Pointf3 b(0, r, 0); - Pointf3 t(0, r, h); - b.rotate(i, Pointf3(0,0,0)); - t.rotate(i, Pointf3(0,0,h)); - vertices.push_back(b); - vertices.push_back(t); + Vec2d p = Eigen::Rotation2Dd(i) * Eigen::Vector2d(0, r); + vertices.emplace_back(Vec3d(p(0), p(1), 0.)); + vertices.emplace_back(Vec3d(p(0), p(1), h)); id = vertices.size() - 1; - facets.push_back(Point3( 0, id - 1, id - 3)); // top - facets.push_back(Point3(id, 1, id - 2)); // bottom - facets.push_back(Point3(id, id - 2, id - 3)); // upper-right of side - facets.push_back(Point3(id, id - 3, id - 1)); // bottom-left of side + facets.emplace_back(Vec3crd( 0, id - 1, id - 3)); // top + facets.emplace_back(Vec3crd(id, 1, id - 2)); // bottom + facets.emplace_back(Vec3crd(id, id - 2, id - 3)); // upper-right of side + facets.emplace_back(Vec3crd(id, id - 3, id - 1)); // bottom-left of side } // Connect the last set of vertices with the first. - facets.push_back(Point3( 2, 0, id - 1)); - facets.push_back(Point3( 1, 3, id)); - facets.push_back(Point3(id, 3, 2)); - facets.push_back(Point3(id, 2, id - 1)); + facets.emplace_back(Vec3crd( 2, 0, id - 1)); + facets.emplace_back(Vec3crd( 1, 3, id)); + facets.emplace_back(Vec3crd(id, 3, 2)); + facets.emplace_back(Vec3crd(id, 2, id - 1)); TriangleMesh mesh(vertices, facets); return mesh; @@ -1734,7 +1589,7 @@ TriangleMesh make_cylinder(double r, double h, double fa) { // Default angle is 1 degree. TriangleMesh make_sphere(double rho, double fa) { Pointf3s vertices; - std::vector facets; + std::vector facets; // Algorithm: // Add points one-by-one to the sphere grid and form facets using relative coordinates. @@ -1746,29 +1601,24 @@ TriangleMesh make_sphere(double rho, double fa) { // Ring to be scaled to generate the steps of the sphere std::vector ring; for (double i = 0; i < 2*PI; i+=angle) { - ring.push_back(i); + ring.emplace_back(i); } const size_t steps = ring.size(); const double increment = (double)(1.0 / (double)steps); // special case: first ring connects to 0,0,0 // insert and form facets. - vertices.push_back(Pointf3(0.0, 0.0, -rho)); + vertices.emplace_back(Vec3d(0.0, 0.0, -rho)); size_t id = vertices.size(); for (size_t i = 0; i < ring.size(); i++) { // Fixed scaling const double z = -rho + increment*rho*2.0; // radius of the circle for this step. const double r = sqrt(abs(rho*rho - z*z)); - Pointf3 b(0, r, z); - b.rotate(ring[i], Pointf3(0,0,z)); - vertices.push_back(b); - if (i == 0) { - facets.push_back(Point3(1, 0, ring.size())); - } else { - facets.push_back(Point3(id, 0, id - 1)); - } - id++; + Vec2d b = Eigen::Rotation2Dd(ring[i]) * Eigen::Vector2d(0, r); + vertices.emplace_back(Vec3d(b(0), b(1), z)); + facets.emplace_back((i == 0) ? Vec3crd(1, 0, ring.size()) : Vec3crd(id, 0, id - 1)); + ++ id; } // General case: insert and form facets for each step, joining it to the ring below it. @@ -1777,16 +1627,15 @@ TriangleMesh make_sphere(double rho, double fa) { const double r = sqrt(abs(rho*rho - z*z)); for (size_t i = 0; i < ring.size(); i++) { - Pointf3 b(0, r, z); - b.rotate(ring[i], Pointf3(0,0,z)); - vertices.push_back(b); + Vec2d b = Eigen::Rotation2Dd(ring[i]) * Eigen::Vector2d(0, r); + vertices.emplace_back(Vec3d(b(0), b(1), z)); if (i == 0) { // wrap around - facets.push_back(Point3(id + ring.size() - 1 , id, id - 1)); - facets.push_back(Point3(id, id - ring.size(), id - 1)); + facets.emplace_back(Vec3crd(id + ring.size() - 1 , id, id - 1)); + facets.emplace_back(Vec3crd(id, id - ring.size(), id - 1)); } else { - facets.push_back(Point3(id , id - ring.size(), (id - 1) - ring.size())); - facets.push_back(Point3(id, id - 1 - ring.size() , id - 1)); + facets.emplace_back(Vec3crd(id , id - ring.size(), (id - 1) - ring.size())); + facets.emplace_back(Vec3crd(id, id - 1 - ring.size() , id - 1)); } id++; } @@ -1795,13 +1644,13 @@ TriangleMesh make_sphere(double rho, double fa) { // special case: last ring connects to 0,0,rho*2.0 // only form facets. - vertices.push_back(Pointf3(0.0, 0.0, rho)); + vertices.emplace_back(Vec3d(0.0, 0.0, rho)); for (size_t i = 0; i < ring.size(); i++) { if (i == 0) { // third vertex is on the other side of the ring. - facets.push_back(Point3(id, id - ring.size(), id - 1)); + facets.emplace_back(Vec3crd(id, id - ring.size(), id - 1)); } else { - facets.push_back(Point3(id, id - ring.size() + i, id - ring.size() + (i - 1))); + facets.emplace_back(Vec3crd(id, id - ring.size() + i, id - ring.size() + (i - 1))); } } id++; diff --git a/xs/src/libslic3r/TriangleMesh.hpp b/xs/src/libslic3r/TriangleMesh.hpp index 6ab52efe2..e4d377a9d 100644 --- a/xs/src/libslic3r/TriangleMesh.hpp +++ b/xs/src/libslic3r/TriangleMesh.hpp @@ -20,33 +20,33 @@ typedef std::vector TriangleMeshPtrs; class TriangleMesh { public: - TriangleMesh(); - TriangleMesh(const Pointf3s &points, const std::vector &facets); - TriangleMesh(const TriangleMesh &other); - TriangleMesh(TriangleMesh &&other); + TriangleMesh() : repaired(false) { stl_initialize(&this->stl); } + TriangleMesh(const Pointf3s &points, const std::vector &facets); + TriangleMesh(const TriangleMesh &other) : repaired(false) { stl_initialize(&this->stl); *this = other; } + TriangleMesh(TriangleMesh &&other) : repaired(false) { stl_initialize(&this->stl); this->swap(other); } + ~TriangleMesh() { stl_close(&this->stl); } TriangleMesh& operator=(const TriangleMesh &other); - TriangleMesh& operator=(TriangleMesh &&other); - void swap(TriangleMesh &other); - ~TriangleMesh(); - void ReadSTLFile(const char* input_file); - void write_ascii(const char* output_file); - void write_binary(const char* output_file); + TriangleMesh& operator=(TriangleMesh &&other) { this->swap(other); return *this; } + void swap(TriangleMesh &other) { std::swap(this->stl, other.stl); std::swap(this->repaired, other.repaired); } + void ReadSTLFile(const char* input_file) { stl_open(&stl, input_file); } + void write_ascii(const char* output_file) { stl_write_ascii(&this->stl, output_file, ""); } + void write_binary(const char* output_file) { stl_write_binary(&this->stl, output_file, ""); } void repair(); float volume(); void check_topology(); - bool is_manifold() const; + bool is_manifold() const { return this->stl.stats.connected_facets_3_edge == this->stl.stats.number_of_facets; } void WriteOBJFile(char* output_file); void scale(float factor); - void scale(const Pointf3 &versor); + void scale(const Vec3d &versor); void translate(float x, float y, float z); void rotate(float angle, const Axis &axis); - void rotate_x(float angle); - void rotate_y(float angle); - void rotate_z(float angle); + void rotate_x(float angle) { this->rotate(angle, X); } + void rotate_y(float angle) { this->rotate(angle, Y); } + void rotate_z(float angle) { this->rotate(angle, Z); } void mirror(const Axis &axis); - void mirror_x(); - void mirror_y(); - void mirror_z(); + void mirror_x() { this->mirror(X); } + void mirror_y() { this->mirror(Y); } + void mirror_z() { this->mirror(Z); } void transform(const float* matrix3x4); void align_to_origin(); void rotate(double angle, Point* center); @@ -55,13 +55,13 @@ public: ExPolygons horizontal_projection() const; Polygon convex_hull(); BoundingBoxf3 bounding_box() const; - // Returns the bbox of this TriangleMesh transformed by the given matrix - BoundingBoxf3 transformed_bounding_box(const std::vector& matrix) const; + // Returns the bbox of this TriangleMesh transformed by the given transformation + BoundingBoxf3 transformed_bounding_box(const Transform3d& t) const; // Returns the convex hull of this TriangleMesh TriangleMesh convex_hull_3d() const; void reset_repair_stats(); bool needed_repair() const; - size_t facets_count() const; + size_t facets_count() const { return this->stl.stats.number_of_facets; } // Returns true, if there are two and more connected patches in the mesh. // Returns false, if one or zero connected patch is in the mesh. diff --git a/xs/src/libslic3r/libslic3r.h b/xs/src/libslic3r/libslic3r.h index 34f61cb12..6fea64cd1 100644 --- a/xs/src/libslic3r/libslic3r.h +++ b/xs/src/libslic3r/libslic3r.h @@ -45,7 +45,6 @@ typedef double coordf_t; //FIXME Better to use an inline function with an explicit return type. //inline coord_t scale_(coordf_t v) { return coord_t(floor(v / SCALING_FACTOR + 0.5f)); } #define scale_(val) ((val) / SCALING_FACTOR) -#define unscale(val) ((val) * SCALING_FACTOR) #define SCALED_EPSILON scale_(EPSILON) /* Implementation of CONFESS("foo"): */ #ifdef _MSC_VER @@ -102,6 +101,9 @@ inline std::string debug_out_path(const char *name, ...) namespace Slic3r { +template +inline T unscale(Q v) { return T(v) * T(SCALING_FACTOR); } + enum Axis { X=0, Y, Z, E, F, NUM_AXES }; template @@ -130,6 +132,17 @@ inline void append(std::vector& dest, std::vector&& src) src.shrink_to_fit(); } +// Casting an std::vector<> from one type to another type without warnings about a loss of accuracy. +template +std::vector cast(const std::vector &src) +{ + std::vector dst; + dst.reserve(src.size()); + for (const T_FROM &a : src) + dst.emplace_back((T_TO)a); + return dst; +} + template inline void remove_nulls(std::vector &vec) { diff --git a/xs/src/perlglue.cpp b/xs/src/perlglue.cpp index d6bd0e94c..5e0918755 100644 --- a/xs/src/perlglue.cpp +++ b/xs/src/perlglue.cpp @@ -41,9 +41,8 @@ REGISTER_CLASS(BoundingBoxf, "Geometry::BoundingBoxf"); REGISTER_CLASS(BoundingBoxf3, "Geometry::BoundingBoxf3"); REGISTER_CLASS(BridgeDetector, "BridgeDetector"); REGISTER_CLASS(Point, "Point"); -REGISTER_CLASS(Point3, "Point3"); -REGISTER_CLASS(Pointf, "Pointf"); -REGISTER_CLASS(Pointf3, "Pointf3"); +__REGISTER_CLASS(Vec2d, "Pointf"); +__REGISTER_CLASS(Vec3d, "Pointf3"); REGISTER_CLASS(DynamicPrintConfig, "Config"); REGISTER_CLASS(StaticPrintConfig, "Config::Static"); REGISTER_CLASS(PrintObjectConfig, "Config::PrintObject"); @@ -133,7 +132,7 @@ SV* ConfigOption_to_SV(const ConfigOption &opt, const ConfigOptionDef &def) auto optv = static_cast(&opt); AV* av = newAV(); av_fill(av, optv->values.size()-1); - for (const Pointf &v : optv->values) + for (const Vec2d &v : optv->values) av_store(av, &v - optv->values.data(), perl_to_SV_clone_ref(v)); return newRV_noinc((SV*)av); } @@ -263,14 +262,14 @@ bool ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* v return from_SV_check(value, &static_cast(opt)->value); case coPoints: { - std::vector &values = static_cast(opt)->values; + std::vector &values = static_cast(opt)->values; AV* av = (AV*)SvRV(value); const size_t len = av_len(av)+1; values.clear(); values.reserve(len); for (size_t i = 0; i < len; i++) { SV** elem = av_fetch(av, i, 0); - Pointf point; + Vec2d point(Vec2d::Zero()); if (elem == NULL || !from_SV_check(*elem, &point)) return false; values.emplace_back(point); } @@ -485,8 +484,8 @@ SV* to_SV_pureperl(const Point* THIS) { AV* av = newAV(); av_fill(av, 1); - av_store(av, 0, newSViv(THIS->x)); - av_store(av, 1, newSViv(THIS->y)); + av_store(av, 0, newSViv((*THIS)(0))); + av_store(av, 1, newSViv((*THIS)(1))); return newRV_noinc((SV*)av); } @@ -495,8 +494,7 @@ void from_SV(SV* point_sv, Point* point) AV* point_av = (AV*)SvRV(point_sv); // get a double from Perl and round it, otherwise // it would get truncated - point->x = lrint(SvNV(*av_fetch(point_av, 0, 0))); - point->y = lrint(SvNV(*av_fetch(point_av, 1, 0))); + (*point) = Point(SvNV(*av_fetch(point_av, 0, 0)), SvNV(*av_fetch(point_av, 1, 0))); } void from_SV_check(SV* point_sv, Point* point) @@ -510,33 +508,32 @@ void from_SV_check(SV* point_sv, Point* point) } } -SV* to_SV_pureperl(const Pointf* point) +SV* to_SV_pureperl(const Vec2d* point) { AV* av = newAV(); av_fill(av, 1); - av_store(av, 0, newSVnv(point->x)); - av_store(av, 1, newSVnv(point->y)); + av_store(av, 0, newSVnv((*point)(0))); + av_store(av, 1, newSVnv((*point)(1))); return newRV_noinc((SV*)av); } -bool from_SV(SV* point_sv, Pointf* point) +bool from_SV(SV* point_sv, Vec2d* point) { AV* point_av = (AV*)SvRV(point_sv); SV* sv_x = *av_fetch(point_av, 0, 0); SV* sv_y = *av_fetch(point_av, 1, 0); if (!looks_like_number(sv_x) || !looks_like_number(sv_y)) return false; - point->x = SvNV(sv_x); - point->y = SvNV(sv_y); + *point = Vec2d(SvNV(sv_x), SvNV(sv_y)); return true; } -bool from_SV_check(SV* point_sv, Pointf* point) +bool from_SV_check(SV* point_sv, Vec2d* point) { if (sv_isobject(point_sv) && (SvTYPE(SvRV(point_sv)) == SVt_PVMG)) { if (!sv_isa(point_sv, perl_class_name(point)) && !sv_isa(point_sv, perl_class_name_ref(point))) CONFESS("Not a valid %s object (got %s)", perl_class_name(point), HvNAME(SvSTASH(SvRV(point_sv)))); - *point = *(Pointf*)SvIV((SV*)SvRV( point_sv )); + *point = *(Vec2d*)SvIV((SV*)SvRV( point_sv )); return true; } else { return from_SV(point_sv, point); diff --git a/xs/src/poly2tri/common/utils.h b/xs/src/poly2tri/common/utils.h index ffb713f58..4bcb76361 100644 --- a/xs/src/poly2tri/common/utils.h +++ b/xs/src/poly2tri/common/utils.h @@ -33,7 +33,9 @@ #define UTILS_H // Otherwise #defines like M_PI are undeclared under Visual Studio -#define _USE_MATH_DEFINES +#ifndef _USE_MATH_DEFINES + #define _USE_MATH_DEFINES +#endif /* _USE_MATH_DEFINES */ #include #include diff --git a/xs/src/slic3r/AppController.cpp b/xs/src/slic3r/AppController.cpp index 58858f5fc..a3ab0155c 100644 --- a/xs/src/slic3r/AppController.cpp +++ b/xs/src/slic3r/AppController.cpp @@ -319,7 +319,7 @@ void AppController::arrange_model() auto& bedpoints = print_ctl()->config().bed_shape.values; Polyline bed; bed.points.reserve(bedpoints.size()); for(auto& v : bedpoints) - bed.append(Point::new_scale(v.x, v.y)); + bed.append(Point::new_scale(v(0), v(1))); if(pind) pind->update(0, _(L("Arranging objects..."))); diff --git a/xs/src/slic3r/GUI/2DBed.cpp b/xs/src/slic3r/GUI/2DBed.cpp index 6d788cf34..e19f839cd 100644 --- a/xs/src/slic3r/GUI/2DBed.cpp +++ b/xs/src/slic3r/GUI/2DBed.cpp @@ -32,17 +32,17 @@ void Bed_2D::repaint() cw--; ch--; - auto cbb = BoundingBoxf(Pointf(0, 0),Pointf(cw, ch)); + auto cbb = BoundingBoxf(Vec2d(0, 0),Vec2d(cw, ch)); // leave space for origin point - cbb.min.translate(4, 0); - cbb.max.translate(-4, -4); + cbb.min(0) += 4; + cbb.max -= Vec2d(4., 4.); // leave space for origin label - cbb.max.translate(0, -13); + cbb.max(1) -= 13; // read new size - cw = cbb.size().x; - ch = cbb.size().y; + cw = cbb.size()(0); + ch = cbb.size()(1); auto ccenter = cbb.center(); @@ -50,20 +50,20 @@ void Bed_2D::repaint() auto bed_shape = m_bed_shape; auto bed_polygon = Polygon::new_scale(m_bed_shape); auto bb = BoundingBoxf(m_bed_shape); - bb.merge(Pointf(0, 0)); // origin needs to be in the visible area - auto bw = bb.size().x; - auto bh = bb.size().y; + bb.merge(Vec2d(0, 0)); // origin needs to be in the visible area + auto bw = bb.size()(0); + auto bh = bb.size()(1); auto bcenter = bb.center(); // calculate the scaling factor for fitting bed shape in canvas area auto sfactor = std::min(cw/bw, ch/bh); - auto shift = Pointf( - ccenter.x - bcenter.x * sfactor, - ccenter.y - bcenter.y * sfactor + auto shift = Vec2d( + ccenter(0) - bcenter(0) * sfactor, + ccenter(1) - bcenter(1) * sfactor ); m_scale_factor = sfactor; - m_shift = Pointf(shift.x + cbb.min.x, - shift.y - (cbb.max.y - GetSize().GetHeight())); + m_shift = Vec2d(shift(0) + cbb.min(0), + shift(1) - (cbb.max(1) - GetSize().GetHeight())); // draw bed fill dc.SetBrush(wxBrush(wxColour(255, 255, 255), wxSOLID)); @@ -71,19 +71,18 @@ void Bed_2D::repaint() for (auto pt: m_bed_shape) { Point pt_pix = to_pixels(pt); - pt_list.push_back(new wxPoint(pt_pix.x, pt_pix.y)); + pt_list.push_back(new wxPoint(pt_pix(0), pt_pix(1))); } dc.DrawPolygon(&pt_list, 0, 0); // draw grid auto step = 10; // 1cm grid Polylines polylines; - for (auto x = bb.min.x - fmod(bb.min.x, step) + step; x < bb.max.x; x += step) { - Polyline pl = Polyline::new_scale({ Pointf(x, bb.min.y), Pointf(x, bb.max.y) }); - polylines.push_back(pl); + for (auto x = bb.min(0) - fmod(bb.min(0), step) + step; x < bb.max(0); x += step) { + polylines.push_back(Polyline::new_scale({ Vec2d(x, bb.min(1)), Vec2d(x, bb.max(1)) })); } - for (auto y = bb.min.y - fmod(bb.min.y, step) + step; y < bb.max.y; y += step) { - polylines.push_back(Polyline::new_scale({ Pointf(bb.min.x, y), Pointf(bb.max.x, y) })); + for (auto y = bb.min(1) - fmod(bb.min(1), step) + step; y < bb.max(1); y += step) { + polylines.push_back(Polyline::new_scale({ Vec2d(bb.min(0), y), Vec2d(bb.max(0), y) })); } polylines = intersection_pl(polylines, bed_polygon); @@ -91,9 +90,9 @@ void Bed_2D::repaint() for (auto pl : polylines) { for (size_t i = 0; i < pl.points.size()-1; i++){ - Point pt1 = to_pixels(Pointf::new_unscale(pl.points[i])); - Point pt2 = to_pixels(Pointf::new_unscale(pl.points[i+1])); - dc.DrawLine(pt1.x, pt1.y, pt2.x, pt2.y); + Point pt1 = to_pixels(unscale(pl.points[i])); + Point pt2 = to_pixels(unscale(pl.points[i+1])); + dc.DrawLine(pt1(0), pt1(1), pt2(0), pt2(1)); } } @@ -102,65 +101,59 @@ void Bed_2D::repaint() dc.SetBrush(wxBrush(wxColour(0, 0, 0), wxTRANSPARENT)); dc.DrawPolygon(&pt_list, 0, 0); - auto origin_px = to_pixels(Pointf(0, 0)); + auto origin_px = to_pixels(Vec2d(0, 0)); // draw axes auto axes_len = 50; auto arrow_len = 6; auto arrow_angle = Geometry::deg2rad(45.0); dc.SetPen(wxPen(wxColour(255, 0, 0), 2, wxSOLID)); // red - auto x_end = Pointf(origin_px.x + axes_len, origin_px.y); - dc.DrawLine(wxPoint(origin_px.x, origin_px.y), wxPoint(x_end.x, x_end.y)); + auto x_end = Vec2d(origin_px(0) + axes_len, origin_px(1)); + dc.DrawLine(wxPoint(origin_px(0), origin_px(1)), wxPoint(x_end(0), x_end(1))); for (auto angle : { -arrow_angle, arrow_angle }){ - auto end = x_end; - end.translate(-arrow_len, 0); - end.rotate(angle, x_end); - dc.DrawLine(wxPoint(x_end.x, x_end.y), wxPoint(end.x, end.y)); + auto end = Eigen::Translation2d(x_end) * Eigen::Rotation2Dd(angle) * Eigen::Translation2d(- x_end) * Eigen::Vector2d(x_end(0) - arrow_len, x_end(1)); + dc.DrawLine(wxPoint(x_end(0), x_end(1)), wxPoint(end(0), end(1))); } dc.SetPen(wxPen(wxColour(0, 255, 0), 2, wxSOLID)); // green - auto y_end = Pointf(origin_px.x, origin_px.y - axes_len); - dc.DrawLine(wxPoint(origin_px.x, origin_px.y), wxPoint(y_end.x, y_end.y)); + auto y_end = Vec2d(origin_px(0), origin_px(1) - axes_len); + dc.DrawLine(wxPoint(origin_px(0), origin_px(1)), wxPoint(y_end(0), y_end(1))); for (auto angle : { -arrow_angle, arrow_angle }) { - auto end = y_end; - end.translate(0, +arrow_len); - end.rotate(angle, y_end); - dc.DrawLine(wxPoint(y_end.x, y_end.y), wxPoint(end.x, end.y)); + auto end = Eigen::Translation2d(y_end) * Eigen::Rotation2Dd(angle) * Eigen::Translation2d(- y_end) * Eigen::Vector2d(y_end(0), y_end(1) + arrow_len); + dc.DrawLine(wxPoint(y_end(0), y_end(1)), wxPoint(end(0), end(1))); } // draw origin dc.SetPen(wxPen(wxColour(0, 0, 0), 1, wxSOLID)); dc.SetBrush(wxBrush(wxColour(0, 0, 0), wxSOLID)); - dc.DrawCircle(origin_px.x, origin_px.y, 3); + dc.DrawCircle(origin_px(0), origin_px(1), 3); static const auto origin_label = wxString("(0,0)"); dc.SetTextForeground(wxColour(0, 0, 0)); dc.SetFont(wxFont(10, wxDEFAULT, wxNORMAL, wxNORMAL)); auto extent = dc.GetTextExtent(origin_label); - const auto origin_label_x = origin_px.x <= cw / 2 ? origin_px.x + 1 : origin_px.x - 1 - extent.GetWidth(); - const auto origin_label_y = origin_px.y <= ch / 2 ? origin_px.y + 1 : origin_px.y - 1 - extent.GetHeight(); + const auto origin_label_x = origin_px(0) <= cw / 2 ? origin_px(0) + 1 : origin_px(0) - 1 - extent.GetWidth(); + const auto origin_label_y = origin_px(1) <= ch / 2 ? origin_px(1) + 1 : origin_px(1) - 1 - extent.GetHeight(); dc.DrawText(origin_label, origin_label_x, origin_label_y); // draw current position - if (m_pos!= Pointf(0, 0)) { + if (m_pos!= Vec2d(0, 0)) { auto pos_px = to_pixels(m_pos); dc.SetPen(wxPen(wxColour(200, 0, 0), 2, wxSOLID)); dc.SetBrush(wxBrush(wxColour(200, 0, 0), wxTRANSPARENT)); - dc.DrawCircle(pos_px.x, pos_px.y, 5); + dc.DrawCircle(pos_px(0), pos_px(1), 5); - dc.DrawLine(pos_px.x - 15, pos_px.y, pos_px.x + 15, pos_px.y); - dc.DrawLine(pos_px.x, pos_px.y - 15, pos_px.x, pos_px.y + 15); + dc.DrawLine(pos_px(0) - 15, pos_px(1), pos_px(0) + 15, pos_px(1)); + dc.DrawLine(pos_px(0), pos_px(1) - 15, pos_px(0), pos_px(1) + 15); } m_painted = true; } // convert G - code coordinates into pixels -Point Bed_2D::to_pixels(Pointf point){ - auto p = Pointf(point); - p.scale(m_scale_factor); - p.translate(m_shift); - return Point(p.x, GetSize().GetHeight() - p.y); +Point Bed_2D::to_pixels(Vec2d point){ + auto p = point * m_scale_factor + m_shift; + return Point(p(0), GetSize().GetHeight() - p(1)); } void Bed_2D::mouse_event(wxMouseEvent event){ @@ -168,7 +161,7 @@ void Bed_2D::mouse_event(wxMouseEvent event){ if (!m_painted) return; auto pos = event.GetPosition(); - auto point = to_units(Point(pos.x, pos.y)); + auto point = to_units(Point(pos.x, pos.y)); if (event.LeftDown() || event.Dragging()) { if (m_on_move) m_on_move(point) ; @@ -177,14 +170,11 @@ void Bed_2D::mouse_event(wxMouseEvent event){ } // convert pixels into G - code coordinates -Pointf Bed_2D::to_units(Point point){ - auto p = Pointf(point.x, GetSize().GetHeight() - point.y); - p.translate(m_shift.negative()); - p.scale(1 / m_scale_factor); - return p; +Vec2d Bed_2D::to_units(Point point){ + return (Vec2d(point(0), GetSize().GetHeight() - point(1)) - m_shift) * (1. / m_scale_factor); } -void Bed_2D::set_pos(Pointf pos){ +void Bed_2D::set_pos(Vec2d pos){ m_pos = pos; Refresh(); } diff --git a/xs/src/slic3r/GUI/2DBed.hpp b/xs/src/slic3r/GUI/2DBed.hpp index 4b14986a2..d7a7f4260 100644 --- a/xs/src/slic3r/GUI/2DBed.hpp +++ b/xs/src/slic3r/GUI/2DBed.hpp @@ -14,15 +14,15 @@ class Bed_2D : public wxPanel bool m_painted = false; bool m_interactive = false; double m_scale_factor; - Pointf m_shift; - Pointf m_pos; - std::function m_on_move = nullptr; + Vec2d m_shift = Vec2d::Zero(); + Vec2d m_pos = Vec2d::Zero(); + std::function m_on_move = nullptr; - Point to_pixels(Pointf point); - Pointf to_units(Point point); + Point to_pixels(Vec2d point); + Vec2d to_units(Point point); void repaint(); void mouse_event(wxMouseEvent event); - void set_pos(Pointf pos); + void set_pos(Vec2d pos); public: Bed_2D(wxWindow* parent) @@ -41,7 +41,7 @@ public: } ~Bed_2D(){} - std::vector m_bed_shape; + std::vector m_bed_shape; }; diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index dd7a3fb4a..a3f7e0a4c 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -26,11 +26,6 @@ #include "GUI.hpp" -static const float UNIT_MATRIX[] = { 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f }; - namespace Slic3r { void GLIndexedVertexArray::load_mesh_flat_shading(const TriangleMesh &mesh) @@ -44,7 +39,7 @@ void GLIndexedVertexArray::load_mesh_flat_shading(const TriangleMesh &mesh) for (int i = 0; i < mesh.stl.stats.number_of_facets; ++ i) { const stl_facet &facet = mesh.stl.facet_start[i]; for (int j = 0; j < 3; ++ j) - this->push_geometry(facet.vertex[j].x, facet.vertex[j].y, facet.vertex[j].z, facet.normal.x, facet.normal.y, facet.normal.z); + this->push_geometry(facet.vertex[j](0), facet.vertex[j](1), facet.vertex[j](2), facet.normal(0), facet.normal(1), facet.normal(2)); } } @@ -60,7 +55,7 @@ void GLIndexedVertexArray::load_mesh_full_shading(const TriangleMesh &mesh) for (int i = 0; i < mesh.stl.stats.number_of_facets; ++i) { const stl_facet &facet = mesh.stl.facet_start[i]; for (int j = 0; j < 3; ++j) - this->push_geometry(facet.vertex[j].x, facet.vertex[j].y, facet.vertex[j].z, facet.normal.x, facet.normal.y, facet.normal.z); + this->push_geometry(facet.vertex[j](0), facet.vertex[j](1), facet.vertex[j](2), facet.normal(0), facet.normal(1), facet.normal(2)); this->push_triangle(vertices_count, vertices_count + 1, vertices_count + 2); vertices_count += 3; @@ -200,7 +195,8 @@ const float GLVolume::OUTSIDE_COLOR[4] = { 0.0f, 0.38f, 0.8f, 1.0f }; const float GLVolume::SELECTED_OUTSIDE_COLOR[4] = { 0.19f, 0.58f, 1.0f, 1.0f }; GLVolume::GLVolume(float r, float g, float b, float a) - : m_angle_z(0.0f) + : m_origin(0, 0, 0) + , m_angle_z(0.0f) , m_scale_factor(1.0f) , m_transformed_bounding_box_dirty(true) , m_transformed_convex_hull_bounding_box_dirty(true) @@ -257,12 +253,12 @@ void GLVolume::set_render_color() set_render_color(color, 4); } -const Pointf3& GLVolume::get_origin() const +const Vec3d& GLVolume::get_origin() const { return m_origin; } -void GLVolume::set_origin(const Pointf3& origin) +void GLVolume::set_origin(const Vec3d& origin) { if (m_origin != origin) { @@ -297,15 +293,13 @@ void GLVolume::set_convex_hull(const TriangleMesh& convex_hull) m_convex_hull = &convex_hull; } -std::vector GLVolume::world_matrix() const +Transform3d GLVolume::world_matrix() const { - std::vector world_mat(UNIT_MATRIX, std::end(UNIT_MATRIX)); - Eigen::Transform m = Eigen::Transform::Identity(); - m.translate(Eigen::Vector3f((float)m_origin.x, (float)m_origin.y, (float)m_origin.z)); - m.rotate(Eigen::AngleAxisf(m_angle_z, Eigen::Vector3f::UnitZ())); - m.scale(m_scale_factor); - ::memcpy((void*)world_mat.data(), (const void*)m.data(), 16 * sizeof(float)); - return world_mat; + Transform3d matrix = Transform3d::Identity(); + matrix.translate(m_origin); + matrix.rotate(Eigen::AngleAxisd((double)m_angle_z, Vec3d::UnitZ())); + matrix.scale((double)m_scale_factor); + return matrix; } BoundingBoxf3 GLVolume::transformed_bounding_box() const @@ -376,7 +370,7 @@ void GLVolume::render() const ::glCullFace(GL_BACK); ::glPushMatrix(); - ::glTranslated(m_origin.x, m_origin.y, m_origin.z); + ::glTranslated(m_origin(0), m_origin(1), m_origin(2)); ::glRotatef(m_angle_z * 180.0f / PI, 0.0f, 0.0f, 1.0f); ::glScalef(m_scale_factor, m_scale_factor, m_scale_factor); if (this->indexed_vertex_array.indexed()) @@ -410,7 +404,7 @@ void GLVolume::render_using_layer_height() const glUniform1f(z_texture_row_to_normalized_id, (GLfloat)(1.0f / layer_height_texture_height())); if (z_cursor_id >= 0) - glUniform1f(z_cursor_id, (GLfloat)(layer_height_texture_data.print_object->model_object()->bounding_box().max.z * layer_height_texture_data.z_cursor_relative)); + glUniform1f(z_cursor_id, (GLfloat)(layer_height_texture_data.print_object->model_object()->bounding_box().max(2) * layer_height_texture_data.z_cursor_relative)); if (z_cursor_band_width_id >= 0) glUniform1f(z_cursor_band_width_id, (GLfloat)layer_height_texture_data.edit_band_width); @@ -502,7 +496,7 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c ::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr); ::glPushMatrix(); - ::glTranslated(m_origin.x, m_origin.y, m_origin.z); + ::glTranslated(m_origin(0), m_origin(1), m_origin(2)); ::glRotatef(m_angle_z * 180.0f / PI, 0.0f, 0.0f, 1.0f); ::glScalef(m_scale_factor, m_scale_factor, m_scale_factor); @@ -547,7 +541,7 @@ void GLVolume::render_legacy() const ::glNormalPointer(GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data()); ::glPushMatrix(); - ::glTranslated(m_origin.x, m_origin.y, m_origin.z); + ::glTranslated(m_origin(0), m_origin(1), m_origin(2)); ::glRotatef(m_angle_z * 180.0f / PI, 0.0f, 0.0f, 1.0f); ::glScalef(m_scale_factor, m_scale_factor, m_scale_factor); @@ -562,7 +556,7 @@ void GLVolume::render_legacy() const double GLVolume::layer_height_texture_z_to_row_id() const { - return (this->layer_height_texture.get() == nullptr) ? 0.0 : double(this->layer_height_texture->cells - 1) / (double(this->layer_height_texture->width) * this->layer_height_texture_data.print_object->model_object()->bounding_box().max.z); + return (this->layer_height_texture.get() == nullptr) ? 0.0 : double(this->layer_height_texture->cells - 1) / (double(this->layer_height_texture->width) * this->layer_height_texture_data.print_object->model_object()->bounding_box().max(2)); } void GLVolume::generate_layer_height_texture(PrintObject *print_object, bool force) @@ -667,7 +661,7 @@ std::vector GLVolumeCollection::load_object( } v.is_modifier = model_volume->modifier; v.shader_outside_printer_detection_enabled = !model_volume->modifier; - v.set_origin(Pointf3(instance->offset.x, instance->offset.y, 0.0)); + v.set_origin(Vec3d(instance->offset(0), instance->offset(1), 0.0)); v.set_angle_z(instance->rotation); v.set_scale_factor(instance->scaling_factor); } @@ -698,16 +692,16 @@ int GLVolumeCollection::load_wipe_tower_preview( // We'll now create the box with jagged edge. y-coordinates of the pre-generated model are shifted so that the front // edge has y=0 and centerline of the back edge has y=depth: Pointf3s points; - std::vector facets; + std::vector facets; float out_points_idx[][3] = {{0, -depth, 0}, {0, 0, 0}, {38.453, 0, 0}, {61.547, 0, 0}, {100, 0, 0}, {100, -depth, 0}, {55.7735, -10, 0}, {44.2265, 10, 0}, {38.453, 0, 1}, {0, 0, 1}, {0, -depth, 1}, {100, -depth, 1}, {100, 0, 1}, {61.547, 0, 1}, {55.7735, -10, 1}, {44.2265, 10, 1}}; int out_facets_idx[][3] = {{0, 1, 2}, {3, 4, 5}, {6, 5, 0}, {3, 5, 6}, {6, 2, 7}, {6, 0, 2}, {8, 9, 10}, {11, 12, 13}, {10, 11, 14}, {14, 11, 13}, {15, 8, 14}, {8, 10, 14}, {3, 12, 4}, {3, 13, 12}, {6, 13, 3}, {6, 14, 13}, {7, 14, 6}, {7, 15, 14}, {2, 15, 7}, {2, 8, 15}, {1, 8, 2}, {1, 9, 8}, {0, 9, 1}, {0, 10, 9}, {5, 10, 0}, {5, 11, 10}, {4, 11, 5}, {4, 12, 11}}; for (int i=0;i<16;++i) - points.push_back(Pointf3(out_points_idx[i][0] / (100.f/min_width), out_points_idx[i][1] + depth, out_points_idx[i][2])); + points.push_back(Vec3d(out_points_idx[i][0] / (100.f/min_width), out_points_idx[i][1] + depth, out_points_idx[i][2])); for (int i=0;i<28;++i) - facets.push_back(Point3(out_facets_idx[i][0], out_facets_idx[i][1], out_facets_idx[i][2])); + facets.push_back(Vec3crd(out_facets_idx[i][0], out_facets_idx[i][1], out_facets_idx[i][2])); TriangleMesh tooth_mesh(points, facets); // We have the mesh ready. It has one tooth and width of min_width. We will now append several of these together until we are close to @@ -718,7 +712,7 @@ int GLVolumeCollection::load_wipe_tower_preview( tooth_mesh.translate(min_width, 0.f, 0.f); } - mesh.scale(Pointf3(width/(n*min_width), 1.f, height)); // Scaling to proper width + mesh.scale(Vec3d(width/(n*min_width), 1.f, height)); // Scaling to proper width } else mesh = make_cube(width, depth, height); @@ -738,7 +732,7 @@ int GLVolumeCollection::load_wipe_tower_preview( else v.indexed_vertex_array.load_mesh_flat_shading(mesh); - v.set_origin(Pointf3(pos_x, pos_y, 0.)); + v.set_origin(Vec3d(pos_x, pos_y, 0.)); // finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry(). v.bounding_box = v.indexed_vertex_array.bounding_box(); @@ -824,9 +818,9 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M return false; BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values)); - BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(unscale(bed_box_2D.max.x), unscale(bed_box_2D.max.y), config->opt_float("max_print_height"))); + BoundingBoxf3 print_volume(unscale(bed_box_2D.min(0), bed_box_2D.min(1), 0.0), unscale(bed_box_2D.max(0), bed_box_2D.max(1), unscale(config->opt_float("max_print_height")))); // Allow the objects to protrude below the print bed - print_volume.min.z = -1e10; + print_volume.min(2) = -1e10; ModelInstance::EPrintVolumeState state = ModelInstance::PVS_Inside; bool all_contained = true; @@ -989,8 +983,8 @@ static void thick_lines_to_indexed_vertex_array( // right, left, top, bottom int idx_prev[4] = { -1, -1, -1, -1 }; double bottom_z_prev = 0.; - Pointf b1_prev; - Vectorf v_prev; + Vec2d b1_prev(Vec2d::Zero()); + Vec2d v_prev(Vec2d::Zero()); int idx_initial[4] = { -1, -1, -1, -1 }; double width_initial = 0.; double bottom_z_initial = 0.0; @@ -1000,7 +994,7 @@ static void thick_lines_to_indexed_vertex_array( for (size_t ii = 0; ii < lines_end; ++ ii) { size_t i = (ii == lines.size()) ? 0 : ii; const Line &line = lines[i]; - double len = unscale(line.length()); + double len = unscale(line.length()); double inv_len = 1.0 / len; double bottom_z = top_z - heights[i]; double middle_z = 0.5 * (top_z + bottom_z); @@ -1010,29 +1004,29 @@ static void thick_lines_to_indexed_vertex_array( bool is_last = (ii == lines_end - 1); bool is_closing = closed && is_last; - Vectorf v = Vectorf::new_unscale(line.vector()); - v.scale(inv_len); + Vec2d v = unscale(line.vector()); + v *= inv_len; - Pointf a = Pointf::new_unscale(line.a); - Pointf b = Pointf::new_unscale(line.b); - Pointf a1 = a; - Pointf a2 = a; - Pointf b1 = b; - Pointf b2 = b; + Vec2d a = unscale(line.a); + Vec2d b = unscale(line.b); + Vec2d a1 = a; + Vec2d a2 = a; + Vec2d b1 = b; + Vec2d b2 = b; { double dist = 0.5 * width; // scaled - double dx = dist * v.x; - double dy = dist * v.y; - a1.translate(+dy, -dx); - a2.translate(-dy, +dx); - b1.translate(+dy, -dx); - b2.translate(-dy, +dx); + double dx = dist * v(0); + double dy = dist * v(1); + a1 += Vec2d(+dy, -dx); + a2 += Vec2d(-dy, +dx); + b1 += Vec2d(+dy, -dx); + b2 += Vec2d(-dy, +dx); } // calculate new XY normals Vector n = line.normal(); - Vectorf3 xy_right_normal = Vectorf3::new_unscale(n.x, n.y, 0); - xy_right_normal.scale(inv_len); + Vec3d xy_right_normal = unscale(n(0), n(1), 0); + xy_right_normal *= inv_len; int idx_a[4]; int idx_b[4]; @@ -1050,7 +1044,7 @@ static void thick_lines_to_indexed_vertex_array( // Share top / bottom vertices if possible. if (is_first) { idx_a[TOP] = idx_last++; - volume.push_geometry(a.x, a.y, top_z , 0., 0., 1.); + volume.push_geometry(a(0), a(1), top_z , 0., 0., 1.); } else { idx_a[TOP] = idx_prev[TOP]; } @@ -1058,11 +1052,11 @@ static void thick_lines_to_indexed_vertex_array( if (is_first || bottom_z_different) { // Start of the 1st line segment or a change of the layer thickness while maintaining the print_z. idx_a[BOTTOM] = idx_last ++; - volume.push_geometry(a.x, a.y, bottom_z, 0., 0., -1.); + volume.push_geometry(a(0), a(1), bottom_z, 0., 0., -1.); idx_a[LEFT ] = idx_last ++; - volume.push_geometry(a2.x, a2.y, middle_z, -xy_right_normal.x, -xy_right_normal.y, -xy_right_normal.z); + volume.push_geometry(a2(0), a2(1), middle_z, -xy_right_normal(0), -xy_right_normal(1), -xy_right_normal(2)); idx_a[RIGHT] = idx_last ++; - volume.push_geometry(a1.x, a1.y, middle_z, xy_right_normal.x, xy_right_normal.y, xy_right_normal.z); + volume.push_geometry(a1(0), a1(1), middle_z, xy_right_normal(0), xy_right_normal(1), xy_right_normal(2)); } else { idx_a[BOTTOM] = idx_prev[BOTTOM]; @@ -1076,16 +1070,16 @@ static void thick_lines_to_indexed_vertex_array( } else { // Continuing a previous segment. // Share left / right vertices if possible. - double v_dot = dot(v_prev, v); + double v_dot = v_prev.dot(v); bool sharp = v_dot < 0.707; // sin(45 degrees) if (sharp) { if (!bottom_z_different) { // Allocate new left / right points for the start of this segment as these points will receive their own normals to indicate a sharp turn. idx_a[RIGHT] = idx_last++; - volume.push_geometry(a1.x, a1.y, middle_z, xy_right_normal.x, xy_right_normal.y, xy_right_normal.z); + volume.push_geometry(a1(0), a1(1), middle_z, xy_right_normal(0), xy_right_normal(1), xy_right_normal(2)); idx_a[LEFT] = idx_last++; - volume.push_geometry(a2.x, a2.y, middle_z, -xy_right_normal.x, -xy_right_normal.y, -xy_right_normal.z); + volume.push_geometry(a2(0), a2(1), middle_z, -xy_right_normal(0), -xy_right_normal(1), -xy_right_normal(2)); } } if (v_dot > 0.9) { @@ -1101,32 +1095,32 @@ static void thick_lines_to_indexed_vertex_array( { // Create a sharp corner with an overshot and average the left / right normals. // At the crease angle of 45 degrees, the overshot at the corner will be less than (1-1/cos(PI/8)) = 8.2% over an arc. - Pointf intersection; + Vec2d intersection(Vec2d::Zero()); Geometry::ray_ray_intersection(b1_prev, v_prev, a1, v, intersection); a1 = intersection; a2 = 2. * a - intersection; - assert(length(a1.vector_to(a)) < width); - assert(length(a2.vector_to(a)) < width); + assert((a - a1).norm() < width); + assert((a - a2).norm() < width); float *n_left_prev = volume.vertices_and_normals_interleaved.data() + idx_prev[LEFT ] * 6; float *p_left_prev = n_left_prev + 3; float *n_right_prev = volume.vertices_and_normals_interleaved.data() + idx_prev[RIGHT] * 6; float *p_right_prev = n_right_prev + 3; - p_left_prev [0] = float(a2.x); - p_left_prev [1] = float(a2.y); - p_right_prev[0] = float(a1.x); - p_right_prev[1] = float(a1.y); - xy_right_normal.x += n_right_prev[0]; - xy_right_normal.y += n_right_prev[1]; - xy_right_normal.scale(1. / length(xy_right_normal)); - n_left_prev [0] = float(-xy_right_normal.x); - n_left_prev [1] = float(-xy_right_normal.y); - n_right_prev[0] = float( xy_right_normal.x); - n_right_prev[1] = float( xy_right_normal.y); + p_left_prev [0] = float(a2(0)); + p_left_prev [1] = float(a2(1)); + p_right_prev[0] = float(a1(0)); + p_right_prev[1] = float(a1(1)); + xy_right_normal(0) += n_right_prev[0]; + xy_right_normal(1) += n_right_prev[1]; + xy_right_normal *= 1. / xy_right_normal.norm(); + n_left_prev [0] = float(-xy_right_normal(0)); + n_left_prev [1] = float(-xy_right_normal(1)); + n_right_prev[0] = float( xy_right_normal(0)); + n_right_prev[1] = float( xy_right_normal(1)); idx_a[LEFT ] = idx_prev[LEFT ]; idx_a[RIGHT] = idx_prev[RIGHT]; } } - else if (cross(v_prev, v) > 0.) { + else if (cross2(v_prev, v) > 0.) { // Right turn. Fill in the right turn wedge. volume.push_triangle(idx_prev[RIGHT], idx_a [RIGHT], idx_prev[TOP] ); volume.push_triangle(idx_prev[RIGHT], idx_prev[BOTTOM], idx_a [RIGHT] ); @@ -1162,20 +1156,20 @@ static void thick_lines_to_indexed_vertex_array( idx_b[TOP] = idx_initial[TOP]; } else { idx_b[TOP] = idx_last ++; - volume.push_geometry(b.x, b.y, top_z , 0., 0., 1.); + volume.push_geometry(b(0), b(1), top_z , 0., 0., 1.); } if (is_closing && (width == width_initial) && (bottom_z == bottom_z_initial)) { idx_b[BOTTOM] = idx_initial[BOTTOM]; } else { idx_b[BOTTOM] = idx_last ++; - volume.push_geometry(b.x, b.y, bottom_z, 0., 0., -1.); + volume.push_geometry(b(0), b(1), bottom_z, 0., 0., -1.); } // Generate new vertices for the end of this line segment. idx_b[LEFT ] = idx_last ++; - volume.push_geometry(b2.x, b2.y, middle_z, -xy_right_normal.x, -xy_right_normal.y, -xy_right_normal.z); + volume.push_geometry(b2(0), b2(1), middle_z, -xy_right_normal(0), -xy_right_normal(1), -xy_right_normal(2)); idx_b[RIGHT ] = idx_last ++; - volume.push_geometry(b1.x, b1.y, middle_z, xy_right_normal.x, xy_right_normal.y, xy_right_normal.z); + volume.push_geometry(b1(0), b1(1), middle_z, xy_right_normal(0), xy_right_normal(1), xy_right_normal(2)); memcpy(idx_prev, idx_b, 4 * sizeof(int)); bottom_z_prev = bottom_z; @@ -1234,15 +1228,15 @@ static void thick_lines_to_indexed_vertex_array(const Lines3& lines, int idx_initial[4] = { -1, -1, -1, -1 }; int idx_prev[4] = { -1, -1, -1, -1 }; double z_prev = 0.0; - Vectorf3 n_right_prev; - Vectorf3 n_top_prev; - Vectorf3 unit_v_prev; + Vec3d n_right_prev = Vec3d::Zero(); + Vec3d n_top_prev = Vec3d::Zero(); + Vec3d unit_v_prev = Vec3d::Zero(); double width_initial = 0.0; // new vertices around the line endpoints // left, right, top, bottom - Pointf3 a[4]; - Pointf3 b[4]; + Vec3d a[4] = { Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero() }; + Vec3d b[4] = { Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero() }; // loop once more in case of closed loops size_t lines_end = closed ? (lines.size() + 1) : lines.size(); @@ -1254,29 +1248,29 @@ static void thick_lines_to_indexed_vertex_array(const Lines3& lines, double height = heights[i]; double width = widths[i]; - Vectorf3 unit_v = normalize(Vectorf3::new_unscale(line.vector())); + Vec3d unit_v = unscale(line.vector()).normalized(); - Vectorf3 n_top; - Vectorf3 n_right; - Vectorf3 unit_positive_z(0.0, 0.0, 1.0); + Vec3d n_top = Vec3d::Zero(); + Vec3d n_right = Vec3d::Zero(); + Vec3d unit_positive_z(0.0, 0.0, 1.0); - if ((line.a.x == line.b.x) && (line.a.y == line.b.y)) + if ((line.a(0) == line.b(0)) && (line.a(1) == line.b(1))) { // vertical segment - n_right = (line.a.z < line.b.z) ? Vectorf3(-1.0, 0.0, 0.0) : Vectorf3(1.0, 0.0, 0.0); - n_top = Vectorf3(0.0, 1.0, 0.0); + n_right = (line.a(2) < line.b(2)) ? Vec3d(-1.0, 0.0, 0.0) : Vec3d(1.0, 0.0, 0.0); + n_top = Vec3d(0.0, 1.0, 0.0); } else { // generic segment - n_right = normalize(cross(unit_v, unit_positive_z)); - n_top = normalize(cross(n_right, unit_v)); + n_right = unit_v.cross(unit_positive_z).normalized(); + n_top = n_right.cross(unit_v).normalized(); } - Vectorf3 rl_displacement = 0.5 * width * n_right; - Vectorf3 tb_displacement = 0.5 * height * n_top; - Pointf3 l_a = Pointf3::new_unscale(line.a); - Pointf3 l_b = Pointf3::new_unscale(line.b); + Vec3d rl_displacement = 0.5 * width * n_right; + Vec3d tb_displacement = 0.5 * height * n_top; + Vec3d l_a = unscale(line.a); + Vec3d l_b = unscale(line.b); a[RIGHT] = l_a + rl_displacement; a[LEFT] = l_a - rl_displacement; @@ -1287,15 +1281,15 @@ static void thick_lines_to_indexed_vertex_array(const Lines3& lines, b[TOP] = l_b + tb_displacement; b[BOTTOM] = l_b - tb_displacement; - Vectorf3 n_bottom = -n_top; - Vectorf3 n_left = -n_right; + Vec3d n_bottom = -n_top; + Vec3d n_left = -n_right; int idx_a[4]; int idx_b[4]; int idx_last = int(volume.vertices_and_normals_interleaved.size() / 6); - bool z_different = (z_prev != l_a.z); - z_prev = l_b.z; + bool z_different = (z_prev != l_a(2)); + z_prev = l_b(2); // Share top / bottom vertices if possible. if (ii == 0) @@ -1329,9 +1323,9 @@ static void thick_lines_to_indexed_vertex_array(const Lines3& lines, { // Continuing a previous segment. // Share left / right vertices if possible. - double v_dot = dot(unit_v_prev, unit_v); + double v_dot = unit_v_prev.dot(unit_v); bool is_sharp = v_dot < 0.707; // sin(45 degrees) - bool is_right_turn = dot(n_top_prev, cross(unit_v_prev, unit_v)) > 0.0; + bool is_right_turn = n_top_prev.dot(unit_v_prev.cross(unit_v)) > 0.0; if (is_sharp) { @@ -1354,9 +1348,9 @@ static void thick_lines_to_indexed_vertex_array(const Lines3& lines, // At the crease angle of 45 degrees, the overshot at the corner will be less than (1-1/cos(PI/8)) = 8.2% over an arc. // averages normals - Vectorf3 average_n_right = normalize(0.5 * (n_right + n_right_prev)); - Vectorf3 average_n_left = -average_n_right; - Vectorf3 average_rl_displacement = 0.5 * width * average_n_right; + Vec3d average_n_right = 0.5 * (n_right + n_right_prev).normalized(); + Vec3d average_n_left = -average_n_right; + Vec3d average_rl_displacement = 0.5 * width * average_n_right; // updates vertices around a a[RIGHT] = l_a + average_rl_displacement; @@ -1364,25 +1358,25 @@ static void thick_lines_to_indexed_vertex_array(const Lines3& lines, // updates previous line normals float* normal_left_prev = volume.vertices_and_normals_interleaved.data() + idx_prev[LEFT] * 6; - normal_left_prev[0] = float(average_n_left.x); - normal_left_prev[1] = float(average_n_left.y); - normal_left_prev[2] = float(average_n_left.z); + normal_left_prev[0] = float(average_n_left(0)); + normal_left_prev[1] = float(average_n_left(1)); + normal_left_prev[2] = float(average_n_left(2)); float* normal_right_prev = volume.vertices_and_normals_interleaved.data() + idx_prev[RIGHT] * 6; - normal_right_prev[0] = float(average_n_right.x); - normal_right_prev[1] = float(average_n_right.y); - normal_right_prev[2] = float(average_n_right.z); + normal_right_prev[0] = float(average_n_right(0)); + normal_right_prev[1] = float(average_n_right(1)); + normal_right_prev[2] = float(average_n_right(2)); // updates previous line's vertices around b float* b_left_prev = normal_left_prev + 3; - b_left_prev[0] = float(a[LEFT].x); - b_left_prev[1] = float(a[LEFT].y); - b_left_prev[2] = float(a[LEFT].z); + b_left_prev[0] = float(a[LEFT](0)); + b_left_prev[1] = float(a[LEFT](1)); + b_left_prev[2] = float(a[LEFT](2)); float* b_right_prev = normal_right_prev + 3; - b_right_prev[0] = float(a[RIGHT].x); - b_right_prev[1] = float(a[RIGHT].y); - b_right_prev[2] = float(a[RIGHT].z); + b_right_prev[0] = float(a[RIGHT](0)); + b_right_prev[1] = float(a[RIGHT](1)); + b_right_prev[2] = float(a[RIGHT](2)); idx_a[LEFT] = idx_prev[LEFT]; idx_a[RIGHT] = idx_prev[RIGHT]; @@ -1479,14 +1473,14 @@ static void thick_lines_to_indexed_vertex_array(const Lines3& lines, #undef BOTTOM } -static void point_to_indexed_vertex_array(const Point3& point, +static void point_to_indexed_vertex_array(const Vec3crd& point, double width, double height, GLIndexedVertexArray& volume) { // builds a double piramid, with vertices on the local axes, around the point - Pointf3 center = Pointf3::new_unscale(point); + Vec3d center = unscale(point); double scale_factor = 1.0; double w = scale_factor * width; @@ -1500,13 +1494,13 @@ static void point_to_indexed_vertex_array(const Point3& point, idxs[i] = idx_last + i; } - Vectorf3 displacement_x(w, 0.0, 0.0); - Vectorf3 displacement_y(0.0, w, 0.0); - Vectorf3 displacement_z(0.0, 0.0, h); + Vec3d displacement_x(w, 0.0, 0.0); + Vec3d displacement_y(0.0, w, 0.0); + Vec3d displacement_z(0.0, 0.0, h); - Vectorf3 unit_x(1.0, 0.0, 0.0); - Vectorf3 unit_y(0.0, 1.0, 0.0); - Vectorf3 unit_z(0.0, 0.0, 1.0); + Vec3d unit_x(1.0, 0.0, 0.0); + Vec3d unit_y(0.0, 1.0, 0.0); + Vec3d unit_z(0.0, 0.0, 1.0); // vertices volume.push_geometry(center - displacement_x, -unit_x); // idxs[0] @@ -1549,7 +1543,7 @@ void _3DScene::thick_lines_to_verts(const Lines3& lines, thick_lines_to_indexed_vertex_array(lines, widths, heights, closed, volume.indexed_vertex_array); } -static void thick_point_to_verts(const Point3& point, +static void thick_point_to_verts(const Vec3crd& point, double width, double height, GLVolume& volume) @@ -1655,7 +1649,7 @@ void _3DScene::polyline3_to_verts(const Polyline3& polyline, double width, doubl thick_lines_to_verts(lines, widths, heights, false, volume); } -void _3DScene::point3_to_verts(const Point3& point, double width, double height, GLVolume& volume) +void _3DScene::point3_to_verts(const Vec3crd& point, double width, double height, GLVolume& volume) { thick_point_to_verts(point, width, height, volume); } diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp index 4290f5bda..ac3a53fe3 100644 --- a/xs/src/slic3r/GUI/3DScene.hpp +++ b/xs/src/slic3r/GUI/3DScene.hpp @@ -119,8 +119,8 @@ public: push_geometry(float(x), float(y), float(z), float(nx), float(ny), float(nz)); } - inline void push_geometry(const Pointf3& p, const Vectorf3& n) { - push_geometry(p.x, p.y, p.z, n.x, n.y, n.z); + inline void push_geometry(const Vec3d& p, const Vec3d& n) { + push_geometry(p(0), p(1), p(2), n(0), n(1), n(2)); } inline void push_triangle(int idx1, int idx2, int idx3) { @@ -176,17 +176,17 @@ public: BoundingBoxf3 bbox; if (! this->vertices_and_normals_interleaved.empty()) { bbox.defined = true; - bbox.min.x = bbox.max.x = this->vertices_and_normals_interleaved[3]; - bbox.min.y = bbox.max.y = this->vertices_and_normals_interleaved[4]; - bbox.min.z = bbox.max.z = this->vertices_and_normals_interleaved[5]; + bbox.min(0) = bbox.max(0) = this->vertices_and_normals_interleaved[3]; + bbox.min(1) = bbox.max(1) = this->vertices_and_normals_interleaved[4]; + bbox.min(2) = bbox.max(2) = this->vertices_and_normals_interleaved[5]; for (size_t i = 9; i < this->vertices_and_normals_interleaved.size(); i += 6) { const float *verts = this->vertices_and_normals_interleaved.data() + i; - bbox.min.x = std::min(bbox.min.x, verts[0]); - bbox.min.y = std::min(bbox.min.y, verts[1]); - bbox.min.z = std::min(bbox.min.z, verts[2]); - bbox.max.x = std::max(bbox.max.x, verts[0]); - bbox.max.y = std::max(bbox.max.y, verts[1]); - bbox.max.z = std::max(bbox.max.z, verts[2]); + bbox.min(0) = std::min(bbox.min(0), verts[0]); + bbox.min(1) = std::min(bbox.min(1), verts[1]); + bbox.min(2) = std::min(bbox.min(2), verts[2]); + bbox.max(0) = std::max(bbox.max(0), verts[0]); + bbox.max(1) = std::max(bbox.max(1), verts[1]); + bbox.max(2) = std::max(bbox.max(2), verts[2]); } } return bbox; @@ -255,7 +255,7 @@ public: private: // Offset of the volume to be rendered. - Pointf3 m_origin; + Vec3d m_origin; // Rotation around Z axis of the volume to be rendered. float m_angle_z; // Scale factor of the volume to be rendered. @@ -323,8 +323,8 @@ public: // Sets render color in dependence of current state void set_render_color(); - const Pointf3& get_origin() const; - void set_origin(const Pointf3& origin); + const Vec3d& get_origin() const; + void set_origin(const Vec3d& origin); void set_angle_z(float angle_z); void set_scale_factor(float scale_factor); void set_convex_hull(const TriangleMesh& convex_hull); @@ -333,7 +333,7 @@ public: int volume_idx() const { return (this->composite_id / 1000) % 1000; } int instance_idx() const { return this->composite_id % 1000; } - std::vector world_matrix() const; + Transform3d world_matrix() const; BoundingBoxf3 transformed_bounding_box() const; BoundingBoxf3 transformed_convex_hull_bounding_box() const; @@ -577,7 +577,7 @@ public: static void extrusionentity_to_verts(const ExtrusionEntityCollection& extrusion_entity_collection, float print_z, const Point& copy, GLVolume& volume); static void extrusionentity_to_verts(const ExtrusionEntity* extrusion_entity, float print_z, const Point& copy, GLVolume& volume); static void polyline3_to_verts(const Polyline3& polyline, double width, double height, GLVolume& volume); - static void point3_to_verts(const Point3& point, double width, double height, GLVolume& volume); + static void point3_to_verts(const Vec3crd& point, double width, double height, GLVolume& volume); }; } diff --git a/xs/src/slic3r/GUI/BedShapeDialog.cpp b/xs/src/slic3r/GUI/BedShapeDialog.cpp index d52535589..e04f2b370 100644 --- a/xs/src/slic3r/GUI/BedShapeDialog.cpp +++ b/xs/src/slic3r/GUI/BedShapeDialog.cpp @@ -48,14 +48,14 @@ void BedShapePanel::build_panel(ConfigOptionPoints* default_pt) auto optgroup = init_shape_options_page(_(L("Rectangular"))); ConfigOptionDef def; def.type = coPoints; - def.default_value = new ConfigOptionPoints{ Pointf(200, 200) }; + def.default_value = new ConfigOptionPoints{ Vec2d(200, 200) }; def.label = L("Size"); def.tooltip = L("Size in X and Y of the rectangular plate."); Option option(def, "rect_size"); optgroup->append_single_option_line(option); def.type = coPoints; - def.default_value = new ConfigOptionPoints{ Pointf(0, 0) }; + def.default_value = new ConfigOptionPoints{ Vec2d(0, 0) }; def.label = L("Origin"); def.tooltip = L("Distance of the 0,0 G-code coordinate from the front left corner of the rectangle."); option = Option(def, "rect_origin"); @@ -149,21 +149,21 @@ void BedShapePanel::set_shape(ConfigOptionPoints* points) // okay, it's a rectangle // find origin coordf_t x_min, x_max, y_min, y_max; - x_max = x_min = points->values[0].x; - y_max = y_min = points->values[0].y; + x_max = x_min = points->values[0](0); + y_max = y_min = points->values[0](1); for (auto pt : points->values) { - x_min = std::min(x_min, pt.x); - x_max = std::max(x_max, pt.x); - y_min = std::min(y_min, pt.y); - y_max = std::max(y_max, pt.y); + x_min = std::min(x_min, pt(0)); + x_max = std::max(x_max, pt(0)); + y_min = std::min(y_min, pt(1)); + y_max = std::max(y_max, pt(1)); } - auto origin = new ConfigOptionPoints{ Pointf(-x_min, -y_min) }; + auto origin = new ConfigOptionPoints{ Vec2d(-x_min, -y_min) }; m_shape_options_book->SetSelection(SHAPE_RECTANGULAR); auto optgroup = m_optgroups[SHAPE_RECTANGULAR]; - optgroup->set_value("rect_size", new ConfigOptionPoints{ Pointf(x_max - x_min, y_max - y_min) });//[x_max - x_min, y_max - y_min]); + optgroup->set_value("rect_size", new ConfigOptionPoints{ Vec2d(x_max - x_min, y_max - y_min) });//[x_max - x_min, y_max - y_min]); optgroup->set_value("rect_origin", origin); update_shape(); return; @@ -178,7 +178,7 @@ void BedShapePanel::set_shape(ConfigOptionPoints* points) double avg_dist = 0; for (auto pt: polygon.points) { - double distance = center.distance_to(pt); + double distance = (pt - center).cast().norm(); vertex_distances.push_back(distance); avg_dist += distance; } @@ -195,7 +195,7 @@ void BedShapePanel::set_shape(ConfigOptionPoints* points) // all vertices are equidistant to center m_shape_options_book->SetSelection(SHAPE_CIRCULAR); auto optgroup = m_optgroups[SHAPE_CIRCULAR]; - boost::any ret = wxNumberFormatter::ToString(unscale(avg_dist * 2), 0); + boost::any ret = wxNumberFormatter::ToString(unscale(avg_dist * 2), 0); optgroup->set_value("diameter", ret); update_shape(); return; @@ -206,8 +206,8 @@ void BedShapePanel::set_shape(ConfigOptionPoints* points) // Invalid polygon.Revert to default bed dimensions. m_shape_options_book->SetSelection(SHAPE_RECTANGULAR); auto optgroup = m_optgroups[SHAPE_RECTANGULAR]; - optgroup->set_value("rect_size", new ConfigOptionPoints{ Pointf(200, 200) }); - optgroup->set_value("rect_origin", new ConfigOptionPoints{ Pointf(0, 0) }); + optgroup->set_value("rect_size", new ConfigOptionPoints{ Vec2d(200, 200) }); + optgroup->set_value("rect_origin", new ConfigOptionPoints{ Vec2d(0, 0) }); update_shape(); return; } @@ -230,19 +230,21 @@ void BedShapePanel::update_shape() { auto page_idx = m_shape_options_book->GetSelection(); if (page_idx == SHAPE_RECTANGULAR) { - Pointf rect_size, rect_origin; + Vec2d rect_size(Vec2d::Zero()); + Vec2d rect_origin(Vec2d::Zero()); try{ - rect_size = boost::any_cast(m_optgroups[SHAPE_RECTANGULAR]->get_value("rect_size")); } + rect_size = boost::any_cast(m_optgroups[SHAPE_RECTANGULAR]->get_value("rect_size")); } catch (const std::exception &e){ - return;} + return; + } try{ - rect_origin = boost::any_cast(m_optgroups[SHAPE_RECTANGULAR]->get_value("rect_origin")); + rect_origin = boost::any_cast(m_optgroups[SHAPE_RECTANGULAR]->get_value("rect_origin")); } catch (const std::exception &e){ return;} - auto x = rect_size.x; - auto y = rect_size.y; + auto x = rect_size(0); + auto y = rect_size(1); // empty strings or '-' or other things if (x == 0 || y == 0) return; double x0 = 0.0; @@ -250,17 +252,17 @@ void BedShapePanel::update_shape() double x1 = x; double y1 = y; - auto dx = rect_origin.x; - auto dy = rect_origin.y; + auto dx = rect_origin(0); + auto dy = rect_origin(1); x0 -= dx; x1 -= dx; y0 -= dy; y1 -= dy; - m_canvas->m_bed_shape = { Pointf(x0, y0), - Pointf(x1, y0), - Pointf(x1, y1), - Pointf(x0, y1)}; + m_canvas->m_bed_shape = { Vec2d(x0, y0), + Vec2d(x1, y0), + Vec2d(x1, y1), + Vec2d(x0, y1)}; } else if(page_idx == SHAPE_CIRCULAR) { double diameter; @@ -274,10 +276,10 @@ void BedShapePanel::update_shape() auto r = diameter / 2; auto twopi = 2 * PI; auto edges = 60; - std::vector points; + std::vector points; for (size_t i = 1; i <= 60; ++i){ auto angle = i * twopi / edges; - points.push_back(Pointf(r*cos(angle), r*sin(angle))); + points.push_back(Vec2d(r*cos(angle), r*sin(angle))); } m_canvas->m_bed_shape = points; } @@ -330,9 +332,9 @@ void BedShapePanel::load_stl() } auto polygon = expolygons[0].contour; - std::vector points; + std::vector points; for (auto pt : polygon.points) - points.push_back(Pointf::new_unscale(pt)); + points.push_back(unscale(pt)); m_canvas->m_bed_shape = points; update_preview(); } diff --git a/xs/src/slic3r/GUI/BedShapeDialog.hpp b/xs/src/slic3r/GUI/BedShapeDialog.hpp index 5ff488063..d8ba5a912 100644 --- a/xs/src/slic3r/GUI/BedShapeDialog.hpp +++ b/xs/src/slic3r/GUI/BedShapeDialog.hpp @@ -34,7 +34,7 @@ public: void load_stl(); // Returns the resulting bed shape polygon. This value will be stored to the ini file. - std::vector GetValue() { return m_canvas->m_bed_shape; } + std::vector GetValue() { return m_canvas->m_bed_shape; } }; class BedShapeDialog : public wxDialog @@ -46,7 +46,7 @@ public: ~BedShapeDialog(){ } void build_dialog(ConfigOptionPoints* default_pt); - std::vector GetValue() { return m_panel->GetValue(); } + std::vector GetValue() { return m_panel->GetValue(); } }; } // GUI diff --git a/xs/src/slic3r/GUI/Field.cpp b/xs/src/slic3r/GUI/Field.cpp index 757a18f11..3c7c817a6 100644 --- a/xs/src/slic3r/GUI/Field.cpp +++ b/xs/src/slic3r/GUI/Field.cpp @@ -632,9 +632,9 @@ void PointCtrl::BUILD() wxSize field_size(40, -1); auto default_pt = static_cast(m_opt.default_value)->values.at(0); - double val = default_pt.x; + double val = default_pt(0); wxString X = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2, wxNumberFormatter::Style_None); - val = default_pt.y; + val = default_pt(1); wxString Y = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2, wxNumberFormatter::Style_None); x_textctrl = new wxTextCtrl(m_parent, wxID_ANY, X, wxDefaultPosition, field_size); @@ -655,13 +655,13 @@ void PointCtrl::BUILD() y_textctrl->SetToolTip(get_tooltip_text(X+", "+Y)); } -void PointCtrl::set_value(const Pointf& value, bool change_event) +void PointCtrl::set_value(const Vec2d& value, bool change_event) { m_disable_change_event = !change_event; - double val = value.x; + double val = value(0); x_textctrl->SetValue(val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2, wxNumberFormatter::Style_None)); - val = value.y; + val = value(1); y_textctrl->SetValue(val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2, wxNumberFormatter::Style_None)); m_disable_change_event = false; @@ -669,8 +669,8 @@ void PointCtrl::set_value(const Pointf& value, bool change_event) void PointCtrl::set_value(const boost::any& value, bool change_event) { - Pointf pt; - const Pointf *ptf = boost::any_cast(&value); + Vec2d pt(Vec2d::Zero()); + const Vec2d *ptf = boost::any_cast(&value); if (!ptf) { ConfigOptionPoints* pts = boost::any_cast(value); @@ -683,13 +683,10 @@ void PointCtrl::set_value(const boost::any& value, bool change_event) boost::any& PointCtrl::get_value() { - Pointf ret_point; - double val; - x_textctrl->GetValue().ToDouble(&val); - ret_point.x = val; - y_textctrl->GetValue().ToDouble(&val); - ret_point.y = val; - return m_value = ret_point; + double x, y; + x_textctrl->GetValue().ToDouble(&x); + y_textctrl->GetValue().ToDouble(&y); + return m_value = Vec2d(x, y); } void StaticText::BUILD() diff --git a/xs/src/slic3r/GUI/Field.hpp b/xs/src/slic3r/GUI/Field.hpp index db8d2a408..e19c47d68 100644 --- a/xs/src/slic3r/GUI/Field.hpp +++ b/xs/src/slic3r/GUI/Field.hpp @@ -372,7 +372,7 @@ public: void BUILD() override; - void set_value(const Pointf& value, bool change_event = false); + void set_value(const Vec2d& value, bool change_event = false); void set_value(const boost::any& value, bool change_event = false); boost::any& get_value() override; diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp index b354e2979..a155769a5 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp @@ -71,8 +71,8 @@ bool GeometryBuffer::set_from_triangles(const Polygons& triangles, float z, bool if (generate_tex_coords) m_tex_coords = std::vector(t_size, 0.0f); - float min_x = (float)unscale(triangles[0].points[0].x); - float min_y = (float)unscale(triangles[0].points[0].y); + float min_x = unscale(triangles[0].points[0](0)); + float min_y = unscale(triangles[0].points[0](1)); float max_x = min_x; float max_y = min_y; @@ -83,8 +83,8 @@ bool GeometryBuffer::set_from_triangles(const Polygons& triangles, float z, bool for (unsigned int v = 0; v < 3; ++v) { const Point& p = t.points[v]; - float x = (float)unscale(p.x); - float y = (float)unscale(p.y); + float x = unscale(p(0)); + float y = unscale(p(1)); m_vertices[v_coord++] = x; m_vertices[v_coord++] = y; @@ -137,11 +137,11 @@ bool GeometryBuffer::set_from_lines(const Lines& lines, float z) unsigned int coord = 0; for (const Line& l : lines) { - m_vertices[coord++] = (float)unscale(l.a.x); - m_vertices[coord++] = (float)unscale(l.a.y); + m_vertices[coord++] = unscale(l.a(0)); + m_vertices[coord++] = unscale(l.a(1)); m_vertices[coord++] = z; - m_vertices[coord++] = (float)unscale(l.b.x); - m_vertices[coord++] = (float)unscale(l.b.y); + m_vertices[coord++] = unscale(l.b(0)); + m_vertices[coord++] = unscale(l.b(1)); m_vertices[coord++] = z; } @@ -317,9 +317,9 @@ bool GLCanvas3D::Bed::set_shape(const Pointfs& shape) _calc_bounding_box(); ExPolygon poly; - for (const Pointf& p : m_shape) + for (const Vec2d& p : m_shape) { - poly.contour.append(Point(scale_(p.x), scale_(p.y))); + poly.contour.append(Point(scale_(p(0)), scale_(p(1)))); } _calc_triangles(poly); @@ -373,9 +373,9 @@ void GLCanvas3D::Bed::render(float theta) const void GLCanvas3D::Bed::_calc_bounding_box() { m_bounding_box = BoundingBoxf3(); - for (const Pointf& p : m_shape) + for (const Vec2d& p : m_shape) { - m_bounding_box.merge(Pointf3(p.x, p.y, 0.0)); + m_bounding_box.merge(Vec3d(p(0), p(1), 0.0)); } } @@ -391,18 +391,18 @@ void GLCanvas3D::Bed::_calc_triangles(const ExPolygon& poly) void GLCanvas3D::Bed::_calc_gridlines(const ExPolygon& poly, const BoundingBox& bed_bbox) { Polylines axes_lines; - for (coord_t x = bed_bbox.min.x; x <= bed_bbox.max.x; x += scale_(10.0)) + for (coord_t x = bed_bbox.min(0); x <= bed_bbox.max(0); x += scale_(10.0)) { Polyline line; - line.append(Point(x, bed_bbox.min.y)); - line.append(Point(x, bed_bbox.max.y)); + line.append(Point(x, bed_bbox.min(1))); + line.append(Point(x, bed_bbox.max(1))); axes_lines.push_back(line); } - for (coord_t y = bed_bbox.min.y; y <= bed_bbox.max.y; y += scale_(10.0)) + for (coord_t y = bed_bbox.min(1); y <= bed_bbox.max(1); y += scale_(10.0)) { Polyline line; - line.append(Point(bed_bbox.min.x, y)); - line.append(Point(bed_bbox.max.x, y)); + line.append(Point(bed_bbox.min(0), y)); + line.append(Point(bed_bbox.max(0), y)); axes_lines.push_back(line); } @@ -591,7 +591,7 @@ bool GLCanvas3D::Bed::_are_equal(const Pointfs& bed_1, const Pointfs& bed_2) } GLCanvas3D::Axes::Axes() - : length(0.0f) + : origin(0, 0, 0), length(0.0f) { } @@ -606,12 +606,12 @@ void GLCanvas3D::Axes::render(bool depth_test) const ::glBegin(GL_LINES); // draw line for x axis ::glColor3f(1.0f, 0.0f, 0.0f); - ::glVertex3f((GLfloat)origin.x, (GLfloat)origin.y, (GLfloat)origin.z); - ::glVertex3f((GLfloat)origin.x + length, (GLfloat)origin.y, (GLfloat)origin.z); + ::glVertex3f((GLfloat)origin(0), (GLfloat)origin(1), (GLfloat)origin(2)); + ::glVertex3f((GLfloat)origin(0) + length, (GLfloat)origin(1), (GLfloat)origin(2)); // draw line for y axis ::glColor3f(0.0f, 1.0f, 0.0f); - ::glVertex3f((GLfloat)origin.x, (GLfloat)origin.y, (GLfloat)origin.z); - ::glVertex3f((GLfloat)origin.x, (GLfloat)origin.y + length, (GLfloat)origin.z); + ::glVertex3f((GLfloat)origin(0), (GLfloat)origin(1), (GLfloat)origin(2)); + ::glVertex3f((GLfloat)origin(0), (GLfloat)origin(1) + length, (GLfloat)origin(2)); ::glEnd(); // draw line for Z axis // (re-enable depth test so that axis is correctly shown when objects are behind it) @@ -620,8 +620,8 @@ void GLCanvas3D::Axes::render(bool depth_test) const ::glBegin(GL_LINES); ::glColor3f(0.0f, 0.0f, 1.0f); - ::glVertex3f((GLfloat)origin.x, (GLfloat)origin.y, (GLfloat)origin.z); - ::glVertex3f((GLfloat)origin.x, (GLfloat)origin.y, (GLfloat)origin.z + length); + ::glVertex3f((GLfloat)origin(0), (GLfloat)origin(1), (GLfloat)origin(2)); + ::glVertex3f((GLfloat)origin(0), (GLfloat)origin(1), (GLfloat)origin(2) + length); ::glEnd(); } @@ -655,10 +655,10 @@ void GLCanvas3D::CuttingPlane::_render_plane(const BoundingBoxf3& bb) const ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); float margin = 20.0f; - float min_x = bb.min.x - margin; - float max_x = bb.max.x + margin; - float min_y = bb.min.y - margin; - float max_y = bb.max.y + margin; + float min_x = bb.min(0) - margin; + float max_x = bb.max(0) + margin; + float min_y = bb.min(1) - margin; + float max_y = bb.max(1) + margin; ::glBegin(GL_QUADS); ::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); @@ -869,8 +869,8 @@ float GLCanvas3D::LayersEditing::get_cursor_z_relative(const GLCanvas3D& canvas) { const Point& mouse_pos = canvas.get_local_mouse_position(); const Rect& rect = get_bar_rect_screen(canvas); - float x = (float)mouse_pos.x; - float y = (float)mouse_pos.y; + float x = (float)mouse_pos(0); + float y = (float)mouse_pos(1); float t = rect.get_top(); float b = rect.get_bottom(); @@ -979,7 +979,7 @@ void GLCanvas3D::LayersEditing::_render_reset_texture(const Rect& reset_rect) co void GLCanvas3D::LayersEditing::_render_active_object_annotations(const GLCanvas3D& canvas, const GLVolume& volume, const PrintObject& print_object, const Rect& bar_rect) const { - float max_z = print_object.model_object()->bounding_box().max.z; + float max_z = print_object.model_object()->bounding_box().max(2); m_shader.start_using(); @@ -1040,7 +1040,7 @@ void GLCanvas3D::LayersEditing::_render_profile(const PrintObject& print_object, // Make the vertical bar a bit wider so the layer height curve does not touch the edge of the bar region. layer_height_max *= 1.12; - coordf_t max_z = unscale(print_object.size.z); + coordf_t max_z = unscale(print_object.size(2)); double layer_height = dynamic_cast(print_object.config.option("layer_height"))->value; float l = bar_rect.get_left(); float w = bar_rect.get_right() - l; @@ -1075,11 +1075,12 @@ void GLCanvas3D::LayersEditing::_render_profile(const PrintObject& print_object, } const Point GLCanvas3D::Mouse::Drag::Invalid_2D_Point(INT_MAX, INT_MAX); -const Pointf3 GLCanvas3D::Mouse::Drag::Invalid_3D_Point(DBL_MAX, DBL_MAX, DBL_MAX); +const Vec3d GLCanvas3D::Mouse::Drag::Invalid_3D_Point(DBL_MAX, DBL_MAX, DBL_MAX); GLCanvas3D::Mouse::Drag::Drag() : start_position_2D(Invalid_2D_Point) , start_position_3D(Invalid_3D_Point) + , volume_center_offset(0, 0, 0) , move_with_shift(false) , move_volume_idx(-1) , gizmo_volume_idx(-1) @@ -1175,7 +1176,7 @@ void GLCanvas3D::Gizmos::set_enabled(bool enable) m_enabled = enable; } -void GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Pointf& mouse_pos) +void GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos) { if (!m_enabled) return; @@ -1194,14 +1195,14 @@ void GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Poin // we currently use circular icons for gizmo, so we check the radius if (it->second->get_state() != GLGizmoBase::On) { - bool inside = length(Pointf(OverlayOffsetX + half_tex_size, top_y + half_tex_size).vector_to(mouse_pos)) < half_tex_size; + bool inside = (mouse_pos - Vec2d(OverlayOffsetX + half_tex_size, top_y + half_tex_size)).norm() < half_tex_size; it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off); } top_y += (tex_size + OverlayGapY); } } -void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Pointf& mouse_pos) +void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos) { if (!m_enabled) return; @@ -1218,7 +1219,7 @@ void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Poi float half_tex_size = 0.5f * tex_size; // we currently use circular icons for gizmo, so we check the radius - if (length(Pointf(OverlayOffsetX + half_tex_size, top_y + half_tex_size).vector_to(mouse_pos)) < half_tex_size) + if ((mouse_pos - Vec2d(OverlayOffsetX + half_tex_size, top_y + half_tex_size)).norm() < half_tex_size) { if ((it->second->get_state() == GLGizmoBase::On)) { @@ -1267,7 +1268,7 @@ void GLCanvas3D::Gizmos::set_hover_id(int id) } } -bool GLCanvas3D::Gizmos::overlay_contains_mouse(const GLCanvas3D& canvas, const Pointf& mouse_pos) const +bool GLCanvas3D::Gizmos::overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const { if (!m_enabled) return false; @@ -1284,7 +1285,7 @@ bool GLCanvas3D::Gizmos::overlay_contains_mouse(const GLCanvas3D& canvas, const float half_tex_size = 0.5f * tex_size; // we currently use circular icons for gizmo, so we check the radius - if (length(Pointf(OverlayOffsetX + half_tex_size, top_y + half_tex_size).vector_to(mouse_pos)) < half_tex_size) + if ((mouse_pos - Vec2d(OverlayOffsetX + half_tex_size, top_y + half_tex_size)).norm() < half_tex_size) return true; top_y += (tex_size + OverlayGapY); @@ -2078,7 +2079,7 @@ void GLCanvas3D::set_bed_shape(const Pointfs& shape) bool new_shape = m_bed.set_shape(shape); // Set the origin and size for painting of the coordinate system axes. - m_axes.origin = Pointf3(0.0, 0.0, (coordf_t)GROUND_Z); + m_axes.origin = Vec3d(0.0, 0.0, (coordf_t)GROUND_Z); set_axes_length(0.3f * (float)m_bed.get_bounding_box().max_size()); if (new_shape) @@ -2098,19 +2099,19 @@ void GLCanvas3D::set_auto_bed_shape() // draw a default square bed around object center const BoundingBoxf3& bbox = volumes_bounding_box(); coordf_t max_size = bbox.max_size(); - const Pointf3& center = bbox.center(); + const Vec3d center = bbox.center(); Pointfs bed_shape; bed_shape.reserve(4); - bed_shape.emplace_back(center.x - max_size, center.y - max_size); - bed_shape.emplace_back(center.x + max_size, center.y - max_size); - bed_shape.emplace_back(center.x + max_size, center.y + max_size); - bed_shape.emplace_back(center.x - max_size, center.y + max_size); + bed_shape.emplace_back(center(0) - max_size, center(1) - max_size); + bed_shape.emplace_back(center(0) + max_size, center(1) - max_size); + bed_shape.emplace_back(center(0) + max_size, center(1) + max_size); + bed_shape.emplace_back(center(0) - max_size, center(1) + max_size); set_bed_shape(bed_shape); // Set the origin for painting of the coordinate system axes. - m_axes.origin = Pointf3(center.x, center.y, (coordf_t)GROUND_Z); + m_axes.origin = Vec3d(center(0), center(1), (coordf_t)GROUND_Z); } void GLCanvas3D::set_axes_length(float length) @@ -2462,7 +2463,7 @@ void GLCanvas3D::reload_scene(bool force) if ((extruders_count > 1) && semm && wt && !co) { // Height of a print (Show at least a slab) - coordf_t height = std::max(m_model->bounding_box().max.z, 10.0); + coordf_t height = std::max(m_model->bounding_box().max(2), 10.0); float x = dynamic_cast(m_config->option("wipe_tower_x"))->value; float y = dynamic_cast(m_config->option("wipe_tower_y"))->value; @@ -2948,7 +2949,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) else if (evt.Leaving()) { // to remove hover on objects when the mouse goes out of this canvas - m_mouse.position = Pointf(-1.0, -1.0); + m_mouse.position = Vec2d(-1.0, -1.0); m_dirty = true; } else if (evt.LeftDClick() && (m_hover_volume_id != -1)) @@ -2964,14 +2965,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // on a volume or not. int volume_idx = m_hover_volume_id; m_layers_editing.state = LayersEditing::Unknown; - if ((layer_editing_object_idx != -1) && m_layers_editing.bar_rect_contains(*this, pos.x, pos.y)) + if ((layer_editing_object_idx != -1) && m_layers_editing.bar_rect_contains(*this, pos(0), pos(1))) { // A volume is selected and the mouse is inside the layer thickness bar. // Start editing the layer height. m_layers_editing.state = LayersEditing::Editing; _perform_layer_editing_action(&evt); } - else if ((layer_editing_object_idx != -1) && m_layers_editing.reset_rect_contains(*this, pos.x, pos.y)) + else if ((layer_editing_object_idx != -1) && m_layers_editing.reset_rect_contains(*this, pos(0), pos(1))) { if (evt.LeftDown()) { @@ -3039,7 +3040,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { // The mouse_to_3d gets the Z coordinate from the Z buffer at the screen coordinate pos x, y, // an converts the screen space coordinate to unscaled object space. - Pointf3 pos3d = (volume_idx == -1) ? Pointf3(DBL_MAX, DBL_MAX) : _mouse_to_3d(pos); + Vec3d pos3d = (volume_idx == -1) ? Vec3d(DBL_MAX, DBL_MAX, DBL_MAX) : _mouse_to_3d(pos); // Only accept the initial position, if it is inside the volume bounding box. BoundingBoxf3 volume_bbox = m_volumes.volumes[volume_idx]->transformed_bounding_box(); @@ -3052,20 +3053,20 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_mouse.drag.start_position_3D = pos3d; // Remember the shift to to the object center.The object center will later be used // to limit the object placement close to the bed. - m_mouse.drag.volume_center_offset = pos3d.vector_to(volume_bbox.center()); + m_mouse.drag.volume_center_offset = volume_bbox.center() - pos3d; } } else if (evt.RightDown()) { // forces a frame render to ensure that m_hover_volume_id is updated even when the user right clicks while // the context menu is already shown, ensuring it to disappear if the mouse is outside any volume - m_mouse.position = Pointf((coordf_t)pos.x, (coordf_t)pos.y); + m_mouse.position = Vec2d((double)pos(0), (double)pos(1)); render(); if (m_hover_volume_id != -1) { // if right clicking on volume, propagate event through callback (shows context menu) if (m_volumes.volumes[volume_idx]->hover) - m_on_right_click_callback.call(pos.x, pos.y); + m_on_right_click_callback.call(pos(0), pos(1)); } } } @@ -3078,21 +3079,21 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // Get new position at the same Z of the initial click point. float z0 = 0.0f; float z1 = 1.0f; - Pointf3 cur_pos = Linef3(_mouse_to_3d(pos, &z0), _mouse_to_3d(pos, &z1)).intersect_plane(m_mouse.drag.start_position_3D.z); + Vec3d cur_pos = Linef3(_mouse_to_3d(pos, &z0), _mouse_to_3d(pos, &z1)).intersect_plane(m_mouse.drag.start_position_3D(2)); // Clip the new position, so the object center remains close to the bed. - cur_pos.translate(m_mouse.drag.volume_center_offset); - Point cur_pos2(scale_(cur_pos.x), scale_(cur_pos.y)); + cur_pos += m_mouse.drag.volume_center_offset; + Point cur_pos2(scale_(cur_pos(0)), scale_(cur_pos(1))); if (!m_bed.contains(cur_pos2)) { Point ip = m_bed.point_projection(cur_pos2); - cur_pos.x = unscale(ip.x); - cur_pos.y = unscale(ip.y); + cur_pos(0) = unscale(ip(0)); + cur_pos(1) = unscale(ip(1)); } - cur_pos.translate(m_mouse.drag.volume_center_offset.negative()); + cur_pos -= m_mouse.drag.volume_center_offset; // Calculate the translation vector. - Vectorf3 vector = m_mouse.drag.start_position_3D.vector_to(cur_pos); + Vec3d vector = cur_pos - m_mouse.drag.start_position_3D; // Get the volume being dragged. GLVolume* volume = m_volumes.volumes[m_mouse.drag.move_volume_idx]; // Get all volumes belonging to the same group, if any. @@ -3114,11 +3115,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // Apply new temporary volume origin and ignore Z. for (GLVolume* v : volumes) - { - Pointf3 origin = v->get_origin(); - origin.translate(vector.x, vector.y, 0.0); - v->set_origin(origin); - } + v->set_origin(v->get_origin() + Vec3d(vector(0), vector(1), 0.0)); m_mouse.drag.start_position_3D = cur_pos; m_gizmos.refresh(); @@ -3180,8 +3177,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { bb.merge(volume->transformed_bounding_box()); } - const Pointf3& size = bb.size(); - m_on_update_geometry_info_callback.call(size.x, size.y, size.z, m_gizmos.get_scale()); + const Vec3d& size = bb.size(); + m_on_update_geometry_info_callback.call(size(0), size(1), size(2), m_gizmos.get_scale()); } if ((m_gizmos.get_current_type() != Gizmos::Rotate) && (volumes.size() > 1)) @@ -3203,15 +3200,15 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // if dragging over blank area with left button, rotate if (m_mouse.is_start_position_3D_defined()) { - const Pointf3& orig = m_mouse.drag.start_position_3D; - m_camera.phi += (((float)pos.x - (float)orig.x) * TRACKBALLSIZE); - m_camera.set_theta(m_camera.get_theta() - ((float)pos.y - (float)orig.y) * TRACKBALLSIZE); + const Vec3d& orig = m_mouse.drag.start_position_3D; + m_camera.phi += (((float)pos(0) - (float)orig(0)) * TRACKBALLSIZE); + m_camera.set_theta(m_camera.get_theta() - ((float)pos(1) - (float)orig(1)) * TRACKBALLSIZE); m_on_viewport_changed_callback.call(); m_dirty = true; } - m_mouse.drag.start_position_3D = Pointf3((coordf_t)pos.x, (coordf_t)pos.y, 0.0); + m_mouse.drag.start_position_3D = Vec3d((coordf_t)pos(0), (coordf_t)pos(1), 0.0); } else if (evt.MiddleIsDown() || evt.RightIsDown()) { @@ -3220,11 +3217,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { // get point in model space at Z = 0 float z = 0.0f; - const Pointf3& cur_pos = _mouse_to_3d(pos, &z); - Pointf3 orig = _mouse_to_3d(m_mouse.drag.start_position_2D, &z); - Pointf3 camera_target = m_camera.target; - camera_target.translate(orig.vector_to(cur_pos).negative()); - m_camera.target = camera_target; + const Vec3d& cur_pos = _mouse_to_3d(pos, &z); + Vec3d orig = _mouse_to_3d(m_mouse.drag.start_position_2D, &z); + m_camera.target += orig - cur_pos; m_on_viewport_changed_callback.call(); @@ -3307,7 +3302,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } else if (evt.Moving()) { - m_mouse.position = Pointf((coordf_t)pos.x, (coordf_t)pos.y); + m_mouse.position = Vec2d((coordf_t)pos(0), (coordf_t)pos(1)); // Only refresh if picking is enabled, in that case the objects may get highlighted if the mouse cursor hovers over. if (m_picking_enabled) m_dirty = true; @@ -3676,25 +3671,25 @@ float GLCanvas3D::_get_zoom_to_bounding_box_factor(const BoundingBoxf3& bbox) co ::glGetFloatv(GL_MODELVIEW_MATRIX, matrix); // camera axes - Pointf3 right((coordf_t)matrix[0], (coordf_t)matrix[4], (coordf_t)matrix[8]); - Pointf3 up((coordf_t)matrix[1], (coordf_t)matrix[5], (coordf_t)matrix[9]); - Pointf3 forward((coordf_t)matrix[2], (coordf_t)matrix[6], (coordf_t)matrix[10]); + Vec3d right((coordf_t)matrix[0], (coordf_t)matrix[4], (coordf_t)matrix[8]); + Vec3d up((coordf_t)matrix[1], (coordf_t)matrix[5], (coordf_t)matrix[9]); + Vec3d forward((coordf_t)matrix[2], (coordf_t)matrix[6], (coordf_t)matrix[10]); - Pointf3 bb_min = bbox.min; - Pointf3 bb_max = bbox.max; - Pointf3 bb_center = bbox.center(); + Vec3d bb_min = bbox.min; + Vec3d bb_max = bbox.max; + Vec3d bb_center = bbox.center(); // bbox vertices in world space - std::vector vertices; + std::vector vertices; vertices.reserve(8); vertices.push_back(bb_min); - vertices.emplace_back(bb_max.x, bb_min.y, bb_min.z); - vertices.emplace_back(bb_max.x, bb_max.y, bb_min.z); - vertices.emplace_back(bb_min.x, bb_max.y, bb_min.z); - vertices.emplace_back(bb_min.x, bb_min.y, bb_max.z); - vertices.emplace_back(bb_max.x, bb_min.y, bb_max.z); + vertices.emplace_back(bb_max(0), bb_min(1), bb_min(2)); + vertices.emplace_back(bb_max(0), bb_max(1), bb_min(2)); + vertices.emplace_back(bb_min(0), bb_max(1), bb_min(2)); + vertices.emplace_back(bb_min(0), bb_min(1), bb_max(2)); + vertices.emplace_back(bb_max(0), bb_min(1), bb_max(2)); vertices.push_back(bb_max); - vertices.emplace_back(bb_min.x, bb_max.y, bb_max.z); + vertices.emplace_back(bb_min(0), bb_max(1), bb_max(2)); coordf_t max_x = 0.0; coordf_t max_y = 0.0; @@ -3702,15 +3697,15 @@ float GLCanvas3D::_get_zoom_to_bounding_box_factor(const BoundingBoxf3& bbox) co // margin factor to give some empty space around the bbox coordf_t margin_factor = 1.25; - for (const Pointf3 v : vertices) + for (const Vec3d v : vertices) { // project vertex on the plane perpendicular to camera forward axis - Pointf3 pos(v.x - bb_center.x, v.y - bb_center.y, v.z - bb_center.z); - Pointf3 proj_on_plane = pos - dot(pos, forward) * forward; + Vec3d pos(v(0) - bb_center(0), v(1) - bb_center(1), v(2) - bb_center(2)); + Vec3d proj_on_plane = pos - pos.dot(forward) * forward; // calculates vertex coordinate along camera xy axes - coordf_t x_on_plane = dot(proj_on_plane, right); - coordf_t y_on_plane = dot(proj_on_plane, up); + coordf_t x_on_plane = proj_on_plane.dot(right); + coordf_t y_on_plane = proj_on_plane.dot(up); max_x = std::max(max_x, margin_factor * std::abs(x_on_plane)); max_y = std::max(max_y, margin_factor * std::abs(y_on_plane)); @@ -3802,15 +3797,15 @@ void GLCanvas3D::_camera_tranform() const ::glRotatef(-m_camera.get_theta(), 1.0f, 0.0f, 0.0f); // pitch ::glRotatef(m_camera.phi, 0.0f, 0.0f, 1.0f); // yaw - Pointf3 neg_target = m_camera.target.negative(); - ::glTranslatef((GLfloat)neg_target.x, (GLfloat)neg_target.y, (GLfloat)neg_target.z); + Vec3d neg_target = - m_camera.target; + ::glTranslatef((GLfloat)neg_target(0), (GLfloat)neg_target(1), (GLfloat)neg_target(2)); } void GLCanvas3D::_picking_pass() const { - const Pointf& pos = m_mouse.position; + const Vec2d& pos = m_mouse.position; - if (m_picking_enabled && !m_mouse.dragging && (pos != Pointf(DBL_MAX, DBL_MAX))) + if (m_picking_enabled && !m_mouse.dragging && (pos != Vec2d(DBL_MAX, DBL_MAX))) { // Render the object for picking. // FIXME This cannot possibly work in a multi - sampled context as the color gets mangled by the anti - aliasing. @@ -3838,10 +3833,10 @@ void GLCanvas3D::_picking_pass() const GLubyte color[4] = { 0, 0, 0, 0 }; const Size& cnv_size = get_canvas_size(); - bool inside = (0 <= pos.x) && (pos.x < cnv_size.get_width()) && (0 <= pos.y) && (pos.y < cnv_size.get_height()); + bool inside = (0 <= pos(0)) && (pos(0) < cnv_size.get_width()) && (0 <= pos(1)) && (pos(1) < cnv_size.get_height()); if (inside) { - ::glReadPixels(pos.x, cnv_size.get_height() - pos.y - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)color); + ::glReadPixels(pos(0), cnv_size.get_height() - pos(1) - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)color); volume_id = color[0] + color[1] * 256 + color[2] * 256 * 256; } @@ -3939,7 +3934,7 @@ void GLCanvas3D::_render_objects() const if (m_config != nullptr) { const BoundingBoxf3& bed_bb = m_bed.get_bounding_box(); - m_volumes.set_print_box((float)bed_bb.min.x, (float)bed_bb.min.y, 0.0f, (float)bed_bb.max.x, (float)bed_bb.max.y, (float)m_config->opt_float("max_print_height")); + m_volumes.set_print_box((float)bed_bb.min(0), (float)bed_bb.min(1), 0.0f, (float)bed_bb.max(0), (float)bed_bb.max(1), (float)m_config->opt_float("max_print_height")); m_volumes.check_outside_state(m_config, nullptr); } // do not cull backfaces to show broken geometry, if any @@ -4107,7 +4102,7 @@ void GLCanvas3D::_perform_layer_editing_action(wxMouseEvent* evt) { const Rect& rect = LayersEditing::get_bar_rect_screen(*this); float b = rect.get_bottom(); - m_layers_editing.last_z = unscale(selected_obj->size.z) * (b - evt->GetY() - 1.0f) / (b - rect.get_top()); + m_layers_editing.last_z = unscale(selected_obj->size(2)) * (b - evt->GetY() - 1.0f) / (b - rect.get_top()); m_layers_editing.last_action = evt->ShiftDown() ? (evt->RightIsDown() ? 3 : 2) : (evt->RightIsDown() ? 0 : 1); } @@ -4137,10 +4132,10 @@ void GLCanvas3D::_perform_layer_editing_action(wxMouseEvent* evt) _start_timer(); } -Pointf3 GLCanvas3D::_mouse_to_3d(const Point& mouse_pos, float* z) +Vec3d GLCanvas3D::_mouse_to_3d(const Point& mouse_pos, float* z) { if (m_canvas == nullptr) - return Pointf3(DBL_MAX, DBL_MAX, DBL_MAX); + return Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); _camera_tranform(); @@ -4151,19 +4146,19 @@ Pointf3 GLCanvas3D::_mouse_to_3d(const Point& mouse_pos, float* z) GLdouble projection_matrix[16]; ::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix); - GLint y = viewport[3] - (GLint)mouse_pos.y; + GLint y = viewport[3] - (GLint)mouse_pos(1); GLfloat mouse_z; if (z == nullptr) - ::glReadPixels((GLint)mouse_pos.x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, (void*)&mouse_z); + ::glReadPixels((GLint)mouse_pos(0), y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, (void*)&mouse_z); else mouse_z = *z; GLdouble out_x, out_y, out_z; - ::gluUnProject((GLdouble)mouse_pos.x, (GLdouble)y, (GLdouble)mouse_z, modelview_matrix, projection_matrix, viewport, &out_x, &out_y, &out_z); - return Pointf3((coordf_t)out_x, (coordf_t)out_y, (coordf_t)out_z); + ::gluUnProject((GLdouble)mouse_pos(0), (GLdouble)y, (GLdouble)mouse_z, modelview_matrix, projection_matrix, viewport, &out_x, &out_y, &out_z); + return Vec3d((coordf_t)out_x, (coordf_t)out_y, (coordf_t)out_z); } -Pointf3 GLCanvas3D::_mouse_to_bed_3d(const Point& mouse_pos) +Vec3d GLCanvas3D::_mouse_to_bed_3d(const Point& mouse_pos) { return mouse_ray(mouse_pos).intersect_plane(0.0); } @@ -4883,7 +4878,7 @@ bool GLCanvas3D::_travel_paths_by_type(const GCodePreviewData& preview_data) TypesList::iterator type = std::find(types.begin(), types.end(), Type(polyline.type)); if (type != types.end()) { - type->volume->print_zs.push_back(unscale(polyline.polyline.bounding_box().min.z)); + type->volume->print_zs.push_back(unscale(polyline.polyline.bounding_box().min(2))); type->volume->offsets.push_back(type->volume->indexed_vertex_array.quad_indices.size()); type->volume->offsets.push_back(type->volume->indexed_vertex_array.triangle_indices.size()); @@ -4949,7 +4944,7 @@ bool GLCanvas3D::_travel_paths_by_feedrate(const GCodePreviewData& preview_data) FeedratesList::iterator feedrate = std::find(feedrates.begin(), feedrates.end(), Feedrate(polyline.feedrate)); if (feedrate != feedrates.end()) { - feedrate->volume->print_zs.push_back(unscale(polyline.polyline.bounding_box().min.z)); + feedrate->volume->print_zs.push_back(unscale(polyline.polyline.bounding_box().min(2))); feedrate->volume->offsets.push_back(feedrate->volume->indexed_vertex_array.quad_indices.size()); feedrate->volume->offsets.push_back(feedrate->volume->indexed_vertex_array.triangle_indices.size()); @@ -5015,7 +5010,7 @@ bool GLCanvas3D::_travel_paths_by_tool(const GCodePreviewData& preview_data, con ToolsList::iterator tool = std::find(tools.begin(), tools.end(), Tool(polyline.extruder_id)); if (tool != tools.end()) { - tool->volume->print_zs.push_back(unscale(polyline.polyline.bounding_box().min.z)); + tool->volume->print_zs.push_back(unscale(polyline.polyline.bounding_box().min(2))); tool->volume->offsets.push_back(tool->volume->indexed_vertex_array.quad_indices.size()); tool->volume->offsets.push_back(tool->volume->indexed_vertex_array.triangle_indices.size()); @@ -5040,11 +5035,11 @@ void GLCanvas3D::_load_gcode_retractions(const GCodePreviewData& preview_data) m_volumes.volumes.emplace_back(volume); GCodePreviewData::Retraction::PositionsList copy(preview_data.retraction.positions); - std::sort(copy.begin(), copy.end(), [](const GCodePreviewData::Retraction::Position& p1, const GCodePreviewData::Retraction::Position& p2){ return p1.position.z < p2.position.z; }); + std::sort(copy.begin(), copy.end(), [](const GCodePreviewData::Retraction::Position& p1, const GCodePreviewData::Retraction::Position& p2){ return p1.position(2) < p2.position(2); }); for (const GCodePreviewData::Retraction::Position& position : copy) { - volume->print_zs.push_back(unscale(position.position.z)); + volume->print_zs.push_back(unscale(position.position(2))); volume->offsets.push_back(volume->indexed_vertex_array.quad_indices.size()); volume->offsets.push_back(volume->indexed_vertex_array.triangle_indices.size()); @@ -5071,11 +5066,11 @@ void GLCanvas3D::_load_gcode_unretractions(const GCodePreviewData& preview_data) m_volumes.volumes.emplace_back(volume); GCodePreviewData::Retraction::PositionsList copy(preview_data.unretraction.positions); - std::sort(copy.begin(), copy.end(), [](const GCodePreviewData::Retraction::Position& p1, const GCodePreviewData::Retraction::Position& p2){ return p1.position.z < p2.position.z; }); + std::sort(copy.begin(), copy.end(), [](const GCodePreviewData::Retraction::Position& p1, const GCodePreviewData::Retraction::Position& p2){ return p1.position(2) < p2.position(2); }); for (const GCodePreviewData::Retraction::Position& position : copy) { - volume->print_zs.push_back(unscale(position.position.z)); + volume->print_zs.push_back(unscale(position.position(2))); volume->offsets.push_back(volume->indexed_vertex_array.quad_indices.size()); volume->offsets.push_back(volume->indexed_vertex_array.triangle_indices.size()); @@ -5115,7 +5110,7 @@ void GLCanvas3D::_load_shells() } // adds wipe tower's volume - coordf_t max_z = m_print->objects[0]->model_object()->get_model()->bounding_box().max.z; + coordf_t max_z = m_print->objects[0]->model_object()->get_model()->bounding_box().max(2); const PrintConfig& config = m_print->config; unsigned int extruders_count = config.nozzle_diameter.size(); if ((extruders_count > 1) && config.single_extruder_multi_material && config.wipe_tower && !config.complete_objects) { @@ -5198,9 +5193,9 @@ void GLCanvas3D::_update_toolpath_volumes_outside_state() if (opt != nullptr) { BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values)); - print_volume = BoundingBoxf3(Pointf3(unscale(bed_box_2D.min.x) - tolerance_x, unscale(bed_box_2D.min.y) - tolerance_y, 0.0), Pointf3(unscale(bed_box_2D.max.x) + tolerance_x, unscale(bed_box_2D.max.y) + tolerance_y, m_config->opt_float("max_print_height"))); + print_volume = BoundingBoxf3(Vec3d(unscale(bed_box_2D.min(0)) - tolerance_x, unscale(bed_box_2D.min(1)) - tolerance_y, 0.0), Vec3d(unscale(bed_box_2D.max(0)) + tolerance_x, unscale(bed_box_2D.max(1)) + tolerance_y, m_config->opt_float("max_print_height"))); // Allow the objects to protrude below the print bed - print_volume.min.z = -1e10; + print_volume.min(2) = -1e10; } } @@ -5231,7 +5226,7 @@ void GLCanvas3D::_on_move(const std::vector& volume_idxs) std::set done; // prevent moving instances twice bool object_moved = false; - Pointf3 wipe_tower_origin(0.0, 0.0, 0.0); + Vec3d wipe_tower_origin(0.0, 0.0, 0.0); for (int volume_idx : volume_idxs) { GLVolume* volume = m_volumes.volumes[volume_idx]; @@ -5250,8 +5245,8 @@ void GLCanvas3D::_on_move(const std::vector& volume_idxs) { // Move a regular object. ModelObject* model_object = m_model->objects[obj_idx]; - const Pointf3& origin = volume->get_origin(); - model_object->instances[instance_idx]->offset = Pointf(origin.x, origin.y); + const Vec3d& origin = volume->get_origin(); + model_object->instances[instance_idx]->offset = Vec2d(origin(0), origin(1)); model_object->invalidate_bounding_box(); object_moved = true; } @@ -5263,8 +5258,8 @@ void GLCanvas3D::_on_move(const std::vector& volume_idxs) if (object_moved) m_on_instance_moved_callback.call(); - if (wipe_tower_origin != Pointf3(0.0, 0.0, 0.0)) - m_on_wipe_tower_moved_callback.call(wipe_tower_origin.x, wipe_tower_origin.y); + if (wipe_tower_origin != Vec3d(0.0, 0.0, 0.0)) + m_on_wipe_tower_moved_callback.call(wipe_tower_origin(0), wipe_tower_origin(1)); } void GLCanvas3D::_on_select(int volume_idx) diff --git a/xs/src/slic3r/GUI/GLCanvas3D.hpp b/xs/src/slic3r/GUI/GLCanvas3D.hpp index b3606d014..0cd2870eb 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.hpp @@ -120,7 +120,7 @@ public: float zoom; float phi; // float distance; - Pointf3 target; + Vec3d target; private: float m_theta; @@ -185,7 +185,7 @@ public: struct Axes { - Pointf3 origin; + Vec3d origin; float length; Axes(); @@ -299,11 +299,11 @@ public: struct Drag { static const Point Invalid_2D_Point; - static const Pointf3 Invalid_3D_Point; + static const Vec3d Invalid_3D_Point; Point start_position_2D; - Pointf3 start_position_3D; - Vectorf3 volume_center_offset; + Vec3d start_position_3D; + Vec3d volume_center_offset; bool move_with_shift; int move_volume_idx; @@ -314,7 +314,7 @@ public: }; bool dragging; - Pointf position; + Vec2d position; Drag drag; Mouse(); @@ -357,13 +357,13 @@ public: bool is_enabled() const; void set_enabled(bool enable); - void update_hover_state(const GLCanvas3D& canvas, const Pointf& mouse_pos); - void update_on_off_state(const GLCanvas3D& canvas, const Pointf& mouse_pos); + void update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos); + void update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos); void reset_all_states(); void set_hover_id(int id); - bool overlay_contains_mouse(const GLCanvas3D& canvas, const Pointf& mouse_pos) const; + bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const; bool grabber_contains_mouse() const; void update(const Linef3& mouse_ray); void refresh(); @@ -691,10 +691,10 @@ private: // Convert the screen space coordinate to an object space coordinate. // If the Z screen space coordinate is not provided, a depth buffer value is substituted. - Pointf3 _mouse_to_3d(const Point& mouse_pos, float* z = nullptr); + Vec3d _mouse_to_3d(const Point& mouse_pos, float* z = nullptr); // Convert the screen space coordinate to world coordinate on the bed. - Pointf3 _mouse_to_bed_3d(const Point& mouse_pos); + Vec3d _mouse_to_bed_3d(const Point& mouse_pos); // Returns the view ray line, in world coordinate, at the given mouse position. Linef3 mouse_ray(const Point& mouse_pos); diff --git a/xs/src/slic3r/GUI/GLGizmo.cpp b/xs/src/slic3r/GUI/GLGizmo.cpp index 978b35495..6adad04d1 100644 --- a/xs/src/slic3r/GUI/GLGizmo.cpp +++ b/xs/src/slic3r/GUI/GLGizmo.cpp @@ -23,7 +23,7 @@ const float GLGizmoBase::Grabber::HalfSize = 2.0f; const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f; GLGizmoBase::Grabber::Grabber() - : center(Pointf3(0.0, 0.0, 0.0)) + : center(0.0, 0.0, 0.0) , angle_x(0.0f) , angle_y(0.0f) , angle_z(0.0f) @@ -73,7 +73,7 @@ void GLGizmoBase::Grabber::render(const float* render_color) const ::glColor3f((GLfloat)render_color[0], (GLfloat)render_color[1], (GLfloat)render_color[2]); ::glPushMatrix(); - ::glTranslatef((GLfloat)center.x, (GLfloat)center.y, (GLfloat)center.z); + ::glTranslatef((GLfloat)center(0), (GLfloat)center(1), (GLfloat)center(2)); float rad_to_deg = 180.0f / (GLfloat)PI; ::glRotatef((GLfloat)angle_x * rad_to_deg, 1.0f, 0.0f, 0.0f); @@ -249,7 +249,7 @@ GLGizmoRotate::GLGizmoRotate(GLGizmoRotate::Axis axis) : GLGizmoBase() , m_axis(axis) , m_angle(0.0f) - , m_center(Pointf3(0.0, 0.0, 0.0)) + , m_center(0.0, 0.0, 0.0) , m_radius(0.0f) , m_keep_initial_values(false) { @@ -287,18 +287,18 @@ bool GLGizmoRotate::on_init() } void GLGizmoRotate::on_update(const Linef3& mouse_ray) -{ - Pointf mouse_pos = mouse_position_in_local_plane(mouse_ray); +{ + Vec2d mouse_pos = to_2d(mouse_position_in_local_plane(mouse_ray)); - Vectorf orig_dir(1.0, 0.0); - Vectorf new_dir = normalize(mouse_pos); + Vec2d orig_dir = Vec2d::UnitX(); + Vec2d new_dir = mouse_pos.normalized(); - coordf_t theta = ::acos(clamp(-1.0, 1.0, dot(new_dir, orig_dir))); - if (cross(orig_dir, new_dir) < 0.0) + double theta = ::acos(clamp(-1.0, 1.0, new_dir.dot(orig_dir))); + if (cross2(orig_dir, new_dir) < 0.0) theta = 2.0 * (coordf_t)PI - theta; // snap - double len = length(mouse_pos); + double len = mouse_pos.norm(); double in_radius = (double)m_radius / 3.0; double out_radius = 2.0 * (double)in_radius; if ((in_radius <= len) && (len <= out_radius)) @@ -323,16 +323,16 @@ void GLGizmoRotate::on_render(const BoundingBoxf3& box) const if (!m_keep_initial_values) { - const Pointf3& size = box.size(); m_center = box.center(); #if !ENABLE_GIZMOS_3D - m_center.z = 0.0; + const Vec3d& size = box.size(); + m_center(2) = 0.0; #endif // !ENABLE_GIZMOS_3D #if ENABLE_GIZMOS_3D m_radius = Offset + box.radius(); #else - m_radius = Offset + ::sqrt(sqr(0.5f * size.x) + sqr(0.5f * size.y)); + m_radius = Offset + ::sqrt(sqr(0.5f * (float)size(0)) + sqr(0.5f * (float)size(1))); #endif // ENABLE_GIZMOS_3D m_keep_initial_values = true; } @@ -481,7 +481,7 @@ void GLGizmoRotate::render_angle() const void GLGizmoRotate::render_grabber() const { float grabber_radius = m_radius + GrabberOffset; - m_grabbers[0].center = Pointf3(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0f); + m_grabbers[0].center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0); m_grabbers[0].angle_z = m_angle; #if ENABLE_GIZMOS_3D @@ -492,7 +492,7 @@ void GLGizmoRotate::render_grabber() const ::glBegin(GL_LINES); ::glVertex3f(0.0f, 0.0f, 0.0f); - ::glVertex3f((GLfloat)m_grabbers[0].center.x, (GLfloat)m_grabbers[0].center.y, (GLfloat)m_grabbers[0].center.z); + ::glVertex3f((GLfloat)m_grabbers[0].center(0), (GLfloat)m_grabbers[0].center(1), (GLfloat)m_grabbers[0].center(2)); ::glEnd(); ::memcpy((void*)m_grabbers[0].color, (const void*)m_highlight_color, 3 * sizeof(float)); @@ -501,7 +501,7 @@ void GLGizmoRotate::render_grabber() const void GLGizmoRotate::transform_to_local() const { - ::glTranslatef((GLfloat)m_center.x, (GLfloat)m_center.y, (GLfloat)m_center.z); + ::glTranslatef((GLfloat)m_center(0), (GLfloat)m_center(1), (GLfloat)m_center(2)); switch (m_axis) { @@ -526,24 +526,24 @@ void GLGizmoRotate::transform_to_local() const } } -Pointf GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray) const +Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray) const { - float half_pi = 0.5f * (float)PI; + double half_pi = 0.5 * (double)PI; - Eigen::Transform m = Eigen::Transform::Identity(); + Transform3d m = Transform3d::Identity(); switch (m_axis) { case X: { - m.rotate(Eigen::AngleAxisf(-half_pi, Eigen::Vector3f::UnitZ())); - m.rotate(Eigen::AngleAxisf(-half_pi, Eigen::Vector3f::UnitY())); + m.rotate(Eigen::AngleAxisd(-half_pi, Vec3d::UnitZ())); + m.rotate(Eigen::AngleAxisd(-half_pi, Vec3d::UnitY())); break; } case Y: { - m.rotate(Eigen::AngleAxisf(-(float)PI, Eigen::Vector3f::UnitZ())); - m.rotate(Eigen::AngleAxisf(-half_pi, Eigen::Vector3f::UnitX())); + m.rotate(Eigen::AngleAxisd(-(double)PI, Vec3d::UnitZ())); + m.rotate(Eigen::AngleAxisd(-half_pi, Vec3d::UnitX())); break; } default: @@ -554,19 +554,19 @@ Pointf GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray) con } } - m.translate(Eigen::Vector3f((float)-m_center.x, (float)-m_center.y, (float)-m_center.z)); + m.translate(-m_center); - Eigen::Matrix world_ray; - Eigen::Matrix local_ray; - world_ray(0, 0) = (float)mouse_ray.a.x; - world_ray(1, 0) = (float)mouse_ray.a.y; - world_ray(2, 0) = (float)mouse_ray.a.z; - world_ray(0, 1) = (float)mouse_ray.b.x; - world_ray(1, 1) = (float)mouse_ray.b.y; - world_ray(2, 1) = (float)mouse_ray.b.z; + Eigen::Matrix world_ray; + Eigen::Matrix local_ray; + world_ray(0, 0) = mouse_ray.a(0); + world_ray(1, 0) = mouse_ray.a(1); + world_ray(2, 0) = mouse_ray.a(2); + world_ray(0, 1) = mouse_ray.b(0); + world_ray(1, 1) = mouse_ray.b(1); + world_ray(2, 1) = mouse_ray.b(2); local_ray = m * world_ray.colwise().homogeneous(); - return Linef3(Pointf3(local_ray(0, 0), local_ray(1, 0), local_ray(2, 0)), Pointf3(local_ray(0, 1), local_ray(1, 1), local_ray(2, 1))).intersect_plane(0.0); + return Linef3(Vec3d(local_ray(0, 0), local_ray(1, 0), local_ray(2, 0)), Vec3d(local_ray(0, 1), local_ray(1, 1), local_ray(2, 1))).intersect_plane(0.0); } GLGizmoRotate3D::GLGizmoRotate3D() @@ -708,17 +708,17 @@ bool GLGizmoScale::on_init() void GLGizmoScale::on_start_dragging() { if (m_hover_id != -1) - m_starting_drag_position = m_grabbers[m_hover_id].center; + m_starting_drag_position = to_2d(m_grabbers[m_hover_id].center); } void GLGizmoScale::on_update(const Linef3& mouse_ray) { - Pointf mouse_pos = mouse_ray.intersect_plane(0.0); - Pointf center(0.5 * (m_grabbers[1].center.x + m_grabbers[0].center.x), 0.5 * (m_grabbers[3].center.y + m_grabbers[0].center.y)); + Vec2d mouse_pos = to_2d(mouse_ray.intersect_plane(0.0)); + Vec2d center(0.5 * (m_grabbers[1].center(0) + m_grabbers[0].center(0)), 0.5 * (m_grabbers[3].center(1) + m_grabbers[0].center(1))); - coordf_t orig_len = length(m_starting_drag_position - center); - coordf_t new_len = length(mouse_pos - center); - coordf_t ratio = (orig_len != 0.0) ? new_len / orig_len : 1.0; + double orig_len = (m_starting_drag_position - center).norm(); + double new_len = (mouse_pos - center).norm(); + double ratio = (orig_len != 0.0) ? new_len / orig_len : 1.0; m_scale = m_starting_scale * (float)ratio; } @@ -727,15 +727,15 @@ void GLGizmoScale::on_render(const BoundingBoxf3& box) const { ::glDisable(GL_DEPTH_TEST); - coordf_t min_x = box.min.x - (coordf_t)Offset; - coordf_t max_x = box.max.x + (coordf_t)Offset; - coordf_t min_y = box.min.y - (coordf_t)Offset; - coordf_t max_y = box.max.y + (coordf_t)Offset; + double min_x = box.min(0) - (double)Offset; + double max_x = box.max(0) + (double)Offset; + double min_y = box.min(1) - (double)Offset; + double max_y = box.max(1) + (double)Offset; - m_grabbers[0].center = Pointf3(min_x, min_y, 0.0f); - m_grabbers[1].center = Pointf3(max_x, min_y, 0.0f); - m_grabbers[2].center = Pointf3(max_x, max_y, 0.0f); - m_grabbers[3].center = Pointf3(min_x, max_y, 0.0f); + m_grabbers[0].center = Vec3d(min_x, min_y, 0.0); + m_grabbers[1].center = Vec3d(max_x, min_y, 0.0); + m_grabbers[2].center = Vec3d(max_x, max_y, 0.0); + m_grabbers[3].center = Vec3d(min_x, max_y, 0.0); ::glLineWidth(2.0f); ::glColor3fv(m_drag_color); @@ -744,7 +744,7 @@ void GLGizmoScale::on_render(const BoundingBoxf3& box) const ::glBegin(GL_LINE_LOOP); for (unsigned int i = 0; i < 4; ++i) { - ::glVertex3f((GLfloat)m_grabbers[i].center.x, (GLfloat)m_grabbers[i].center.y, 0.0f); + ::glVertex3f((GLfloat)m_grabbers[i].center(0), (GLfloat)m_grabbers[i].center(1), 0.0f); } ::glEnd(); @@ -841,34 +841,34 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const { ::glEnable(GL_DEPTH_TEST); - Vectorf3 offset_vec((coordf_t)Offset, (coordf_t)Offset, (coordf_t)Offset); + Vec3d offset_vec((double)Offset, (double)Offset, (double)Offset); m_box = BoundingBoxf3(box.min - offset_vec, box.max + offset_vec); - const Pointf3& center = m_box.center(); + const Vec3d& center = m_box.center(); // x axis - m_grabbers[0].center = Pointf3(m_box.min.x, center.y, center.z); - m_grabbers[1].center = Pointf3(m_box.max.x, center.y, center.z); + m_grabbers[0].center = Vec3d(m_box.min(0), center(1), center(2)); + m_grabbers[1].center = Vec3d(m_box.max(0), center(1), center(2)); ::memcpy((void*)m_grabbers[0].color, (const void*)RED, 3 * sizeof(float)); ::memcpy((void*)m_grabbers[1].color, (const void*)RED, 3 * sizeof(float)); // y axis - m_grabbers[2].center = Pointf3(center.x, m_box.min.y, center.z); - m_grabbers[3].center = Pointf3(center.x, m_box.max.y, center.z); + m_grabbers[2].center = Vec3d(center(0), m_box.min(1), center(2)); + m_grabbers[3].center = Vec3d(center(0), m_box.max(1), center(2)); ::memcpy((void*)m_grabbers[2].color, (const void*)GREEN, 3 * sizeof(float)); ::memcpy((void*)m_grabbers[3].color, (const void*)GREEN, 3 * sizeof(float)); // z axis - m_grabbers[4].center = Pointf3(center.x, center.y, m_box.min.z); - m_grabbers[5].center = Pointf3(center.x, center.y, m_box.max.z); + m_grabbers[4].center = Vec3d(center(0), center(1), m_box.min(2)); + m_grabbers[5].center = Vec3d(center(0), center(1), m_box.max(2)); ::memcpy((void*)m_grabbers[4].color, (const void*)BLUE, 3 * sizeof(float)); ::memcpy((void*)m_grabbers[5].color, (const void*)BLUE, 3 * sizeof(float)); // uniform - m_grabbers[6].center = Pointf3(m_box.min.x, m_box.min.y, m_box.min.z); - m_grabbers[7].center = Pointf3(m_box.max.x, m_box.min.y, m_box.min.z); - m_grabbers[8].center = Pointf3(m_box.max.x, m_box.max.y, m_box.min.z); - m_grabbers[9].center = Pointf3(m_box.min.x, m_box.max.y, m_box.min.z); + m_grabbers[6].center = Vec3d(m_box.min(0), m_box.min(1), m_box.min(2)); + m_grabbers[7].center = Vec3d(m_box.max(0), m_box.min(1), m_box.min(2)); + m_grabbers[8].center = Vec3d(m_box.max(0), m_box.max(1), m_box.min(2)); + m_grabbers[9].center = Vec3d(m_box.min(0), m_box.max(1), m_box.min(2)); for (int i = 6; i < 10; ++i) { ::memcpy((void*)m_grabbers[i].color, (const void*)m_highlight_color, 3 * sizeof(float)); @@ -942,26 +942,26 @@ void GLGizmoScale3D::render_box() const { // bottom face ::glBegin(GL_LINE_LOOP); - ::glVertex3f((GLfloat)m_box.min.x, (GLfloat)m_box.min.y, (GLfloat)m_box.min.z); - ::glVertex3f((GLfloat)m_box.min.x, (GLfloat)m_box.max.y, (GLfloat)m_box.min.z); - ::glVertex3f((GLfloat)m_box.max.x, (GLfloat)m_box.max.y, (GLfloat)m_box.min.z); - ::glVertex3f((GLfloat)m_box.max.x, (GLfloat)m_box.min.y, (GLfloat)m_box.min.z); + ::glVertex3f((GLfloat)m_box.min(0), (GLfloat)m_box.min(1), (GLfloat)m_box.min(2)); + ::glVertex3f((GLfloat)m_box.min(0), (GLfloat)m_box.max(1), (GLfloat)m_box.min(2)); + ::glVertex3f((GLfloat)m_box.max(0), (GLfloat)m_box.max(1), (GLfloat)m_box.min(2)); + ::glVertex3f((GLfloat)m_box.max(0), (GLfloat)m_box.min(1), (GLfloat)m_box.min(2)); ::glEnd(); // top face ::glBegin(GL_LINE_LOOP); - ::glVertex3f((GLfloat)m_box.min.x, (GLfloat)m_box.min.y, (GLfloat)m_box.max.z); - ::glVertex3f((GLfloat)m_box.min.x, (GLfloat)m_box.max.y, (GLfloat)m_box.max.z); - ::glVertex3f((GLfloat)m_box.max.x, (GLfloat)m_box.max.y, (GLfloat)m_box.max.z); - ::glVertex3f((GLfloat)m_box.max.x, (GLfloat)m_box.min.y, (GLfloat)m_box.max.z); + ::glVertex3f((GLfloat)m_box.min(0), (GLfloat)m_box.min(1), (GLfloat)m_box.max(2)); + ::glVertex3f((GLfloat)m_box.min(0), (GLfloat)m_box.max(1), (GLfloat)m_box.max(2)); + ::glVertex3f((GLfloat)m_box.max(0), (GLfloat)m_box.max(1), (GLfloat)m_box.max(2)); + ::glVertex3f((GLfloat)m_box.max(0), (GLfloat)m_box.min(1), (GLfloat)m_box.max(2)); ::glEnd(); // vertical edges ::glBegin(GL_LINES); - ::glVertex3f((GLfloat)m_box.min.x, (GLfloat)m_box.min.y, (GLfloat)m_box.min.z); ::glVertex3f((GLfloat)m_box.min.x, (GLfloat)m_box.min.y, (GLfloat)m_box.max.z); - ::glVertex3f((GLfloat)m_box.min.x, (GLfloat)m_box.max.y, (GLfloat)m_box.min.z); ::glVertex3f((GLfloat)m_box.min.x, (GLfloat)m_box.max.y, (GLfloat)m_box.max.z); - ::glVertex3f((GLfloat)m_box.max.x, (GLfloat)m_box.max.y, (GLfloat)m_box.min.z); ::glVertex3f((GLfloat)m_box.max.x, (GLfloat)m_box.max.y, (GLfloat)m_box.max.z); - ::glVertex3f((GLfloat)m_box.max.x, (GLfloat)m_box.min.y, (GLfloat)m_box.min.z); ::glVertex3f((GLfloat)m_box.max.x, (GLfloat)m_box.min.y, (GLfloat)m_box.max.z); + ::glVertex3f((GLfloat)m_box.min(0), (GLfloat)m_box.min(1), (GLfloat)m_box.min(2)); ::glVertex3f((GLfloat)m_box.min(0), (GLfloat)m_box.min(1), (GLfloat)m_box.max(2)); + ::glVertex3f((GLfloat)m_box.min(0), (GLfloat)m_box.max(1), (GLfloat)m_box.min(2)); ::glVertex3f((GLfloat)m_box.min(0), (GLfloat)m_box.max(1), (GLfloat)m_box.max(2)); + ::glVertex3f((GLfloat)m_box.max(0), (GLfloat)m_box.max(1), (GLfloat)m_box.min(2)); ::glVertex3f((GLfloat)m_box.max(0), (GLfloat)m_box.max(1), (GLfloat)m_box.max(2)); + ::glVertex3f((GLfloat)m_box.max(0), (GLfloat)m_box.min(1), (GLfloat)m_box.min(2)); ::glVertex3f((GLfloat)m_box.max(0), (GLfloat)m_box.min(1), (GLfloat)m_box.max(2)); ::glEnd(); } @@ -971,25 +971,25 @@ void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int if ((id_1 < grabbers_count) && (id_2 < grabbers_count)) { ::glBegin(GL_LINES); - ::glVertex3f((GLfloat)m_grabbers[id_1].center.x, (GLfloat)m_grabbers[id_1].center.y, (GLfloat)m_grabbers[id_1].center.z); - ::glVertex3f((GLfloat)m_grabbers[id_2].center.x, (GLfloat)m_grabbers[id_2].center.y, (GLfloat)m_grabbers[id_2].center.z); + ::glVertex3f((GLfloat)m_grabbers[id_1].center(0), (GLfloat)m_grabbers[id_1].center(1), (GLfloat)m_grabbers[id_1].center(2)); + ::glVertex3f((GLfloat)m_grabbers[id_2].center(0), (GLfloat)m_grabbers[id_2].center(1), (GLfloat)m_grabbers[id_2].center(2)); ::glEnd(); } } -Linef3 transform(const Linef3& line, const Eigen::Transform& t) +Linef3 transform(const Linef3& line, const Transform3d& t) { - Eigen::Matrix world_line; - Eigen::Matrix local_line; - world_line(0, 0) = (float)line.a.x; - world_line(1, 0) = (float)line.a.y; - world_line(2, 0) = (float)line.a.z; - world_line(0, 1) = (float)line.b.x; - world_line(1, 1) = (float)line.b.y; - world_line(2, 1) = (float)line.b.z; + Eigen::Matrix world_line; + Eigen::Matrix local_line; + world_line(0, 0) = line.a(0); + world_line(1, 0) = line.a(1); + world_line(2, 0) = line.a(2); + world_line(0, 1) = line.b(0); + world_line(1, 1) = line.b(1); + world_line(2, 1) = line.b(2); local_line = t * world_line.colwise().homogeneous(); - return Linef3(Pointf3(local_line(0, 0), local_line(1, 0), local_line(2, 0)), Pointf3(local_line(0, 1), local_line(1, 1), local_line(2, 1))); + return Linef3(Vec3d(local_line(0, 0), local_line(1, 0), local_line(2, 0)), Vec3d(local_line(0, 1), local_line(1, 1), local_line(2, 1))); } void GLGizmoScale3D::do_scale_x(const Linef3& mouse_ray) @@ -1020,8 +1020,8 @@ void GLGizmoScale3D::do_scale_z(const Linef3& mouse_ray) void GLGizmoScale3D::do_scale_uniform(const Linef3& mouse_ray) { - Pointf3 center = m_starting_center; - center.z = m_box.min.z; + Vec3d center = m_starting_center; + center(2) = m_box.min(2); double ratio = calc_ratio(0, mouse_ray, center); if (ratio > 0.0) @@ -1032,17 +1032,17 @@ void GLGizmoScale3D::do_scale_uniform(const Linef3& mouse_ray) } } -double GLGizmoScale3D::calc_ratio(unsigned int preferred_plane_id, const Linef3& mouse_ray, const Pointf3& center) const +double GLGizmoScale3D::calc_ratio(unsigned int preferred_plane_id, const Linef3& mouse_ray, const Vec3d& center) const { double ratio = 0.0; - Vectorf3 starting_vec = m_starting_drag_position - center; - double len_starting_vec = length(starting_vec); + Vec3d starting_vec = m_starting_drag_position - center; + double len_starting_vec = starting_vec.norm(); if (len_starting_vec == 0.0) return ratio; - Vectorf3 starting_vec_dir = normalize(starting_vec); - Vectorf3 mouse_dir = mouse_ray.unit_vector(); + Vec3d starting_vec_dir = starting_vec.normalized(); + Vec3d mouse_dir = mouse_ray.unit_vector(); unsigned int plane_id = preferred_plane_id; // 1st try to see if the mouse direction is close enough to the preferred plane normal @@ -1051,17 +1051,17 @@ double GLGizmoScale3D::calc_ratio(unsigned int preferred_plane_id, const Linef3& { case 0: { - dot_to_normal = std::abs(dot(mouse_dir, Vectorf3(0.0, 0.0, 1.0))); + dot_to_normal = std::abs(mouse_dir.dot(Vec3d::UnitZ())); break; } case 1: { - dot_to_normal = std::abs(dot(mouse_dir, Vectorf3(0.0, -1.0, 0.0))); + dot_to_normal = std::abs(mouse_dir.dot(-Vec3d::UnitY())); break; } case 2: { - dot_to_normal = std::abs(dot(mouse_dir, Vectorf3(1.0, 0.0, 0.0))); + dot_to_normal = std::abs(mouse_dir.dot(Vec3d::UnitX())); break; } } @@ -1073,9 +1073,9 @@ double GLGizmoScale3D::calc_ratio(unsigned int preferred_plane_id, const Linef3& typedef std::map ProjsMap; ProjsMap projs_map; - projs_map.insert(ProjsMap::value_type(std::abs(dot(mouse_dir, Vectorf3(0.0, 0.0, 1.0))), 0)); // plane xy - projs_map.insert(ProjsMap::value_type(std::abs(dot(mouse_dir, Vectorf3(0.0, -1.0, 0.0))), 1)); // plane xz - projs_map.insert(ProjsMap::value_type(std::abs(dot(mouse_dir, Vectorf3(1.0, 0.0, 0.0))), 2)); // plane yz + projs_map.insert(ProjsMap::value_type(std::abs(mouse_dir.dot(Vec3d::UnitZ())), 0)); // plane xy + projs_map.insert(ProjsMap::value_type(std::abs(mouse_dir.dot(-Vec3d::UnitY())), 1)); // plane xz + projs_map.insert(ProjsMap::value_type(std::abs(mouse_dir.dot(Vec3d::UnitX())), 2)); // plane yz plane_id = projs_map.rbegin()->second; } @@ -1084,36 +1084,36 @@ double GLGizmoScale3D::calc_ratio(unsigned int preferred_plane_id, const Linef3& case 0: { // calculates the intersection of the mouse ray with the plane parallel to plane XY and passing through the given center - Eigen::Transform m = Eigen::Transform::Identity(); - m.translate(Eigen::Vector3f(-(float)center.x, -(float)center.y, -(float)center.z)); - Pointf mouse_pos_2d = transform(mouse_ray, m).intersect_plane(0.0); + Transform3d m = Transform3d::Identity(); + m.translate(-center); + Vec2d mouse_pos_2d = to_2d(transform(mouse_ray, m).intersect_plane(0.0)); // ratio is given by the projection of the calculated intersection on the starting vector divided by the starting vector length - ratio = dot(Vectorf3(mouse_pos_2d.x, mouse_pos_2d.y, 0.0), starting_vec_dir) / len_starting_vec; + ratio = starting_vec_dir.dot(Vec3d(mouse_pos_2d(0), mouse_pos_2d(1), 0.0)) / len_starting_vec; break; } case 1: { // calculates the intersection of the mouse ray with the plane parallel to plane XZ and passing through the given center - Eigen::Transform m = Eigen::Transform::Identity(); - m.rotate(Eigen::AngleAxisf(-0.5f * (float)PI, Eigen::Vector3f::UnitX())); - m.translate(Eigen::Vector3f(-(float)center.x, -(float)center.y, -(float)center.z)); - Pointf mouse_pos_2d = transform(mouse_ray, m).intersect_plane(0.0); + Transform3d m = Transform3d::Identity(); + m.rotate(Eigen::AngleAxisd(-0.5 * (double)PI, Vec3d::UnitX())); + m.translate(-center); + Vec2d mouse_pos_2d = to_2d(transform(mouse_ray, m).intersect_plane(0.0)); // ratio is given by the projection of the calculated intersection on the starting vector divided by the starting vector length - ratio = dot(Vectorf3(mouse_pos_2d.x, 0.0, mouse_pos_2d.y), starting_vec_dir) / len_starting_vec; + ratio = starting_vec_dir.dot(Vec3d(mouse_pos_2d(0), 0.0, mouse_pos_2d(1))) / len_starting_vec; break; } case 2: { // calculates the intersection of the mouse ray with the plane parallel to plane YZ and passing through the given center - Eigen::Transform m = Eigen::Transform::Identity(); - m.rotate(Eigen::AngleAxisf(-0.5f * (float)PI, Eigen::Vector3f::UnitY())); - m.translate(Eigen::Vector3f(-(float)center.x, -(float)center.y, -(float)center.z)); - Pointf mouse_pos_2d = transform(mouse_ray, m).intersect_plane(0.0); + Transform3d m = Transform3d::Identity(); + m.rotate(Eigen::AngleAxisd(-0.5f * (double)PI, Vec3d::UnitY())); + m.translate(-center); + Vec2d mouse_pos_2d = to_2d(transform(mouse_ray, m).intersect_plane(0.0)); // ratio is given by the projection of the calculated intersection on the starting vector divided by the starting vector length - ratio = dot(Vectorf3(0.0, mouse_pos_2d.y, -mouse_pos_2d.x), starting_vec_dir) / len_starting_vec; + ratio = starting_vec_dir.dot(Vec3d(0.0, mouse_pos_2d(1), -mouse_pos_2d(0))) / len_starting_vec; break; } } diff --git a/xs/src/slic3r/GUI/GLGizmo.hpp b/xs/src/slic3r/GUI/GLGizmo.hpp index b584286b4..0bef4bf63 100644 --- a/xs/src/slic3r/GUI/GLGizmo.hpp +++ b/xs/src/slic3r/GUI/GLGizmo.hpp @@ -12,7 +12,6 @@ namespace Slic3r { class BoundingBoxf3; -class Pointf3; class Linef3; namespace GUI { @@ -25,7 +24,7 @@ protected: static const float HalfSize; static const float DraggingScaleFactor; - Pointf3 center; + Vec3d center; float angle_x; float angle_y; float angle_z; @@ -142,7 +141,7 @@ private: Axis m_axis; float m_angle; - mutable Pointf3 m_center; + mutable Vec3d m_center; mutable float m_radius; mutable bool m_keep_initial_values; @@ -169,7 +168,8 @@ private: void render_grabber() const; void transform_to_local() const; - Pointf mouse_position_in_local_plane(const Linef3& mouse_ray) const; + // returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate + Vec3d mouse_position_in_local_plane(const Linef3& mouse_ray) const; }; class GLGizmoRotate3D : public GLGizmoBase @@ -234,7 +234,7 @@ class GLGizmoScale : public GLGizmoBase float m_scale; float m_starting_scale; - Pointf m_starting_drag_position; + Vec2d m_starting_drag_position; public: GLGizmoScale(); @@ -264,8 +264,8 @@ class GLGizmoScale3D : public GLGizmoBase float m_starting_scale_y; float m_starting_scale_z; - Pointf3 m_starting_drag_position; - Pointf3 m_starting_center; + Vec3d m_starting_drag_position; + Vec3d m_starting_center; public: GLGizmoScale3D(); @@ -302,7 +302,7 @@ private: void do_scale_z(const Linef3& mouse_ray); void do_scale_uniform(const Linef3& mouse_ray); - double calc_ratio(unsigned int preferred_plane_id, const Linef3& mouse_ray, const Pointf3& center) const; + double calc_ratio(unsigned int preferred_plane_id, const Linef3& mouse_ray, const Vec3d& center) const; }; } // namespace GUI diff --git a/xs/src/slic3r/GUI/GLToolbar.cpp b/xs/src/slic3r/GUI/GLToolbar.cpp index fd993f5a2..e82369db4 100644 --- a/xs/src/slic3r/GUI/GLToolbar.cpp +++ b/xs/src/slic3r/GUI/GLToolbar.cpp @@ -1,5 +1,7 @@ +#include "../../libslic3r/point.hpp" #include "GLToolbar.hpp" +#include "../../libslic3r/libslic3r.h" #include "../../slic3r/GUI/GLCanvas3D.hpp" #include @@ -267,7 +269,7 @@ bool GLToolbar::is_item_pressed(const std::string& name) const return false; } -void GLToolbar::update_hover_state(const Pointf& mouse_pos) +void GLToolbar::update_hover_state(const Vec2d& mouse_pos) { if (!m_enabled) return; @@ -288,7 +290,7 @@ void GLToolbar::update_hover_state(const Pointf& mouse_pos) } } -int GLToolbar::contains_mouse(const Pointf& mouse_pos) const +int GLToolbar::contains_mouse(const Vec2d& mouse_pos) const { if (!m_enabled) return -1; @@ -342,7 +344,6 @@ void GLToolbar::do_action(unsigned int item_id) } void GLToolbar::render() const -//void GLToolbar::render(const Pointf& mouse_pos) const { if (!m_enabled || m_items.empty()) return; @@ -407,13 +408,13 @@ float GLToolbar::_get_main_size() const return size; } -void GLToolbar::_update_hover_state_horizontal(const Pointf& mouse_pos) +void GLToolbar::_update_hover_state_horizontal(const Vec2d& mouse_pos) { float zoom = m_parent.get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; Size cnv_size = m_parent.get_canvas_size(); - Pointf scaled_mouse_pos((mouse_pos.x - 0.5f * (float)cnv_size.get_width()) * inv_zoom, (0.5f * (float)cnv_size.get_height() - mouse_pos.y) * inv_zoom); + Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom); float scaled_icons_size = (float)m_icons_texture.items_icon_size * inv_zoom; float scaled_separator_size = m_layout.separator_size * inv_zoom; @@ -437,7 +438,7 @@ void GLToolbar::_update_hover_state_horizontal(const Pointf& mouse_pos) float bottom = top - scaled_icons_size; GLToolbarItem::EState state = item->get_state(); - bool inside = (left <= scaled_mouse_pos.x) && (scaled_mouse_pos.x <= right) && (bottom <= scaled_mouse_pos.y) && (scaled_mouse_pos.y <= top); + bool inside = (left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top); switch (state) { @@ -487,13 +488,13 @@ void GLToolbar::_update_hover_state_horizontal(const Pointf& mouse_pos) m_parent.set_tooltip(tooltip); } -void GLToolbar::_update_hover_state_vertical(const Pointf& mouse_pos) +void GLToolbar::_update_hover_state_vertical(const Vec2d& mouse_pos) { float zoom = m_parent.get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; Size cnv_size = m_parent.get_canvas_size(); - Pointf scaled_mouse_pos((mouse_pos.x - 0.5f * (float)cnv_size.get_width()) * inv_zoom, (0.5f * (float)cnv_size.get_height() - mouse_pos.y) * inv_zoom); + Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom); float scaled_icons_size = (float)m_icons_texture.items_icon_size * inv_zoom; float scaled_separator_size = m_layout.separator_size * inv_zoom; @@ -517,7 +518,7 @@ void GLToolbar::_update_hover_state_vertical(const Pointf& mouse_pos) float bottom = top - scaled_icons_size; GLToolbarItem::EState state = item->get_state(); - bool inside = (left <= scaled_mouse_pos.x) && (scaled_mouse_pos.x <= right) && (bottom <= scaled_mouse_pos.y) && (scaled_mouse_pos.y <= top); + bool inside = (left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top); switch (state) { @@ -567,13 +568,13 @@ void GLToolbar::_update_hover_state_vertical(const Pointf& mouse_pos) m_parent.set_tooltip(tooltip); } -int GLToolbar::_contains_mouse_horizontal(const Pointf& mouse_pos) const +int GLToolbar::_contains_mouse_horizontal(const Vec2d& mouse_pos) const { float zoom = m_parent.get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; Size cnv_size = m_parent.get_canvas_size(); - Pointf scaled_mouse_pos((mouse_pos.x - 0.5f * (float)cnv_size.get_width()) * inv_zoom, (0.5f * (float)cnv_size.get_height() - mouse_pos.y) * inv_zoom); + Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom); float scaled_icons_size = (float)m_icons_texture.items_icon_size * inv_zoom; float scaled_separator_size = m_layout.separator_size * inv_zoom; @@ -598,7 +599,7 @@ int GLToolbar::_contains_mouse_horizontal(const Pointf& mouse_pos) const float right = left + scaled_icons_size; float bottom = top - scaled_icons_size; - if ((left <= scaled_mouse_pos.x) && (scaled_mouse_pos.x <= right) && (bottom <= scaled_mouse_pos.y) && (scaled_mouse_pos.y <= top)) + if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) return id; left += icon_stride; @@ -608,13 +609,13 @@ int GLToolbar::_contains_mouse_horizontal(const Pointf& mouse_pos) const return -1; } -int GLToolbar::_contains_mouse_vertical(const Pointf& mouse_pos) const +int GLToolbar::_contains_mouse_vertical(const Vec2d& mouse_pos) const { float zoom = m_parent.get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; Size cnv_size = m_parent.get_canvas_size(); - Pointf scaled_mouse_pos((mouse_pos.x - 0.5f * (float)cnv_size.get_width()) * inv_zoom, (0.5f * (float)cnv_size.get_height() - mouse_pos.y) * inv_zoom); + Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom); float scaled_icons_size = (float)m_icons_texture.items_icon_size * inv_zoom; float scaled_separator_size = m_layout.separator_size * inv_zoom; @@ -639,7 +640,7 @@ int GLToolbar::_contains_mouse_vertical(const Pointf& mouse_pos) const float right = left + scaled_icons_size; float bottom = top - scaled_icons_size; - if ((left <= scaled_mouse_pos.x) && (scaled_mouse_pos.x <= right) && (bottom <= scaled_mouse_pos.y) && (scaled_mouse_pos.y <= top)) + if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top)) return id; top -= icon_stride; diff --git a/xs/src/slic3r/GUI/GLToolbar.hpp b/xs/src/slic3r/GUI/GLToolbar.hpp index b6eb6b19c..18d3f130d 100644 --- a/xs/src/slic3r/GUI/GLToolbar.hpp +++ b/xs/src/slic3r/GUI/GLToolbar.hpp @@ -8,9 +8,6 @@ #include namespace Slic3r { - -class Pointf; - namespace GUI { class GLCanvas3D; @@ -148,10 +145,10 @@ public: bool is_item_pressed(const std::string& name) const; - void update_hover_state(const Pointf& mouse_pos); + void update_hover_state(const Vec2d& mouse_pos); // returns the id of the item under the given mouse position or -1 if none - int contains_mouse(const Pointf& mouse_pos) const; + int contains_mouse(const Vec2d& mouse_pos) const; void do_action(unsigned int item_id); @@ -163,10 +160,11 @@ private: float _get_height_horizontal() const; float _get_height_vertical() const; float _get_main_size() const; - void _update_hover_state_horizontal(const Pointf& mouse_pos); - void _update_hover_state_vertical(const Pointf& mouse_pos); - int _contains_mouse_horizontal(const Pointf& mouse_pos) const; - int _contains_mouse_vertical(const Pointf& mouse_pos) const; + void _update_hover_state_horizontal(const Vec2d& mouse_pos); + void _update_hover_state_vertical(const Vec2d& mouse_pos); + int _contains_mouse_horizontal(const Vec2d& mouse_pos) const; + int _contains_mouse_vertical(const Vec2d& mouse_pos) const; + void _render_horizontal() const; void _render_vertical() const; }; diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 8555f0b92..18f63f65e 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -610,10 +610,10 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt break; case coPoints:{ if (opt_key.compare("bed_shape") == 0){ - config.option(opt_key)->values = boost::any_cast>(value); + config.option(opt_key)->values = boost::any_cast>(value); break; } - ConfigOptionPoints* vec_new = new ConfigOptionPoints{ boost::any_cast(value) }; + ConfigOptionPoints* vec_new = new ConfigOptionPoints{ boost::any_cast(value) }; config.option(opt_key)->set_at(vec_new, opt_index, 0); } break; @@ -895,10 +895,10 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl g_wiping_dialog_button->Bind(wxEVT_BUTTON, ([parent](wxCommandEvent& e) { auto &config = g_PresetBundle->project_config; - std::vector init_matrix = (config.option("wiping_volumes_matrix"))->values; - std::vector init_extruders = (config.option("wiping_volumes_extruders"))->values; + const std::vector &init_matrix = (config.option("wiping_volumes_matrix"))->values; + const std::vector &init_extruders = (config.option("wiping_volumes_extruders"))->values; - WipingDialog dlg(parent,std::vector(init_matrix.begin(),init_matrix.end()),std::vector(init_extruders.begin(),init_extruders.end())); + WipingDialog dlg(parent,cast(init_matrix),cast(init_extruders)); if (dlg.ShowModal() == wxID_OK) { std::vector matrix = dlg.get_matrix(); diff --git a/xs/src/slic3r/GUI/RammingChart.cpp b/xs/src/slic3r/GUI/RammingChart.cpp index 2603a5eab..8954ff93b 100644 --- a/xs/src/slic3r/GUI/RammingChart.cpp +++ b/xs/src/slic3r/GUI/RammingChart.cpp @@ -261,7 +261,7 @@ std::vector Chart::get_ramming_speed(float sampling) const { std::vector> Chart::get_buttons() const { std::vector> buttons_out; for (const auto& button : m_buttons) - buttons_out.push_back(std::make_pair(button.get_pos().m_x,button.get_pos().m_y)); + buttons_out.push_back(std::make_pair(float(button.get_pos().m_x),float(button.get_pos().m_y))); return buttons_out; } diff --git a/xs/src/xsinit.h b/xs/src/xsinit.h index 9365f1979..c9e363602 100644 --- a/xs/src/xsinit.h +++ b/xs/src/xsinit.h @@ -68,7 +68,16 @@ extern "C" { #undef fputc #undef fwrite #undef fclose + + // Breaks compilation with Eigen matrices embedded into Slic3r::Point. + #undef malloc + #undef realloc + #undef free + #undef select #endif /* _MSC_VER */ +#undef Zero +#undef Packet +#undef _ } #endif @@ -188,9 +197,9 @@ void from_SV_check(SV* poly_sv, Polyline* THIS); SV* to_SV_pureperl(const Point* THIS); void from_SV(SV* point_sv, Point* point); void from_SV_check(SV* point_sv, Point* point); -SV* to_SV_pureperl(const Pointf* point); -bool from_SV(SV* point_sv, Pointf* point); -bool from_SV_check(SV* point_sv, Pointf* point); +SV* to_SV_pureperl(const Vec2d* point); +bool from_SV(SV* point_sv, Vec2d* point); +bool from_SV_check(SV* point_sv, Vec2d* point); void from_SV_check(SV* surface_sv, Surface* THIS); SV* to_SV(TriangleMesh* THIS); diff --git a/xs/xsp/BoundingBox.xsp b/xs/xsp/BoundingBox.xsp index ebeb17822..a34cad0bc 100644 --- a/xs/xsp/BoundingBox.xsp +++ b/xs/xsp/BoundingBox.xsp @@ -25,15 +25,15 @@ double radius(); Clone min_point() %code{% RETVAL = THIS->min; %}; Clone max_point() %code{% RETVAL = THIS->max; %}; - int x_min() %code{% RETVAL = THIS->min.x; %}; - int x_max() %code{% RETVAL = THIS->max.x; %}; - int y_min() %code{% RETVAL = THIS->min.y; %}; - int y_max() %code{% RETVAL = THIS->max.y; %}; - void set_x_min(double val) %code{% THIS->min.x = val; %}; - void set_x_max(double val) %code{% THIS->max.x = val; %}; - void set_y_min(double val) %code{% THIS->min.y = val; %}; - void set_y_max(double val) %code{% THIS->max.y = val; %}; - std::string serialize() %code{% char buf[2048]; sprintf(buf, "%ld,%ld;%ld,%ld", THIS->min.x, THIS->min.y, THIS->max.x, THIS->max.y); RETVAL = buf; %}; + int x_min() %code{% RETVAL = THIS->min(0); %}; + int x_max() %code{% RETVAL = THIS->max(0); %}; + int y_min() %code{% RETVAL = THIS->min(1); %}; + int y_max() %code{% RETVAL = THIS->max(1); %}; + void set_x_min(double val) %code{% THIS->min(0) = val; %}; + void set_x_max(double val) %code{% THIS->max(0) = val; %}; + void set_y_min(double val) %code{% THIS->min(1) = val; %}; + void set_y_max(double val) %code{% THIS->max(1) = val; %}; + std::string serialize() %code{% char buf[2048]; sprintf(buf, "%ld,%ld;%ld,%ld", THIS->min(0), THIS->min(1), THIS->max(0), THIS->max(1)); RETVAL = buf; %}; bool defined() %code{% RETVAL = THIS->defined; %}; %{ @@ -56,24 +56,24 @@ new_from_points(CLASS, points) Clone clone() %code{% RETVAL = THIS; %}; void merge(BoundingBoxf* bb) %code{% THIS->merge(*bb); %}; - void merge_point(Pointf* point) %code{% THIS->merge(*point); %}; + void merge_point(Vec2d* point) %code{% THIS->merge(*point); %}; void scale(double factor); void translate(double x, double y); - Clone size(); - Clone center(); + Clone size(); + Clone center(); double radius(); bool empty() %code{% RETVAL = empty(*THIS); %}; - Clone min_point() %code{% RETVAL = THIS->min; %}; - Clone max_point() %code{% RETVAL = THIS->max; %}; - double x_min() %code{% RETVAL = THIS->min.x; %}; - double x_max() %code{% RETVAL = THIS->max.x; %}; - double y_min() %code{% RETVAL = THIS->min.y; %}; - double y_max() %code{% RETVAL = THIS->max.y; %}; - void set_x_min(double val) %code{% THIS->min.x = val; %}; - void set_x_max(double val) %code{% THIS->max.x = val; %}; - void set_y_min(double val) %code{% THIS->min.y = val; %}; - void set_y_max(double val) %code{% THIS->max.y = val; %}; - std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf;%lf,%lf", THIS->min.x, THIS->min.y, THIS->max.x, THIS->max.y); RETVAL = buf; %}; + Clone min_point() %code{% RETVAL = THIS->min; %}; + Clone max_point() %code{% RETVAL = THIS->max; %}; + double x_min() %code{% RETVAL = THIS->min(0); %}; + double x_max() %code{% RETVAL = THIS->max(0); %}; + double y_min() %code{% RETVAL = THIS->min(1); %}; + double y_max() %code{% RETVAL = THIS->max(1); %}; + void set_x_min(double val) %code{% THIS->min(0) = val; %}; + void set_x_max(double val) %code{% THIS->max(0) = val; %}; + void set_y_min(double val) %code{% THIS->min(1) = val; %}; + void set_y_max(double val) %code{% THIS->max(1) = val; %}; + std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf;%lf,%lf", THIS->min(0), THIS->min(1), THIS->max(0), THIS->max(1)); RETVAL = buf; %}; bool defined() %code{% RETVAL = THIS->defined; %}; %{ @@ -96,23 +96,23 @@ new_from_points(CLASS, points) Clone clone() %code{% RETVAL = THIS; %}; void merge(BoundingBoxf3* bb) %code{% THIS->merge(*bb); %}; - void merge_point(Pointf3* point) %code{% THIS->merge(*point); %}; + void merge_point(Vec3d* point) %code{% THIS->merge(*point); %}; void scale(double factor); void translate(double x, double y, double z); void offset(double delta); - bool contains_point(Pointf3* point) %code{% RETVAL = THIS->contains(*point); %}; - Clone size(); - Clone center(); + bool contains_point(Vec3d* point) %code{% RETVAL = THIS->contains(*point); %}; + Clone size(); + Clone center(); double radius(); bool empty() %code{% RETVAL = empty(*THIS); %}; - Clone min_point() %code{% RETVAL = THIS->min; %}; - Clone max_point() %code{% RETVAL = THIS->max; %}; - double x_min() %code{% RETVAL = THIS->min.x; %}; - double x_max() %code{% RETVAL = THIS->max.x; %}; - double y_min() %code{% RETVAL = THIS->min.y; %}; - double y_max() %code{% RETVAL = THIS->max.y; %}; - double z_min() %code{% RETVAL = THIS->min.z; %}; - double z_max() %code{% RETVAL = THIS->max.z; %}; - std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf,%lf;%lf,%lf,%lf", THIS->min.x, THIS->min.y, THIS->min.z, THIS->max.x, THIS->max.y, THIS->max.z); RETVAL = buf; %}; + Clone min_point() %code{% RETVAL = THIS->min; %}; + Clone max_point() %code{% RETVAL = THIS->max; %}; + double x_min() %code{% RETVAL = THIS->min(0); %}; + double x_max() %code{% RETVAL = THIS->max(0); %}; + double y_min() %code{% RETVAL = THIS->min(1); %}; + double y_max() %code{% RETVAL = THIS->max(1); %}; + double z_min() %code{% RETVAL = THIS->min(2); %}; + double z_max() %code{% RETVAL = THIS->max(2); %}; + std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf,%lf;%lf,%lf,%lf", THIS->min(0), THIS->min(1), THIS->min(2), THIS->max(0), THIS->max(1), THIS->max(2)); RETVAL = buf; %}; bool defined() %code{% RETVAL = THIS->defined; %}; }; diff --git a/xs/xsp/GCode.xsp b/xs/xsp/GCode.xsp index c1856ccf7..9e04edd4c 100644 --- a/xs/xsp/GCode.xsp +++ b/xs/xsp/GCode.xsp @@ -35,9 +35,9 @@ } %}; - Ref origin() + Ref origin() %code{% RETVAL = &(THIS->origin()); %}; - void set_origin(Pointf* pointf) + void set_origin(Vec2d* pointf) %code{% THIS->set_origin(*pointf); %}; Ref last_pos() %code{% RETVAL = &(THIS->last_pos()); %}; diff --git a/xs/xsp/GUI_3DScene.xsp b/xs/xsp/GUI_3DScene.xsp index 515675a31..5f1b55cf3 100644 --- a/xs/xsp/GUI_3DScene.xsp +++ b/xs/xsp/GUI_3DScene.xsp @@ -55,14 +55,10 @@ int object_idx() const; int volume_idx() const; int instance_idx() const; - Clone origin() const + Clone origin() const %code%{ RETVAL = THIS->get_origin(); %}; void translate(double x, double y, double z) - %code%{ - Pointf3 o = THIS->get_origin(); - o.translate(x, y, z); - THIS->set_origin(o); - %}; + %code%{ THIS->set_origin(THIS->get_origin() + Vec3d(x, y, z)); %}; Clone bounding_box() const %code%{ RETVAL = THIS->bounding_box; %}; diff --git a/xs/xsp/Geometry.xsp b/xs/xsp/Geometry.xsp index b23bbeffa..b7e92ba69 100644 --- a/xs/xsp/Geometry.xsp +++ b/xs/xsp/Geometry.xsp @@ -8,7 +8,7 @@ %package{Slic3r::Geometry}; -Pointfs arrange(size_t total_parts, Pointf* part, coordf_t dist, BoundingBoxf* bb = NULL) +Pointfs arrange(size_t total_parts, Vec2d* part, coordf_t dist, BoundingBoxf* bb = NULL) %code{% Pointfs points; if (! Slic3r::Geometry::arrange(total_parts, *part, dist, bb, points)) diff --git a/xs/xsp/Line.xsp b/xs/xsp/Line.xsp index 92429e57a..777dc41fa 100644 --- a/xs/xsp/Line.xsp +++ b/xs/xsp/Line.xsp @@ -29,7 +29,6 @@ bool parallel_to_line(Line* line) %code{% RETVAL = THIS->parallel_to(*line); %}; Clone midpoint(); - Clone point_at(double distance); Clone intersection_infinite(Line* other) %code{% Point p; @@ -37,8 +36,8 @@ if (!res) CONFESS("Intersection failed"); RETVAL = p; %}; - Clone as_polyline() - %code{% RETVAL = Polyline(*THIS); %}; + Polyline* as_polyline() + %code{% RETVAL = new Polyline(THIS->a, THIS->b); %}; Clone normal(); Clone vector(); double ccw(Point* point) @@ -70,7 +69,7 @@ Line::coincides_with(line_sv) CODE: Line line; from_SV_check(line_sv, &line); - RETVAL = THIS->coincides_with(line); + RETVAL = (*THIS) == line; OUTPUT: RETVAL @@ -79,15 +78,15 @@ Line::coincides_with(line_sv) %name{Slic3r::Linef3} class Linef3 { - Linef3(Pointf3* a, Pointf3* b) + Linef3(Vec3d* a, Vec3d* b) %code{% RETVAL = new Linef3(*a, *b); %}; ~Linef3(); Clone clone() %code{% RETVAL = THIS; %}; - Ref a() + Ref a() %code{% RETVAL = &THIS->a; %}; - Ref b() + Ref b() %code{% RETVAL = &THIS->b; %}; - Clone intersect_plane(double z); + Clone intersect_plane(double z); void scale(double factor); }; diff --git a/xs/xsp/Model.xsp b/xs/xsp/Model.xsp index 25c26c380..ac265a3b3 100644 --- a/xs/xsp/Model.xsp +++ b/xs/xsp/Model.xsp @@ -81,7 +81,7 @@ bool add_default_instances(); Clone bounding_box(); - void center_instances_around_point(Pointf* point) + void center_instances_around_point(Vec2d* point) %code%{ THIS->center_instances_around_point(*point); %}; void translate(double x, double y, double z); Clone mesh(); @@ -289,9 +289,9 @@ ModelMaterial::attributes() void set_layer_height_profile(std::vector profile) %code%{ THIS->layer_height_profile = profile; THIS->layer_height_profile_valid = true; %}; - Ref origin_translation() + Ref origin_translation() %code%{ RETVAL = &THIS->origin_translation; %}; - void set_origin_translation(Pointf3* point) + void set_origin_translation(Vec3d* point) %code%{ THIS->origin_translation = *point; %}; bool needed_repair() const; @@ -299,7 +299,7 @@ ModelMaterial::attributes() int facets_count(); void center_around_origin(); void translate(double x, double y, double z); - void scale_xyz(Pointf3* versor) + void scale_xyz(Vec3d* versor) %code{% THIS->scale(*versor); %}; void rotate(float angle, Axis axis); void mirror(Axis axis); @@ -357,14 +357,14 @@ ModelMaterial::attributes() %code%{ RETVAL = THIS->rotation; %}; double scaling_factor() %code%{ RETVAL = THIS->scaling_factor; %}; - Ref offset() + Ref offset() %code%{ RETVAL = &THIS->offset; %}; void set_rotation(double val) %code%{ THIS->rotation = val; THIS->get_object()->invalidate_bounding_box(); %}; void set_scaling_factor(double val) %code%{ THIS->scaling_factor = val; THIS->get_object()->invalidate_bounding_box(); %}; - void set_offset(Pointf *offset) + void set_offset(Vec2d *offset) %code%{ THIS->offset = *offset; %}; void transform_mesh(TriangleMesh* mesh, bool dont_translate = false) const; diff --git a/xs/xsp/Point.xsp b/xs/xsp/Point.xsp index b7aded6a0..beefc6249 100644 --- a/xs/xsp/Point.xsp +++ b/xs/xsp/Point.xsp @@ -3,6 +3,7 @@ %{ #include #include "libslic3r/Point.hpp" +#include "libslic3r/Line.hpp" #include "libslic3r/Polygon.hpp" #include "libslic3r/Polyline.hpp" %} @@ -12,44 +13,44 @@ ~Point(); Clone clone() %code{% RETVAL=THIS; %}; - void scale(double factor); - void translate(double x, double y); + void scale(double factor) + %code{% *THIS *= factor; %}; + void translate(double x, double y) + %code{% *THIS += Point(x, y); %}; SV* arrayref() %code{% RETVAL = to_SV_pureperl(THIS); %}; SV* pp() %code{% RETVAL = to_SV_pureperl(THIS); %}; int x() - %code{% RETVAL = THIS->x; %}; + %code{% RETVAL = (*THIS)(0); %}; int y() - %code{% RETVAL = THIS->y; %}; + %code{% RETVAL = (*THIS)(1); %}; void set_x(int val) - %code{% THIS->x = val; %}; + %code{% (*THIS)(0) = val; %}; void set_y(int val) - %code{% THIS->y = val; %}; + %code{% (*THIS)(1) = val; %}; int nearest_point_index(Points points); Clone nearest_point(Points points) %code{% Point p; THIS->nearest_point(points, &p); RETVAL = p; %}; double distance_to(Point* point) - %code{% RETVAL = THIS->distance_to(*point); %}; + %code{% RETVAL = (*point - *THIS).cast().norm(); %}; double distance_to_line(Line* line) - %code{% RETVAL = THIS->distance_to(*line); %}; + %code{% RETVAL = line->distance_to(*THIS); %}; double perp_distance_to_line(Line* line) - %code{% RETVAL = THIS->perp_distance_to(*line); %}; + %code{% RETVAL = line->perp_distance_to(*THIS); %}; double ccw(Point* p1, Point* p2) %code{% RETVAL = THIS->ccw(*p1, *p2); %}; double ccw_angle(Point* p1, Point* p2) %code{% RETVAL = THIS->ccw_angle(*p1, *p2); %}; - Clone projection_onto_polygon(Polygon* polygon) + Point* projection_onto_polygon(Polygon* polygon) %code{% RETVAL = new Point(THIS->projection_onto(*polygon)); %}; - Clone projection_onto_polyline(Polyline* polyline) + Point* projection_onto_polyline(Polyline* polyline) %code{% RETVAL = new Point(THIS->projection_onto(*polyline)); %}; - Clone projection_onto_line(Line* line) + Point* projection_onto_line(Line* line) %code{% RETVAL = new Point(THIS->projection_onto(*line)); %}; - Clone negative() - %code{% RETVAL = new Point(THIS->negative()); %}; - bool coincides_with_epsilon(Point* point) - %code{% RETVAL = THIS->coincides_with_epsilon(*point); %}; - std::string serialize() %code{% char buf[2048]; sprintf(buf, "%ld,%ld", THIS->x, THIS->y); RETVAL = buf; %}; + Point* negative() + %code{% RETVAL = new Point(- *THIS); %}; + std::string serialize() %code{% char buf[2048]; sprintf(buf, "%ld,%ld", (*THIS)(0), (*THIS)(1)); RETVAL = buf; %}; %{ @@ -68,7 +69,7 @@ Point::coincides_with(point_sv) CODE: Point point; from_SV_check(point_sv, &point); - RETVAL = THIS->coincides_with(point); + RETVAL = (*THIS) == point; OUTPUT: RETVAL @@ -76,72 +77,62 @@ Point::coincides_with(point_sv) }; -%name{Slic3r::Point3} class Point3 { - Point3(int _x = 0, int _y = 0, int _z = 0); - ~Point3(); - Clone clone() - %code{% RETVAL = THIS; %}; - int x() - %code{% RETVAL = THIS->x; %}; - int y() - %code{% RETVAL = THIS->y; %}; - int z() - %code{% RETVAL = THIS->z; %}; - std::string serialize() %code{% char buf[2048]; sprintf(buf, "%ld,%ld,%ld", THIS->x, THIS->y, THIS->z); RETVAL = buf; %}; -}; - -%name{Slic3r::Pointf} class Pointf { - Pointf(double _x = 0, double _y = 0); - ~Pointf(); - Clone clone() +%name{Slic3r::Pointf} class Vec2d { + Vec2d(double _x = 0, double _y = 0); + ~Vec2d(); + Clone clone() %code{% RETVAL = THIS; %}; SV* arrayref() %code{% RETVAL = to_SV_pureperl(THIS); %}; SV* pp() %code{% RETVAL = to_SV_pureperl(THIS); %}; double x() - %code{% RETVAL = THIS->x; %}; + %code{% RETVAL = (*THIS)(0); %}; double y() - %code{% RETVAL = THIS->y; %}; + %code{% RETVAL = (*THIS)(1); %}; void set_x(double val) - %code{% THIS->x = val; %}; + %code{% (*THIS)(0) = val; %}; void set_y(double val) - %code{% THIS->y = val; %}; - void translate(double x, double y); - void scale(double factor); - void rotate(double angle, Pointf* center) - %code{% THIS->rotate(angle, *center); %}; - Clone negative() - %code{% RETVAL = THIS->negative(); %}; - Clone vector_to(Pointf* point) - %code{% RETVAL = THIS->vector_to(*point); %}; - std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf", THIS->x, THIS->y); RETVAL = buf; %}; + %code{% (*THIS)(1) = val; %}; + void translate(double x, double y) + %code{% *THIS += Vec2d(x, y); %}; + void scale(double factor) + %code{% *THIS *= factor; %}; + void rotate(double angle, Vec2d* center) + %code{% *THIS = Eigen::Translation2d(*center) * Eigen::Rotation2Dd(angle) * Eigen::Translation2d(- *center) * Eigen::Vector2d((*THIS)(0), (*THIS)(1)); %}; + Vec2d* negative() + %code{% RETVAL = new Vec2d(- *THIS); %}; + Vec2d* vector_to(Vec2d* point) + %code{% RETVAL = new Vec2d(*point - *THIS); %}; + std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf", (*THIS)(0), (*THIS)(1)); RETVAL = buf; %}; }; -%name{Slic3r::Pointf3} class Pointf3 { - Pointf3(double _x = 0, double _y = 0, double _z = 0); - ~Pointf3(); - Clone clone() +%name{Slic3r::Pointf3} class Vec3d { + Vec3d(double _x = 0, double _y = 0, double _z = 0); + ~Vec3d(); + Clone clone() %code{% RETVAL = THIS; %}; double x() - %code{% RETVAL = THIS->x; %}; + %code{% RETVAL = (*THIS)(0); %}; double y() - %code{% RETVAL = THIS->y; %}; + %code{% RETVAL = (*THIS)(1); %}; double z() - %code{% RETVAL = THIS->z; %}; + %code{% RETVAL = (*THIS)(2); %}; void set_x(double val) - %code{% THIS->x = val; %}; + %code{% (*THIS)(0) = val; %}; void set_y(double val) - %code{% THIS->y = val; %}; + %code{% (*THIS)(1) = val; %}; void set_z(double val) - %code{% THIS->z = val; %}; - void translate(double x, double y, double z); - void scale(double factor); - double distance_to(Pointf3* point) - %code{% RETVAL = THIS->distance_to(*point); %}; - Clone negative() - %code{% RETVAL = THIS->negative(); %}; - Clone vector_to(Pointf3* point) - %code{% RETVAL = THIS->vector_to(*point); %}; - std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf,%lf", THIS->x, THIS->y, THIS->z); RETVAL = buf; %}; + %code{% (*THIS)(2) = val; %}; + void translate(double x, double y, double z) + %code{% *THIS += Vec3d(x, y, z); %}; + void scale(double factor) + %code{% *THIS *= factor; %}; + double distance_to(Vec3d* point) + %code{% RETVAL = (*point - *THIS).norm(); %}; + Vec3d* negative() + %code{% RETVAL = new Vec3d(- *THIS); %}; + Vec3d* vector_to(Vec3d* point) + %code{% RETVAL = new Vec3d(*point - *THIS); %}; + std::string serialize() %code{% char buf[2048]; sprintf(buf, "%lf,%lf,%lf", (*THIS)(0), (*THIS)(1), (*THIS)(2)); RETVAL = buf; %}; }; diff --git a/xs/xsp/Polygon.xsp b/xs/xsp/Polygon.xsp index f5db9f515..a94425477 100644 --- a/xs/xsp/Polygon.xsp +++ b/xs/xsp/Polygon.xsp @@ -39,7 +39,6 @@ %code{% THIS->triangulate_convex(&RETVAL); %}; Clone centroid(); Clone bounding_box(); - std::string wkt(); Points concave_points(double angle); Points convex_points(double angle); Clone point_projection(Point* point) diff --git a/xs/xsp/Polyline.xsp b/xs/xsp/Polyline.xsp index 60d7c6aca..0dbd0e572 100644 --- a/xs/xsp/Polyline.xsp +++ b/xs/xsp/Polyline.xsp @@ -38,7 +38,6 @@ bool is_straight(); Clone bounding_box(); void remove_duplicate_points(); - std::string wkt(); %{ Polyline* diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index 717064916..ee9779f68 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -63,8 +63,6 @@ _constant() %code%{ RETVAL = THIS->layer_height_ranges; %}; std::vector layer_height_profile() %code%{ RETVAL = THIS->layer_height_profile; %}; - Ref size() - %code%{ RETVAL = &THIS->size; %}; Clone bounding_box(); Points _shifted_copies() @@ -72,7 +70,7 @@ _constant() void set_shifted_copies(Points value) %code%{ THIS->_shifted_copies = value; %}; - bool add_copy(Pointf* point) + bool add_copy(Vec2d* point) %code%{ RETVAL = THIS->add_copy(*point); %}; bool delete_last_copy(); bool delete_all_copies(); @@ -176,15 +174,6 @@ _constant() void set_step_started(PrintStep step) %code%{ THIS->state.set_started(step); %}; - void clear_filament_stats() - %code%{ - THIS->filament_stats.clear(); - %}; - void set_filament_stats(int extruder_id, float length) - %code%{ - THIS->filament_stats.insert(std::pair(extruder_id, 0)); - THIS->filament_stats[extruder_id] += length; - %}; SV* filament_stats() %code%{ HV* hv = newHV(); diff --git a/xs/xsp/TriangleMesh.xsp b/xs/xsp/TriangleMesh.xsp index d4578303b..2bc20da3a 100644 --- a/xs/xsp/TriangleMesh.xsp +++ b/xs/xsp/TriangleMesh.xsp @@ -16,7 +16,7 @@ void repair(); void WriteOBJFile(char* output_file); void scale(float factor); - void scale_xyz(Pointf3* versor) + void scale_xyz(Vec3d* versor) %code{% THIS->scale(*versor); %}; void translate(float x, float y, float z); void rotate_x(float angle); @@ -33,7 +33,7 @@ ExPolygons horizontal_projection(); Clone convex_hull(); Clone bounding_box(); - Clone center() + Clone center() %code{% RETVAL = THIS->bounding_box().center(); %}; int facets_count(); void reset_repair_stats(); @@ -60,14 +60,14 @@ TriangleMesh::ReadFromPerl(vertices, facets) for (int i = 0; i < stl.stats.number_of_facets; i++) { AV* facet_av = (AV*)SvRV(*av_fetch(facets_av, i, 0)); stl_facet facet; - facet.normal.x = 0; - facet.normal.y = 0; - facet.normal.z = 0; + facet.normal(0) = 0; + facet.normal(1) = 0; + facet.normal(2) = 0; for (unsigned int v = 0; v <= 2; v++) { AV* vertex_av = (AV*)SvRV(*av_fetch(vertices_av, SvIV(*av_fetch(facet_av, v, 0)), 0)); - facet.vertex[v].x = SvNV(*av_fetch(vertex_av, 0, 0)); - facet.vertex[v].y = SvNV(*av_fetch(vertex_av, 1, 0)); - facet.vertex[v].z = SvNV(*av_fetch(vertex_av, 2, 0)); + facet.vertex[v](0) = SvNV(*av_fetch(vertex_av, 0, 0)); + facet.vertex[v](1) = SvNV(*av_fetch(vertex_av, 1, 0)); + facet.vertex[v](2) = SvNV(*av_fetch(vertex_av, 2, 0)); } facet.extra[0] = 0; facet.extra[1] = 0; @@ -110,9 +110,9 @@ TriangleMesh::vertices() AV* vertex = newAV(); av_store(vertices, i, newRV_noinc((SV*)vertex)); av_extend(vertex, 2); - av_store(vertex, 0, newSVnv(THIS->stl.v_shared[i].x)); - av_store(vertex, 1, newSVnv(THIS->stl.v_shared[i].y)); - av_store(vertex, 2, newSVnv(THIS->stl.v_shared[i].z)); + av_store(vertex, 0, newSVnv(THIS->stl.v_shared[i](0))); + av_store(vertex, 1, newSVnv(THIS->stl.v_shared[i](1))); + av_store(vertex, 2, newSVnv(THIS->stl.v_shared[i](2))); } RETVAL = newRV_noinc((SV*)vertices); @@ -155,9 +155,9 @@ TriangleMesh::normals() AV* facet = newAV(); av_store(normals, i, newRV_noinc((SV*)facet)); av_extend(facet, 2); - av_store(facet, 0, newSVnv(THIS->stl.facet_start[i].normal.x)); - av_store(facet, 1, newSVnv(THIS->stl.facet_start[i].normal.y)); - av_store(facet, 2, newSVnv(THIS->stl.facet_start[i].normal.z)); + av_store(facet, 0, newSVnv(THIS->stl.facet_start[i].normal(0))); + av_store(facet, 1, newSVnv(THIS->stl.facet_start[i].normal(1))); + av_store(facet, 2, newSVnv(THIS->stl.facet_start[i].normal(2))); } RETVAL = newRV_noinc((SV*)normals); @@ -169,9 +169,9 @@ TriangleMesh::size() CODE: AV* size = newAV(); av_extend(size, 2); - av_store(size, 0, newSVnv(THIS->stl.stats.size.x)); - av_store(size, 1, newSVnv(THIS->stl.stats.size.y)); - av_store(size, 2, newSVnv(THIS->stl.stats.size.z)); + av_store(size, 0, newSVnv(THIS->stl.stats.size(0))); + av_store(size, 1, newSVnv(THIS->stl.stats.size(1))); + av_store(size, 2, newSVnv(THIS->stl.stats.size(2))); RETVAL = newRV_noinc((SV*)size); OUTPUT: RETVAL @@ -181,7 +181,7 @@ TriangleMesh::slice(z) std::vector z CODE: // convert doubles to floats - std::vector z_f(z.begin(), z.end()); + std::vector z_f = cast(z); std::vector layers; TriangleMeshSlicer mslicer(THIS); @@ -216,12 +216,12 @@ TriangleMesh::cut(z, upper, lower) std::vector TriangleMesh::bb3() CODE: - RETVAL.push_back(THIS->stl.stats.min.x); - RETVAL.push_back(THIS->stl.stats.min.y); - RETVAL.push_back(THIS->stl.stats.max.x); - RETVAL.push_back(THIS->stl.stats.max.y); - RETVAL.push_back(THIS->stl.stats.min.z); - RETVAL.push_back(THIS->stl.stats.max.z); + RETVAL.push_back(THIS->stl.stats.min(0)); + RETVAL.push_back(THIS->stl.stats.min(1)); + RETVAL.push_back(THIS->stl.stats.max(0)); + RETVAL.push_back(THIS->stl.stats.max(1)); + RETVAL.push_back(THIS->stl.stats.min(2)); + RETVAL.push_back(THIS->stl.stats.max(2)); OUTPUT: RETVAL diff --git a/xs/xsp/my.map b/xs/xsp/my.map index ba20ee236..d85734086 100644 --- a/xs/xsp/my.map +++ b/xs/xsp/my.map @@ -66,13 +66,13 @@ Point3* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T Clone O_OBJECT_SLIC3R_T -Pointf* O_OBJECT_SLIC3R -Ref O_OBJECT_SLIC3R_T -Clone O_OBJECT_SLIC3R_T +Vec2d* O_OBJECT_SLIC3R +Ref O_OBJECT_SLIC3R_T +Clone O_OBJECT_SLIC3R_T -Pointf3* O_OBJECT_SLIC3R -Ref O_OBJECT_SLIC3R_T -Clone O_OBJECT_SLIC3R_T +Vec3d* O_OBJECT_SLIC3R +Ref O_OBJECT_SLIC3R_T +Clone O_OBJECT_SLIC3R_T Line* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index cee75fe26..b3d73b9b3 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -22,12 +22,12 @@ %typemap{Point3*}; %typemap{Ref}{simple}; %typemap{Clone}{simple}; -%typemap{Pointf*}; -%typemap{Ref}{simple}; -%typemap{Clone}{simple}; -%typemap{Pointf3*}; -%typemap{Ref}{simple}; -%typemap{Clone}{simple}; +%typemap{Vec2d*}; +%typemap{Ref}{simple}; +%typemap{Clone}{simple}; +%typemap{Vec3d*}; +%typemap{Ref}{simple}; +%typemap{Clone}{simple}; %typemap{BoundingBox*}; %typemap{Ref}{simple}; %typemap{Clone}{simple};