Skip to content

Commit d9253db

Browse files
initial obliquity
1 parent 53bbef6 commit d9253db

File tree

2 files changed

+165
-1
lines changed

2 files changed

+165
-1
lines changed

include/world_builder/utilities.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ namespace WorldBuilder
410410
const std::unique_ptr<CoordinateSystems::Interface> &coordinate_system,
411411
const bool only_positive,
412412
const Objects::BezierCurve &bezier_curve);
413+
// const Point<2> &obliquity_vector);
413414

414415

415416

source/world_builder/utilities.cc

Lines changed: 164 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ namespace WorldBuilder
387387
const std::unique_ptr<CoordinateSystems::Interface> &coordinate_system,
388388
const bool only_positive,
389389
const Objects::BezierCurve &bezier_curve)
390+
// const Point<2> &obliquity_vector)
390391
{
391392
// Initialize variables that this function will return
392393
double distance = std::numeric_limits<double>::infinity();
@@ -406,6 +407,12 @@ namespace WorldBuilder
406407
const Point<2> check_point_surface_2d(natural_coordinate.get_surface_coordinates(),
407408
natural_coordinate_system);
408409

410+
411+
412+
413+
414+
415+
409416
// The section which is checked.
410417
size_t section = 0;
411418

@@ -427,9 +434,165 @@ namespace WorldBuilder
427434
double fraction_CPL_P1P2 = std::numeric_limits<double>::infinity();
428435

429436
// Get the closest point on the curve (the trench or the fault trace) to the check point.
430-
const Objects::ClosestPointOnCurve closest_point_on_curve = bezier_curve.closest_point_on_curve_segment(check_point_surface_2d);
437+
Objects::ClosestPointOnCurve closest_point_on_curve = bezier_curve.closest_point_on_curve_segment(check_point_surface_2d);
431438
Point<2> closest_point_on_line_2d = closest_point_on_curve.point;
432439

440+
// Hard-coded obliquity vector for testing purposes, this will be replaced later by an input parameter.
441+
const Point<2> obliquity_vector(1.0, 0.0, natural_coordinate_system);
442+
443+
// If the obliquity_vector is not a NAN, this means that the user has specified an obliquity vector.
444+
// This will require a potential modification of the `closest_point_on_line_2d` variable.
445+
if (!std::isnan(obliquity_vector[0]))
446+
{
447+
// Check if the bezier_curve has found a point on the curve that is closest to the checkpoint (without considering the obliquity vector).
448+
// If so, we need to check whether this point is on the correct side of the curve, given the reference point.
449+
// 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
450+
// intersect the trench given the obliquity_vector.
451+
if (!std::isnan(closest_point_on_line_2d[0]))
452+
{
453+
Point<2> check_point_surface_2d_temp_ob = check_point_surface_2d;
454+
455+
if (!bool_cartesian)
456+
{
457+
const double normal = std::fabs(point_list[i_section_min_distance+static_cast<size_t>(std::round(fraction_CPL_P1P2))][0]-check_point_surface_2d[0]);
458+
const double plus = std::fabs(point_list[i_section_min_distance+static_cast<size_t>(std::round(fraction_CPL_P1P2))][0]-(check_point_surface_2d[0]+2*Consts::PI));
459+
const double min = std::fabs(point_list[i_section_min_distance+static_cast<size_t>(std::round(fraction_CPL_P1P2))][0]-(check_point_surface_2d[0]-2*Consts::PI));
460+
461+
// find out whether the check point, checkpoint + 2pi or check point -2 pi is closest to the point list.
462+
if (plus < normal)
463+
{
464+
check_point_surface_2d_temp_ob[0]+= 2*Consts::PI;
465+
}
466+
else if (min < normal)
467+
{
468+
check_point_surface_2d_temp_ob[0]-= 2*Consts::PI;
469+
}
470+
}
471+
472+
const Point<2> AB_normal_ob = closest_point_on_curve.normal*closest_point_on_line_2d.distance(reference_point);//*AB.norm();
473+
const Point<2> local_reference_point_ob = AB_normal_ob*1.+closest_point_on_line_2d;
474+
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();
475+
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.;
476+
477+
double line_factor;
478+
double old_dist;
479+
double new_dist;
480+
Point<2> iterable_check_point_surface_2d = check_point_surface_2d;
481+
Objects::ClosestPointOnCurve iterable_closest_point_on_curve = bezier_curve.closest_point_on_curve_segment(iterable_check_point_surface_2d);
482+
bool converged = false;
483+
484+
if (reference_normal_on_side_of_line_ob != reference_point_on_side_of_line_ob)
485+
{
486+
// We want to take the current checkpoint and move it along the obliquity vector using a parameterized line
487+
// towards the bezier curve until we find a point on the bezier curve that intersects this parameterized line.
488+
for (unsigned int i = 0; i < 100; ++i)
489+
{
490+
// We will use the distance of the check point to the current "closest point on curve" to scale the distance
491+
// traveled along the parameterized line.
492+
old_dist = iterable_closest_point_on_curve.distance / 1.1;
493+
494+
// If the sign of the dot product of the obliquity vector and the normal vector of the closest point on
495+
// the curve is positive, then we want to move along the obliquity vector in the negative direction,
496+
// otherwise in the positive direction.
497+
line_factor = obliquity_vector * iterable_closest_point_on_curve.normal > 0 ? -1.0 : 1.0;
498+
499+
// Parameterize a line through the checkpoint along the obliquity vector.
500+
Point<2> parameterized_line(iterable_check_point_surface_2d[0] + line_factor * old_dist * obliquity_vector[0],
501+
iterable_check_point_surface_2d[1] + line_factor * old_dist * obliquity_vector[1],
502+
natural_coordinate_system);
503+
504+
// Check where the closest point on the bezier curve is to the new check point (after moving along the
505+
// obliquity vector).
506+
iterable_closest_point_on_curve = bezier_curve.closest_point_on_curve_segment(parameterized_line);
507+
iterable_check_point_surface_2d = parameterized_line;
508+
509+
// The new distance from the bezier curve. Use this to check to see if we are converging/have converged.
510+
new_dist = iterable_closest_point_on_curve.distance;
511+
512+
// If the distance is increasing, this means that we are moving away from the trench, so abort the search
513+
// and return NAN's for the closest point to ensure this point doesn't get used.
514+
// NOTE: I think this makes sense most of the time, for example if the obliquity vector is parallel to the
515+
// bezier curve, you will never get closer to it. But I'm not sure this is fully general.
516+
if (std::abs(old_dist - new_dist) >= std::abs(old_dist))
517+
{
518+
closest_point_on_line_2d[0] = std::numeric_limits<double>::quiet_NaN();
519+
closest_point_on_line_2d[1] = std::numeric_limits<double>::quiet_NaN();
520+
break;
521+
}
522+
523+
// The new distance and the old distance are very close, implying the point has converged.
524+
if (std::abs(new_dist - old_dist) < 1)
525+
{
526+
converged = true;
527+
break;
528+
}
529+
}
530+
}
531+
532+
// If converged, update the closest point to the intersection of the obliquity vector with the bezier curve.
533+
if (converged)
534+
{
535+
closest_point_on_curve = bezier_curve.closest_point_on_curve_segment(iterable_check_point_surface_2d);
536+
closest_point_on_line_2d = closest_point_on_curve.point;
537+
}
538+
}
539+
540+
else
541+
{
542+
// The point is outside of the bezier curves range, but in this case this does NOT mean
543+
// that the point should be neglected since the slab can be oblique to the trench.
544+
// Determine the min/max x and y coordinates of the trench, and then use the obliquity
545+
// vector to see if the check point will intersect the trench at all.
546+
auto compare_x_coordinate = [](auto p1, auto p2)
547+
{
548+
return p1[0]<p2[0];
549+
};
550+
const double max_along_x = (*std::max_element(point_list.begin(), point_list.end(), compare_x_coordinate))[0];
551+
const double min_along_x = (*std::min_element(point_list.begin(), point_list.end(), compare_x_coordinate))[0];
552+
553+
auto compare_y_coordinate = [](auto p1, auto p2)
554+
{
555+
return p1[1]<p2[1];
556+
};
557+
558+
const double min_along_y = (*std::min_element(point_list.begin(), point_list.end(), compare_y_coordinate)) [1];
559+
const double max_along_y = (*std::max_element(point_list.begin(), point_list.end(), compare_y_coordinate)) [1];
560+
561+
// First parameterize the trench points:
562+
const Point<2> trench_point2(min_along_x, max_along_y, natural_coordinate_system);
563+
const Point<2> trench_point1(max_along_x, min_along_y, natural_coordinate_system);
564+
565+
// The unit vector that connects the two extremes of the trench points
566+
const Point<2> trench_uv = (trench_point2 - trench_point1) / (trench_point2 - trench_point1).norm();
567+
568+
// If both lines are parameterized with l_i = x_i + t_i * v_i, then since we know the points x_i and the
569+
// vectors v_i, we can solve for t_1 and t_2 when l_1 = l_2. This works out to be:
570+
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]);
571+
const double denominator = obliquity_vector[1] * trench_uv[0] - obliquity_vector[0] * trench_uv[1];
572+
const double t_val = numerator / denominator;
573+
574+
// If the two lines are parallel, t_val will be infinite. Check to see that this is not the case.
575+
if (std::isfinite(t_val))
576+
{
577+
// t_val is finite, now determine where the intersection point is, and see if this lies within the trench extents.
578+
const Point<2> intersection_point(check_point_surface_2d[0] + t_val * obliquity_vector[0],
579+
check_point_surface_2d[1] + t_val * obliquity_vector[1],
580+
natural_coordinate_system);
581+
582+
if (intersection_point[0] >= min_along_x && intersection_point[0] <= max_along_x
583+
&&
584+
intersection_point[1] >= min_along_y && intersection_point[1] <= max_along_y)
585+
{
586+
// The intersection point is within the trench extents, so we need to find the closest point on the curve
587+
// from this intersection point.
588+
closest_point_on_curve = bezier_curve.closest_point_on_curve_segment(intersection_point);
589+
closest_point_on_line_2d = closest_point_on_curve.point;
590+
}
591+
}
592+
593+
}
594+
}
595+
433596
// We now need 3d points from this point on, so make them.
434597
// The order of a Cartesian coordinate is x,y,z and the order of
435598
// a spherical coordinate it radius, long, lat (in rad).

0 commit comments

Comments
 (0)