Skip to content

Commit 80c76ee

Browse files
update logic
1 parent efdb609 commit 80c76ee

File tree

2 files changed

+54
-103
lines changed

2 files changed

+54
-103
lines changed

source/world_builder/features/subducting_plate.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ namespace WorldBuilder
183183
value *= (Consts::PI/180.);
184184
}
185185

186-
186+
187187
default_temperature_models.resize(0);
188188
default_composition_models.resize(0);
189189
default_grains_models.resize(0);

source/world_builder/utilities.cc

Lines changed: 53 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -443,13 +443,59 @@ namespace WorldBuilder
443443
// Normalize the vector
444444
obliquity_vector_point = obliquity_vector_point / obliquity_vector_point.norm();
445445

446+
// If the check point is near the ends of the Bezier curve, there is a chance that the Bezier curve will not
447+
// find a closest point. Check for this case by seeing if the line created by the checkpoint and the obliquity
448+
// vector intersects the end segments of the Bezier curve.
449+
Point<2> iterable_check_point_surface_2d = check_point_surface_2d;
450+
Objects::ClosestPointOnCurve iterable_closest_point_on_curve = bezier_curve.closest_point_on_curve_segment(iterable_check_point_surface_2d);
451+
452+
if (std::isnan(closest_point_on_line_2d[0]))
453+
{
454+
const Point<2> p1 = point_list[0];
455+
const Point<2> p2 = point_list[point_list.size()-1];
456+
const double dist_p1 = check_point_surface_2d.distance(p1);
457+
const double dist_p2 = check_point_surface_2d.distance(p2);
458+
const Point<2> closest_terminal_point = dist_p1 < dist_p2 ? p1 : p2;
459+
double closest_distance_to_trench = dist_p1 < dist_p2 ? dist_p1 : dist_p2;
460+
461+
const Point<2> second_closest_terminal_point = dist_p1 < dist_p2 ? point_list[1] : point_list[point_list.size()-2];
462+
for (unsigned int i = 0; i < 100; ++i)
463+
{
464+
const Point<2> vector_closest_point_to_checkpoint = closest_terminal_point - iterable_check_point_surface_2d;
465+
const double line_factor = obliquity_vector_point * vector_closest_point_to_checkpoint < 0 ? -1.0 : 1.0;
466+
467+
// Parameterize a line through the checkpoint along the obliquity vector.
468+
Point<2> parameterized_line(iterable_check_point_surface_2d[0] + line_factor * closest_distance_to_trench * obliquity_vector_point[0],
469+
iterable_check_point_surface_2d[1] + line_factor * closest_distance_to_trench * obliquity_vector_point[1],
470+
natural_coordinate_system);
471+
const double new_distance1 = parameterized_line.distance(closest_terminal_point);
472+
const double new_distance2 = parameterized_line.distance(second_closest_terminal_point);
473+
const double new_distance_search = std::min(new_distance1, new_distance2);
474+
475+
if (new_distance_search < closest_distance_to_trench)
476+
{
477+
// We are getting closer to the trench, so continue the search.
478+
iterable_check_point_surface_2d = parameterized_line;
479+
closest_distance_to_trench = new_distance_search;
480+
481+
if (!std::isnan(bezier_curve.closest_point_on_curve_segment(iterable_check_point_surface_2d).point[0]))
482+
{
483+
closest_point_on_curve = bezier_curve.closest_point_on_curve_segment(iterable_check_point_surface_2d);
484+
closest_point_on_line_2d = bezier_curve.closest_point_on_curve_segment(iterable_check_point_surface_2d).point;
485+
iterable_closest_point_on_curve = closest_point_on_curve;
486+
break;
487+
}
488+
489+
}
490+
}
491+
}
446492
// Check if the bezier_curve has found a point on the curve that is closest to the checkpoint (without considering the obliquity vector).
447493
// If so, we need to check whether this point is on the correct side of the curve, given the reference point.
448494
// If the bezier_curve has not found a point on the curve that is closest to the checkpoint, check to see if the point will still
449495
// intersect the trench given the obliquity_vector.
450496
if (!std::isnan(closest_point_on_line_2d[0]))
451497
{
452-
Point<2> check_point_surface_2d_temp_ob = check_point_surface_2d;
498+
Point<2> check_point_surface_2d_temp_ob = iterable_check_point_surface_2d;
453499

454500
if (!bool_cartesian)
455501
{
@@ -473,11 +519,8 @@ namespace WorldBuilder
473519
const bool reference_normal_on_side_of_line_ob = (closest_point_on_line_2d-local_reference_point_ob).norm_square() < (check_point_surface_2d_temp_ob-local_reference_point_ob).norm_square();
474520
const bool reference_point_on_side_of_line_ob = (point_list[point_list.size()-1][0] - point_list[0][0])*(reference_point[1] - point_list[0][1]) - (reference_point[0] - point_list[0][0])*(point_list[point_list.size()-1][1] - point_list[0][1]) < 0.;
475521

476-
double line_factor;
477522
double old_dist;
478523
double new_dist;
479-
Point<2> iterable_check_point_surface_2d = check_point_surface_2d;
480-
Objects::ClosestPointOnCurve iterable_closest_point_on_curve = bezier_curve.closest_point_on_curve_segment(iterable_check_point_surface_2d);
481524
bool converged = false;
482525

483526
if (reference_normal_on_side_of_line_ob != reference_point_on_side_of_line_ob)
@@ -490,10 +533,11 @@ namespace WorldBuilder
490533
// traveled along the parameterized line.
491534
old_dist = iterable_closest_point_on_curve.distance / 1.1;
492535

493-
// If the sign of the dot product of the obliquity vector and the normal vector of the closest point on
494-
// the curve is positive, then we want to move along the obliquity vector in the negative direction,
536+
// If the sign of the dot product of the obliquity vector and the vector connecting the closest point on
537+
// the curve to the check point is positive, then we want to move along the obliquity vector in the negative direction,
495538
// otherwise in the positive direction.
496-
line_factor = obliquity_vector_point * iterable_closest_point_on_curve.normal > 0 ? -1.0 : 1.0;
539+
const Point<2> vector_closest_point_to_checkpoint = iterable_check_point_surface_2d - iterable_closest_point_on_curve.point;
540+
const double line_factor = obliquity_vector_point * vector_closest_point_to_checkpoint < 0 ? -1.0 : 1.0;
497541

498542
// Parameterize a line through the checkpoint along the obliquity vector.
499543
Point<2> parameterized_line(iterable_check_point_surface_2d[0] + line_factor * old_dist * obliquity_vector_point[0],
@@ -514,8 +558,8 @@ namespace WorldBuilder
514558
// bezier curve, you will never get closer to it. But I'm not sure this is fully general.
515559
if (std::abs(old_dist - new_dist) >= std::abs(old_dist))
516560
{
517-
closest_point_on_line_2d[0] = std::numeric_limits<double>::quiet_NaN();
518-
closest_point_on_line_2d[1] = std::numeric_limits<double>::quiet_NaN();
561+
closest_point_on_line_2d[0] = NaN::DQNAN;
562+
closest_point_on_line_2d[1] = NaN::DQNAN;
519563
break;
520564
}
521565

@@ -535,99 +579,6 @@ namespace WorldBuilder
535579
closest_point_on_line_2d = closest_point_on_curve.point;
536580
}
537581
}
538-
539-
else
540-
{
541-
// The point is outside of the bezier curves range, but in this case this does NOT mean
542-
// that the point should be neglected since the slab can be oblique to the trench.
543-
// Determine the min/max x and y coordinates of the trench, and then use the obliquity
544-
// vector to see if the check point will intersect the trench at all.
545-
double closest_distance_to_trench = std::numeric_limits<double>::infinity();
546-
unsigned int closest_point_idx;
547-
for (unsigned int point_idx = 0; point_idx < point_list.size(); ++point_idx)
548-
{
549-
const double current_distance = check_point_surface_2d.distance(point_list[point_idx]);
550-
if (current_distance < closest_distance_to_trench)
551-
{
552-
closest_distance_to_trench = current_distance;
553-
closest_point_idx = point_idx;
554-
}
555-
}
556-
const Point<2> closest_point = point_list[closest_point_idx];
557-
558-
559-
unsigned int second_closest_point_idx;
560-
if (closest_point_idx == 0)
561-
second_closest_point_idx = 1;
562-
else if (closest_point_idx == point_list.size() - 1)
563-
second_closest_point_idx = point_list.size() - 2;
564-
else
565-
{
566-
const double dist_prev = check_point_surface_2d.distance(point_list[closest_point_idx - 1]);
567-
const double dist_next = check_point_surface_2d.distance(point_list[closest_point_idx + 1]);
568-
second_closest_point_idx = dist_prev < dist_next ? closest_point_idx - 1 : closest_point_idx + 1;
569-
}
570-
571-
const Point<2> second_closest_point = point_list[second_closest_point_idx];
572-
// std::vector<Point<2> > closest_points;
573-
// closest_points.push_back(closest_point);
574-
// closest_points.push_back(second_closest_point);
575-
576-
// WorldBuilder::Objects::BezierCurve testier_curve = Objects::BezierCurve(closest_points);
577-
578-
579-
580-
581-
582-
583-
auto compare_x_coordinate = [](auto p1, auto p2)
584-
{
585-
return p1[0]<p2[0];
586-
};
587-
const double max_along_x = (*std::max_element(point_list.begin(), point_list.end(), compare_x_coordinate))[0];
588-
const double min_along_x = (*std::min_element(point_list.begin(), point_list.end(), compare_x_coordinate))[0];
589-
590-
auto compare_y_coordinate = [](auto p1, auto p2)
591-
{
592-
return p1[1]<p2[1];
593-
};
594-
595-
const double min_along_y = (*std::min_element(point_list.begin(), point_list.end(), compare_y_coordinate)) [1];
596-
const double max_along_y = (*std::max_element(point_list.begin(), point_list.end(), compare_y_coordinate)) [1];
597-
598-
// First parameterize the trench points:
599-
const Point<2> trench_point2(min_along_x, max_along_y, natural_coordinate_system);
600-
const Point<2> trench_point1(max_along_x, min_along_y, natural_coordinate_system);
601-
602-
// The unit vector that connects the two extremes of the trench points
603-
const Point<2> trench_uv = (trench_point2 - trench_point1) / (trench_point2 - trench_point1).norm();
604-
605-
// If both lines are parameterized with l_i = x_i + t_i * v_i, then since we know the points x_i and the
606-
// vectors v_i, we can solve for t_1 and t_2 when l_1 = l_2. This works out to be:
607-
const double numerator = trench_uv[0] * (trench_point1[1] - check_point_surface_2d[1]) + trench_uv[1] * (check_point_surface_2d[0] - trench_point1[0]);
608-
const double denominator = obliquity_vector_point[1] * trench_uv[0] - obliquity_vector_point[0] * trench_uv[1];
609-
const double t_val = numerator / denominator;
610-
611-
// If the two lines are parallel, t_val will be infinite. Check to see that this is not the case.
612-
if (std::isfinite(t_val))
613-
{
614-
// t_val is finite, now determine where the intersection point is, and see if this lies within the trench extents.
615-
const Point<2> intersection_point(check_point_surface_2d[0] + t_val * obliquity_vector_point[0],
616-
check_point_surface_2d[1] + t_val * obliquity_vector_point[1],
617-
natural_coordinate_system);
618-
619-
if (intersection_point[0] >= min_along_x && intersection_point[0] <= max_along_x
620-
&&
621-
intersection_point[1] >= min_along_y && intersection_point[1] <= max_along_y)
622-
{
623-
// The intersection point is within the trench extents, so we need to find the closest point on the curve
624-
// from this intersection point.
625-
closest_point_on_curve = bezier_curve.closest_point_on_curve_segment(intersection_point);
626-
closest_point_on_line_2d = closest_point_on_curve.point;
627-
}
628-
}
629-
630-
}
631582
}
632583

633584
// We now need 3d points from this point on, so make them.

0 commit comments

Comments
 (0)