bool BullCutter::generalEdgePush(const Fiber& f, Interval& i, const Point& p1, const Point& p2) const { //std::cout << " BullCutter::generalEdgePush() \n"; bool result = false; if ( isZero_tol( (p2-p1).xyNorm() ) ) { // this would be a vertical edge return result; } if ( isZero_tol( p2.z-p1.z ) ) // this would be a horizontal edge return result; assert( fabs(p2.z-p1.z) > 0.0 ); // no horiz edges allowed hereafter // p1+t*(p2-p1) = f.p1.z+radius2 => double tplane = (f.p1.z + radius2 - p1.z ) / (p2.z-p1.z); // intersect edge with plane at z = ufp1.z Point ell_center = p1+tplane*(p2-p1); assert( isZero_tol( fabs(ell_center.z - (f.p1.z+radius2)) ) ); Point major_dir = (p2-p1); assert( major_dir.xyNorm() > 0.0 ); major_dir.z = 0; major_dir.xyNormalize(); Point minor_dir = major_dir.xyPerp(); double theta = atan( (p2.z - p1.z) / (p2-p1).xyNorm() ); double major_length = fabs( radius2/sin(theta) ) ; double minor_length = radius2; AlignedEllipse e(ell_center, major_length, minor_length, radius1, major_dir, minor_dir ); if ( e.aligned_solver( f ) ) { // now we want the offset-ellipse point to lie on the fiber Point pseudo_cc = e.ePoint1(); // pseudo cc-point on ellipse and cylinder Point pseudo_cc2 = e.ePoint2(); CCPoint cc = pseudo_cc.closestPoint(p1,p2); CCPoint cc2 = pseudo_cc2.closestPoint(p1,p2); cc.type = EDGE_POS; cc2.type = EDGE_POS; Point cl = e.oePoint1() - Point(0,0,center_height); assert( isZero_tol( fabs(cl.z - f.p1.z)) ); Point cl2 = e.oePoint2() - Point(0,0,center_height); assert( isZero_tol( fabs(cl2.z - f.p1.z)) ); double cl_t = f.tval(cl); double cl_t2 = f.tval(cl2); if ( i.update_ifCCinEdgeAndTrue( cl_t, cc, p1, p2, true ) ) result = true; if ( i.update_ifCCinEdgeAndTrue( cl_t2, cc2, p1, p2, true ) ) result = true; } //std::cout << " BullCutter::generalEdgePush() DONE result= " << result << "\n"; return result; }
bool MillingCutter::singleVertexPush(const Fiber& f, Interval& i, const Point& p, CCType cctyp) const { bool result = false; if ( ( p.z >= f.p1.z ) && ( p.z <= (f.p1.z+ this->getLength()) ) ) { // p.z is within cutter Point pq = p.xyClosestPoint(f.p1, f.p2); // closest point on fiber double q = (p-pq).xyNorm(); // distance in XY-plane from fiber to p double h = p.z - f.p1.z; assert( h>= 0.0); double cwidth = this->width( h ); if ( q <= cwidth ) { // we are going to hit the vertex p double ofs = sqrt( square( cwidth ) - square(q) ); // distance along fiber Point start = pq - ofs*f.dir; Point stop = pq + ofs*f.dir; CCPoint cc_tmp( p, cctyp ); i.updateUpper( f.tval(stop) , cc_tmp ); i.updateLower( f.tval(start) , cc_tmp ); result = true; } } return result; }
// cone is pushed along Fiber f into contact with edge p1-p2 bool ConeCutter::generalEdgePush(const Fiber& f, Interval& i, const Point& p1, const Point& p2) const { bool result = false; if ( isZero_tol(p2.z-p1.z) ) // guard agains horizontal edge return result; assert( (p2.z-p1.z) != 0.0 ); // idea: as the ITO-cone slides along the edge it will pierce a z-plane at the height of the fiber // the shaped of the pierced area is either a circle if the edge is steep // or a 'half-circle' + cone shape if the edge is shallow (ice-cream cone...) // we can now intersect this 2D shape with the fiber and get the CL-points. // how to get the CC-point? (point on edge closest to z-axis of cutter? closest to CL?) // this is where the ITO cone pierces the plane // edge-line: p1+t*(p2-p1) = zheight // => t = (zheight - p1)/ (p2-p1) double t_tip = (f.p1.z - p1.z) / (p2.z-p1.z); if (t_tip < 0.0 ) t_tip = 0.0; Point p_tip = p1 + t_tip*(p2-p1); assert( isZero_tol( abs(p_tip.z-f.p1.z) ) ); // p_tip should be in plane of fiber // this is where the ITO cone base exits the plane double t_base = (f.p1.z+center_height - p1.z) / (p2.z-p1.z); Point p_base = p1 + t_base*(p2-p1); p_base.z = f.p1.z; // project to plane of fiber //std::cout << "(t0, t1) (" << t0 << " , " << t1 << ") \n"; double L = (p_base-p_tip).xyNorm(); if ( L <= radius ) { // this is where the ITO-slice is a circle // find intersection points, if any, between the fiber and the circle // fiber is f.p1 - f.p2 // circle is centered at p_base and radius double d = p_base.xyDistanceToLine(f.p1, f.p2); if ( d <= radius ) { // we know there is an intersection point. // http://mathworld.wolfram.com/Circle-LineIntersection.html // subtract circle center, math is for circle centered at (0,0) double dx = f.p2.x - f.p1.x; double dy = f.p2.y - f.p1.y; double dr = sqrt( square(dx) + square(dy) ); double det = (f.p1.x-p_base.x) * (f.p2.y-p_base.y) - (f.p2.x-p_base.x) * (f.p1.y-p_base.y); // intersection given by: // x = det*dy +/- sign(dy) * dx * sqrt( r^2 dr^2 - det^2 ) / dr^2 // y = -det*dx +/- abs(dy) * sqrt( r^2 dr^2 - det^2 ) / dr^2 double discr = square(radius) * square(dr) - square(det); assert( discr > 0.0 ); // this means we have an intersection if ( discr == 0.0 ) { // tangent case double x_tang = ( det*dy )/ square(dr); double y_tang = -( det*dx )/ square(dr); Point p_tang(x_tang+p_base.x, y_tang+p_base.y); // translate back from (0,0) system! double t_tang = f.tval( p_tang ); if ( circle_CC( t_tang, p1, p2, f, i) ) result = true; } else { // two intersection points double x_pos = ( det*dy + sign(dy)* dx * sqrt( discr ) ) / square(dr); double y_pos = ( -det*dx + abs(dy) * sqrt( discr ) ) / square(dr); Point p_pos(x_pos+p_base.x, y_pos+p_base.y); double t_pos = f.tval( p_pos ); // the same with "-" sign: double x_neg = ( det*dy - sign(dy) * dx * sqrt( discr ) ) / square(dr); double y_neg = ( -det*dx - abs(dy) * sqrt( discr ) ) / square(dr); Point p_neg(x_neg+p_base.x, y_neg+p_base.y); double t_neg = f.tval( p_neg ); if ( circle_CC( t_pos, p1, p2, f, i) ) result = true; if ( circle_CC( t_neg, p1, p2, f, i) ) result = true; } } return result; } else { // ITO-slice is cone + half-circle // lines from p_tip to tangent points assert( L > radius ); // http://mathworld.wolfram.com/CircleTangentLine.html // circle centered at x0, y0, radius a // tangent through (0,0) // t = +/- acos( -a*x0 +/- y0*sqrt(x0^2+y0^2-a^2) / (x0^2+y0^2) ) // translate so p_mid is at (0,0) //Point c = p_base - p_mid; //double cos1 = (-radius*c.x + c.y*sqrt(square(c.x)+square(c.y)+square(radius)) )/ (square(c.x) + square(c.y) ); //double cos2 = (-radius*c.x - c.y*sqrt(square(c.x)+square(c.y)+square(radius)) )/ (square(c.x) + square(c.y) ); return result; } }