Commit e5b45ec4 authored by JasonPries's avatar JasonPries
Browse files

Updated implementation of RotateCopy

A bug in Mesh::locate_triangle emerged during the insert_internal_contours stage of initial mesh refinement for Stator0 use case. This is related to the locate_triangle method supplying incorrect return values for either nonconvex domains, boundary points, or both, when starting the search from particular edges. The implementation of locate_triangle needs to be reconsidered. Perhaps a bounding box needs to be stored along with the mesh of the actual domain.
parent 82363551
......@@ -34,6 +34,7 @@ LocateTriangleResult Mesh::locate_triangle(const Point *p, Edge *&e) const {
}
LocateTriangleResult Mesh::locate_triangle(const Point *p, const Edge *&e) const {
// TODO: Need to search along boundary triangles in order to ensure the internal/external status
const Edge *start = e;
double xp = p->X;
double yp = p->Y;
......@@ -79,7 +80,7 @@ LocateTriangleResult Mesh::locate_triangle(const Point *p, const Edge *&e) const
} else if (e->next() != start) {
e = e->next();
} else {
throw (std::exception()); //TODO: This branch should never be reached. Supply return value"
throw std::exception(); //TODO: This branch should never be reached. Supply return value"
}
} else if (e->next() != start) {
e = e->next();
......@@ -548,44 +549,39 @@ void Mesh::create_boundary_polygon() {
void Mesh::triangulate_boundary_polygon() {
Edges.reserve(3 * num_points());
// Create initial polygon
size_t Ne = 0;
for (size_t i = 0; i < Contours.size(); ++i) {
Edge * ep = Edges[Ne];
while (ep != ep->Next->Next->Next) {
if (ep->is_protruding()) {
Edge * e0 = new Edge;
Edge * e1 = new Edge;
// Edge of new triangle
e0->Node = ep->Next->Node;
e0->Prev = ep;
e0->Next = ep->Prev;
e0->Twin = e1;
// Twin edge, part of new polygonal boundary
e1->Node = ep->Prev->Node;
e1->Next = ep->Next;
e1->Prev = ep->Prev->Prev;
e1->Twin = e0;
// Store new edges
Edges.push_back(e0);
Edges.push_back(e1);
// Update polygonal boundary
ep->Next->Prev = e1;
ep->Next = e0;
ep->Prev->Prev->Next = e1;
ep->Prev->Prev = e0;
// Next edge
ep = e1->Next;
} else {
ep = ep->Next;
}
Edge * ep = Edges[0];
while (ep != ep->Next->Next->Next) {
if (ep->is_protruding()) {
Edge * e0 = new Edge;
Edge * e1 = new Edge;
// Edge of new triangle
e0->Node = ep->Next->Node;
e0->Prev = ep;
e0->Next = ep->Prev;
e0->Twin = e1;
// Twin edge, part of new polygonal boundary
e1->Node = ep->Prev->Node;
e1->Next = ep->Next;
e1->Prev = ep->Prev->Prev;
e1->Twin = e0;
// Store new edges
Edges.push_back(e0);
Edges.push_back(e1);
// Update polygonal boundary
ep->Next->Prev = e1;
ep->Next = e0;
ep->Prev->Prev->Next = e1;
ep->Prev->Prev = e0;
// Next edge
ep = e1->Next;
} else {
ep = ep->Next;
}
Ne += Contours[i]->size();
}
// Edge swap to make triangulation Delaunay
......@@ -665,7 +661,14 @@ void Mesh::insert_internal_boundaries() {
LocateTriangleResult result = locate_triangle(&p0, e);
if (result != LocateTriangleResult::Point) {
throw (std::exception()); //TODO: Could not locate point within triangulation while inserting internal constraints
//TODO: Could not locate point within triangulation while inserting internal constraints
//TODO: Need to fix locate_triangle method so that search continues along boundary until the edge extrusion strip contains the point (verifying the internal/external status)
LocateTriangleResult result = locate_triangle(&p1, e);
if (result == LocateTriangleResult::Point) {
std::swap(p0, p1);
} else {
throw std::exception();
}
}
if (e->is_attached(&p1, e)) {
......
......@@ -16,109 +16,151 @@ RotateCopy::RotateCopy(std::vector<const Curve *> &input, Vertex *center, double
Verticies.reserve(3 * copies * input.size());
Constraints.reserve(3 * copies * input.size());
// Reserve Local Vectors
std::vector<Curve *> local_curves;
local_curves.reserve(Input.size());
std::vector<const Curve *> leading_curves;
std::vector<const Curve *> lagging_curves;
std::vector<bool> is_lead_or_lag(input.size(),false);
// Find leading/lagging curve pairs
for (size_t i = 0; i != input.size(); ++i) {
for (size_t j = 0; j != input.size(); ++j) {
if (!(i == j || is_lead_or_lag[i] || is_lead_or_lag[j])) { //
if (input[i]->is_identical(input[j], center, angle)) {
leading_curves.push_back(input[i]);
is_lead_or_lag[i] = true;
lagging_curves.push_back(input[j]);
is_lead_or_lag[j] = true;
break;
}
}
}
}
std::vector<Vertex *> local_verticies;
local_verticies.reserve(Input.size() * 2);
// If not leading/lagging, curve is internal
std::vector<const Curve *> internal_curves;
for (size_t i =0; i != input.size(); ++i) {
if(!is_lead_or_lag[i]) {
internal_curves.push_back(input[i]);
}
}
std::list<Vertex *> input_vlist;
// TODO: Check for complete elimination of leading/lagging curves
for (size_t i = 0; i != Copies; ++i) {
local_curves.clear();
local_verticies.clear();
input_vlist.clear();
// Get leading/lagging verticies
std::vector<Vertex *> leading_verticies;
{
std::list<Vertex *> local_verts;
for (auto i : leading_curves) {
i->get_verticies(local_verts);
}
local_verts.sort(); // remove duplicates
local_verts.unique();
local_verts.remove(center);
// Clone input curves and create a list of unique input verticies
for (auto c : Input) {
local_curves.push_back(c->clone());
Curves.push_back(local_curves.back());
c->get_verticies(input_vlist);
leading_verticies.assign(local_verts.begin(),local_verts.end()); // assign to vector
}
std::vector<Vertex *> lagging_verticies;
{
std::list<Vertex *> local_verts;
for (auto i : lagging_curves) {
i->get_verticies(local_verts);
}
input_vlist.sort();
input_vlist.unique();
local_verts.sort(); // remove duplicates
local_verts.unique();
local_verts.remove(center);
// Rewrite
/*
// Get local curves
for (auto c : Input) {
local_curves.push_back(c->clone());
lagging_verticies.assign(local_verts.begin(),local_verts.end()); // assign to vector
}
// Get internal verticies
std::vector<Vertex *> internal_verticies;
{
std::list<Vertex *> local_verts;
for (auto c : internal_curves) {
c->get_verticies(local_verts);
}
local_verts.sort(); // remove duplicates
local_verts.unique();
local_verts.remove(center);
// Erase corotational curves
for (size_t j = 0;j != local_curves.size();++j) {
auto k = local_curves.begin();
while (k != local_curves.end()) {
if (local_curves[j].is_corotational(*k, center, angle)) {
k = local_curves.erase(k);
}
else {
++k;
}
}
// Trim leading verticies
for(auto v : leading_verticies) {
local_verts.remove(v);
}
// Get local verticies
for (auto c : local_curves) {
c->get_verticies(input_vlist);
// Trim lagging verticies
for(auto v : lagging_verticies) {
local_verts.remove(v);
}
// Erase corotational verticies
for (size_t j = 0;j != input_vlist.size();++j) {
auto k = input_vlist.end();
while (k != input_vlist.end()) {
if (input_vlist[j].is_corotational(*k, center, angle)) {
k = input_vlist.erase(k);
}
else {
++k;
}
}
// Copy to vector
internal_verticies.assign(local_verts.begin(),local_verts.end());
}
// Make rotated copies
std::vector<Vertex *> rotated_lagging(leading_verticies.begin(), leading_verticies.end());
for (size_t i = 0; i != Copies; ++i) {
// Create curve clones
std::vector<Curve *> local_curves;
for (auto c : internal_curves) {
local_curves.push_back(c->clone());
Curves.push_back(local_curves.back());
}
*/
// Erase center if it exists
auto j = std::find(input_vlist.begin(), input_vlist.end(), center);
if (j != input_vlist.end()) {
input_vlist.erase(j);
for (auto c : leading_curves) {
local_curves.push_back(c->clone());
Curves.push_back(local_curves.back());
}
// Rotate input verticies
double a = (i + 1.0) * Angle * M_PI / 180.0;
// Create new verticies and constrain them
double a = (i + 1) * Angle * M_PI / 180.0;
double cosa = cos(a);
double sina = sin(a);
double x0 = Center->x();
double y0 = Center->y();
auto v = input_vlist.begin();
while (v != input_vlist.end()) {
double dx = (*v)->x() - x0;
double dy = (*v)->y() - y0;
std::vector<Vertex *> rotated_leading;
for(auto v : leading_verticies) {
double dx = v->x() - x0;
double dy = v->y() - y0;
double vx = cosa * dx - sina * dy + x0;
double vy = sina * dx + cosa * dy + y0;
local_verticies.push_back(new Vertex(vx, vy));
rotated_leading.push_back(new Vertex(vx, vy));
Verticies.push_back(local_verticies.back());
Verticies.push_back(rotated_leading.back());
v++;
Constraints.push_back(new Rotation(*v, *rotated_leading.back(), *Center, Angle * (i + 1)));
}
// Replace verticies in rotated curves
std::vector<Vertex *> input_vvector{input_vlist.begin(), input_vlist.end()};
for (auto c : local_curves) {
c->replace_verticies(input_vvector, local_verticies);
std::vector<Vertex *> rotated_internal;
for(auto v : internal_verticies) {
double dx = v->x() - x0;
double dy = v->y() - y0;
double vx = cosa * dx - sina * dy + x0;
double vy = sina * dx + cosa * dy + y0;
rotated_internal.push_back(new Vertex(vx, vy));
Verticies.push_back(rotated_internal.back());
Constraints.push_back(new Rotation(*v, *rotated_internal.back(), *Center, Angle * (i + 1)));
}
// Constrain rotated verticies to be rotated about the origin
for (size_t j = 0; j != local_verticies.size(); ++j) {
Constraints.push_back(new Rotation(*input_vvector[j], *local_verticies[j], *Center, Angle * (i + 1)));
// Replace verticies in clones curves
for (auto c : local_curves) {
c->replace_verticies(leading_verticies, rotated_leading);
c->replace_verticies(internal_verticies, rotated_internal);
c->replace_verticies(lagging_verticies, rotated_lagging);
}
// Leading verticies becomes lagging verticies
rotated_lagging.assign(rotated_leading.begin(), rotated_leading.end());
}
// Shrink
Curves.shrink_to_fit();
Verticies.shrink_to_fit();
Constraints.shrink_to_fit();
......
......@@ -9,7 +9,7 @@ public:
private:
Vertex *Center;
double Angle;
double Angle; // TODO: Write 'update_angle' method which updates all associated rotation constraints
size_t Copies;
};
......
......@@ -136,6 +136,8 @@ public:
const Curve *curve(size_t i) const { return Curves[i]; };
std::vector<const Curve *> const curves() {return std::vector<const Curve *>(Curves.begin(),Curves.end());};
const Constraint *constraint(size_t i) const { return Constraints[i]; };
const Contour *contour(size_t i) const { return Contours[i]; };
......
......@@ -340,9 +340,6 @@ TEST(Rotate, nonoverlapping) {
test_rotated_verticies(s, {1, 2, 3, 4}, &v0, 360.0 / (N - 1), N - 2);
test_rotated_curves(s, {0, 1, 2, 3}, &v0, 360.0 / (N - 1), N - 2);
}
FAIL(); // TODO: Rewrite rotate copy based on notes in current implementation
}
TEST(Rotate, overlapping) {
......@@ -375,25 +372,38 @@ TEST(Rotate, overlapping) {
std::vector<const Curve *> vec({&l0, &l1, &c0, &c1});
RotateCopy &r0 = s.new_element<RotateCopy>(vec, &v0, 360.0 / N, N - 2);
s.save_as<SaveMethod::Rasterize>(SAVE_DIR, "Rotate__overlapping_0");
s.solve();
s.build();
s.save_as<SaveMethod::Rasterize>(SAVE_DIR, "Rotate__overlapping_0");
// Run Tests
{
test_sketch_size(s, 9, 8, 13, 1);
test_sketch_size(s, 9, 10, 10, 3);
test_rotated_verticies(s, {1, 2, 3, 4}, &v0, 360.0 / N, N - 2);
test_rotated_curves(s, {0, 1, 2, 3}, &v0, 360.0 / N, N - 2);
}
// Change Sketch
rad0.Dim = 0.5;
rad1.Dim = 2.5;
s.solve();
s.build();
s.save_as<SaveMethod::Rasterize>(SAVE_DIR, "Rotate__overlapping_1");
// Run Tests
{
test_sketch_size(s, 9, 10, 10, 3);
test_rotated_verticies(s, {1, 2, 3, 4}, &v0, 360.0 / N, N - 2);
test_rotated_curves(s, {0, 1, 2, 3}, &v0, 360.0 / N, N - 2);
}
FAIL(); // TODO: Change sketch, run tests
FAIL(); // TODO: Change angle of horizontal line w.r.t. x-axis and rerun
}
TEST(Rotate, open_ovlerapping) {
TEST(Rotate, open_overlapping) {
FAIL(); // TODO
}
......
......@@ -31,16 +31,18 @@ TEST(Stator, 0) {
LineSegment &l3 = sketch.new_element<LineSegment>(v5, v6);
CircularArc &c3 = sketch.new_element<CircularArc>(v6, v3, origin, rb);
//std::vector<const Curve*> mv{ &l0,&l1,&l2,&l3,&c0,&c1,&c2,&c3 };
std::vector<const Curve*> mv{&l0, &l3, &c0, &c1, &c2, &c3};
MirrorCopy &m0 = sketch.new_element<MirrorCopy>(mv, &l1);
auto mvec = sketch.curves();
MirrorCopy &m0 = sketch.new_element<MirrorCopy>(mvec, &l1);
auto rvec = sketch.curves();
RotateCopy &rcopy = sketch.new_element<RotateCopy>(rvec, &origin, 360.0 / Nt, 1);
sketch.solve();
sketch.save_as<SaveMethod::Rasterize>(SDIR, "stator0_0");
EXPECT_TRUE(sketch.build());
EXPECT_EQ(sketch.boundary()->size(), 8);
EXPECT_EQ(sketch.boundary()->size(), 14);
Fixation &f = sketch.new_element<Fixation>(origin);
......@@ -65,7 +67,7 @@ TEST(Stator, 0) {
sketch.save_as<SaveMethod::Rasterize>(SDIR, "stator0_1");
EXPECT_TRUE(sketch.build());
EXPECT_EQ(sketch.boundary()->size(), 8);
EXPECT_EQ(sketch.boundary()->size(), 14);
Mesh mesh{sketch};
......@@ -80,4 +82,6 @@ TEST(Stator, 0) {
mesh.refine();
mesh.save_as(MDIR, "stator0_refined");
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment