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