@@ -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