RealVectorValue CrackFrontDefinition::calculateCrackFrontDirection(const Node* crack_front_node, const RealVectorValue& tangent_direction, const CRACK_NODE_TYPE ntype) const { RealVectorValue crack_dir; RealVectorValue zero_vec(0.0); bool calc_dir = true; if (_end_direction_method == END_CRACK_DIRECTION_VECTOR) { if (ntype == END_1_NODE) { crack_dir = _crack_direction_vector_end_1; calc_dir = false; } else if (ntype == END_2_NODE) { crack_dir = _crack_direction_vector_end_2; calc_dir = false; } } if (calc_dir) { if (_direction_method == CRACK_DIRECTION_VECTOR) { crack_dir = _crack_direction_vector; } else if (_direction_method == CRACK_MOUTH) { if (_crack_mouth_coordinates.absolute_fuzzy_equals(*crack_front_node,1.e-15)) { mooseError("Crack mouth too close to crack front node"); } RealVectorValue mouth_to_front = *crack_front_node - _crack_mouth_coordinates; RealVectorValue crack_plane_normal = mouth_to_front.cross(tangent_direction); if (crack_plane_normal.absolute_fuzzy_equals(zero_vec,1.e-15)) { mooseError("Vector from crack mouth to crack front node is collinear with crack front segment"); } crack_dir = tangent_direction.cross(crack_plane_normal); Real dotprod = crack_dir*mouth_to_front; if (dotprod < 0) { crack_dir = -crack_dir; } } else if (_direction_method == CURVED_CRACK_FRONT) { crack_dir = tangent_direction.cross(_crack_plane_normal); } } crack_dir = crack_dir.unit(); return crack_dir; }
OrientedBoxInterface::OrientedBoxInterface(const InputParameters & parameters) : _center(parameters.get<Point>("center")) { const std::string & name = parameters.get<std::string>("_object_name"); // Define the bounding box Real xmax = 0.5 * parameters.get<Real>("width"); Real ymax = 0.5 * parameters.get<Real>("length"); Real zmax = 0.5 * parameters.get<Real>("height"); Point bottom_left(-xmax, -ymax, -zmax); Point top_right(xmax, ymax, zmax); _bounding_box = new MeshTools::BoundingBox(bottom_left, top_right); /* * now create the rotation matrix that rotates the oriented * box's width direction to "x", its length direction to "y" * and its height direction to "z" */ RealVectorValue w = parameters.get<RealVectorValue>("width_direction"); RealVectorValue l = parameters.get<RealVectorValue>("length_direction"); /* * Normalize the width and length directions in readiness for * insertion into the rotation matrix */ Real len = w.norm(); if (len == 0.0) mooseError("Length of width_direction vector is zero in " << name); w /= len; len = l.norm(); if (len == 0.0) mooseError("Length of length_direction vector is zero in " << name); l /= len; if (w*l > 1E-10) mooseError("width_direction and length_direction are not perpendicular in " << name); // The rotation matrix! _rot_matrix = new RealTensorValue(w, l, w.cross(l)); }
bool LineSegment::intersect (const LineSegment & l, Point & intersect_p) const { /** * First check for concurance: * * * | x1 y1 z1 1 | * | x2 y2 z2 1 | = (x3 - x1) * [(x2-x1) x (x4-x3)] = 0 * | x3 y3 z3 1 | * | x4 y4 z4 1 | * * * Solve: * x = _p0 + (_p1 - _p0)*s * x = l.p0 + (l._p1 - l.p0)*t * * where * a = _p1 - _p0 * b = l._p1 - l._p0 * c = l._p0 - _p0 * * s = (c x b) * (a x b) / | a x b |^2 */ RealVectorValue a = _p1 - _p0; RealVectorValue b = l._p1 - l._p0; RealVectorValue c = l._p0 - _p0; RealVectorValue v = a.cross(b); // Check for parallel lines if (std::abs(v.norm()) < 1.e-10 && std::abs(c.cross(a).norm()) < 1.e-10) { // TODO: The lines are co-linear but more work is needed to determine and intersection point // it could be the case that the line segments don't lie on the same line or overlap only // a bit return true; } // Check that the lines are coplanar Real concur = c * (a.cross(b)); if (std::abs(concur) > 1.e-10) return false; Real s = (c.cross(b) * v) / (v*v); Real t = (c.cross(a) * v) / (v*v); // if s and t are between 0 and 1 then the Line Segments intersect // TODO: We could handle other case of clamping to the end of Line // Segements if we want to here if (s >= 0 && s <= 1 && t >= 0 && t <= 1) { intersect_p = _p0 + s*a; return true; } return false; /** * Parameteric Equation of lines * _p0 + t(v0) = l._p0 + u(v1) * * Case 1: Parallel Lines * v0 x v1 == 0 * * Case 1a: Collinear Lines * v0 x v1 == 0 * (l._p0 - _p0) x (_p1 - _p0) == 0 * * Case 2: Intersecting Lines * 0 <= t <= 1 * 0 <= u <= 1 * * * Case 1: The lines do not intersect * vleft cross vright = non-zero * * Case 2: The lines are co-linear * vleft cross vright = zero * vleft (Denominator) = zero * * Case 3: The line intersect at a single point * vleft cross vright = zero * vleft (Denominator) = non-zero RealVectorValue v0 = _p1 - _p0; RealVectorValue v1 = l._p1 - l._p0; RealVectorValue v2 = l._p0 - _p0; RealVectorValue vbot = v0.cross(v1); RealVectorValue vtop = v2.cross(v1); RealVectorValue crossed = vleft.cross(vright); // Case 1: No intersection if (std::abs(vleft.cross(vright).size()) > 1.e-10) return false; // Case 2: Co-linear (just return one of the end points) if (std::abs(vleft.size()) < 1.e-10) { intersect_p = _p0; return true; } // Case 3: //TODO: We could detect whether the Line Segments actually overlap // instead of whether the Lines are co-linear Real a = vright.size()/vleft.size(); intersect_p = _p0 + a*v0; return true; */ }