approximate_min_ellipsoid_d_debug.h

来自「很多二维 三维几何计算算法 C++ 类库」· C头文件 代码 · 共 728 行 · 第 1/2 页

H
728
字号
	  << "    2 index 0 ge { neg } { } ifelse" << endl	  << "    % stack: a b c sqrt(disc)" << endl	  << "    % compute first solution (sqrt(disc)-b) / (2*a):" << endl	  << "    dup 3 index sub 4 index 2.0 mul div" << endl	  << "    5 1 roll" << endl	  << "    % stack: x1 a b c sqrt(disc)" << endl	  << "    % compute second solution 2*c / (sqrt(disc)-b):" << endl	  << "    3 2 roll sub exch 2.0 mul exch div" << endl	  << "    exch pop" << endl	  << "} def" << endl	  << "%" << endl	  << "% Usage: u v normalize u' v'" << endl	  << "% Takes the vector [u,v] and normalizes it to length 1." << endl	  << "/normalize {" << endl	  << "    dup dup mul" << endl	  << "    % stack: u v v^2" << endl	  << "    2 index dup mul add" << endl	  << "    % stack: u v v^2+u^2" << endl	  << "    sqrt 1.0 exch div dup 4 1 roll mul 3 1 roll mul exch" << endl	  << "} def" << endl	  << "%" << endl	  << "% Usage: a b h cellipse" << endl	  << "% Draws the ellipse x^T M x <= 1 with M = [[a,h],[h,b]]." << endl	  << "%" << endl	  << "/cellipse {" << endl	  << "% compute Eigen decomposition of M:" << endl	  << "%" << endl	  << "% stack: a b h" << endl	  << "dup 0.0 eq {" << endl	  << "	% ellipse is a sphere:" << endl	  << "	2 index sqrt" << endl	  << "	2 index sqrt" << endl	  << "	[ 1.0 0.0 0.0 1.0 0.0 0.0 ]" << endl	  << "}" << endl	  << "{" << endl	  << "	1.0" << endl	  << "	4 copy pop pop add neg" << endl	  << "	5 copy pop pop dup mul neg 3 1 roll mul add" << endl	  << "	find-roots" << endl	  << "	% stack: a b h x1 x2" << endl	  << "	%" << endl	  << "	% build first Eigenvector:" << endl	  << "	2 index 2 index 6 index sub normalize" << endl	  << "	% build second Eigenvector:" << endl	  << "	% stack: a b h x1 x2 ev1x ev1y" << endl	  << "	4 index 3 index 8 index sub normalize" << endl	  << "	% build matrix containing Eigenvectors:" << endl	  << "	% stack: a b h x1 x2 ev1x ev1y ev2x ev2y" << endl	  << "	6 array" << endl	  << "	dup 0 6 index put" << endl	  << "	dup 1 4 index put" << endl	  << "	dup 2 5 index put" << endl	  << "	dup 3 3 index put" << endl	  << "	dup 4 0 put" << endl	  << "	dup 5 0 put" << endl	  << "	5 1 roll pop pop pop pop" << endl	  << "} ifelse" << endl	  << "    % stack:  a b h x1 x2 T" << endl	  << "    %" << endl	  << "    % We now draw an circle scaled by x1 (along the " << endl	  << "    % x-axis) and x2 (along the y-axis):" << endl	  << "    matrix currentmatrix    %  remember CTM" << endl	  << "    % stack:  a b h x1 x2 T old-ctm" << endl	  << "    exch matrix invertmatrix concat" << endl	  << "    2 index sqrt 1.0 exch div 2 index sqrt 1.0" << endl	  << "    exch div scale" << endl	  << "    newpath" << endl	  << "    0 0 1 0 360 arc closepath" << endl	  << "    setmatrix               %  restore CTM" << endl	  << "    pop pop pop pop pop" << endl	  << "} def" << endl	  << "%" << endl	  << "% Usage: a b d u v mu ellipse" << endl	  << "% Finds the path (i.e., border) of the ellipse" << endl	  << "%" << endl	  << "%   E = { x | x^T M x + x^T m + mu <= 0 }," << endl	  << "%" << endl	  << "% where" << endl	  << "%" << endl	  << "%       [ a  b ]        [ u ]" << endl	  << "%   M = [      ],   m = [   ]" << endl	  << "%       [ b  d ]        [ v ]" << endl	  << "%" << endl	  << "% and det(M) > 0." << endl	  << "/ellipse {" << endl	  << "  /emu exch def" << endl	  << "  /ev exch def" << endl	  << "  /eu exch def" << endl	  << "  /ed exch def" << endl	  << "  /eb exch def" << endl	  << "  /ea exch def" << endl	  << "  /ematrix [ ea eb eb ed 0 0 ] matrix invertmatrix def" << endl	  << "  % compute z = M^{-1} m:" << endl	  << "  eu ev ematrix transform" << endl	  << "  /ezy exch def" << endl	  << "  /ezx exch def" << endl	  << "  % translate to center:" << endl	  << "  matrix currentmatrix    %  remember CTM" << endl	  << "  ezx neg 2 div ezy neg 2 div translate" << endl	  << "  % compute matrix of (now centrally symmetric) ellipse:" << endl	  << "  /efactor ezx eu mul ezy ev mul add 4.0 div emu sub def" << endl	  << "  ea efactor div ed efactor div eb efactor div cellipse" << endl	  << "  setmatrix               % restore CTM" << endl	  << "} def" << endl	  << "/setcol { 193 255 div 152 255 div 159 255 div" << endl	  << "          setrgbcolor" << endl	  << "} def" << endl	  << "%" << endl	  << "%" << endl	  << "%%EndProlog" << endl	  << "%%Page: 1 1" << endl;	  	// write content:	f << "gsave" << endl	  << body.str()	  << "grestore" << endl	  << "showpage" << endl	  << "%%Trailer" << endl;		// write footer:	f.close();      }          public: // modifiers:      // Sets the stroke mode for the next objects.      void set_stroke_mode(Stroke_mode m)      {	bm = m;      }            // Sets the labelmode for the next objects.      void set_label_mode(Label_mode m)      {	lm = m;      }            // Sets the label for the next object.  (This only makes sense if      // the label mode for the next object will be different from None.)      void set_label(const std::string& l)      {	next_label = l;      }            // Sets the angle for the next object drawn in mode Angle or      // Random_angle.  (So you can temporarily overwrite the random      // angle.)      void set_angle(double angle)      {	next_angle = angle;      }            // Enable or disable automatic adjusting of the bounding box.      void enlarge_bounding_box(bool active)      {	adjust_bb = active;      }            // Renders the line from (x,y) to (u,v) in the current stroke      // and label mode.      //      // Implementation note: stroke and label mode are not yet implemented.      void write_line(double x, double y, double u, double v,		      bool colored = false)      {	// set color:	if (colored)	  body << "gsave setcol" << std::endl;		// output ball in appropriate mode:	adjust_bounding_box(x,y);	adjust_bounding_box(u,v);	body << "newpath\n"	     << x << ' ' << y << " moveto\n"	     << u << ' ' << v << " lineto\n"	     << "stroke\n";	// restore color:	if (colored)	  body << "grestore" << std::endl;      }            // Renders the circle with center (x,y) and radius r in      // the current stroke and label mode.  All coordinates must be of      // type double.      void write_circle(double x, double y, double r, bool colored = false)      {	// set color:	if (colored)	  body << "gsave setcol" << std::endl;		// output ball in appropriate mode:	adjust_bounding_box(x-r,y-r);	adjust_bounding_box(x+r,y+r);	body << x << ' ' << y << ' ' << r << ' ';	const char *mode[] = { "ball", "bball", "dball" };	body << mode[static_cast<int>(bm)] << std::endl;		// output label:	if (lm != None) {	  const double dist = 5.0;	  const double lx = x + (r+dist/zoom)*std::cos(next_angle);	  const double ly = y + (r+dist/zoom)*std::sin(next_angle);	  adjust_bounding_box(lx,ly);	  body << x << ' ' << y << ' ' << r << " (" << next_label << ") "	       << dist << ' ' << next_angle << " drawl" << std::endl;	}		// restore color:	if (colored)	  body << "grestore" << std::endl;	// generate next angle (if needed):	if (lm == Random_angle)	  next_angle = static_cast<double>(std::rand());		// update counter and label:	next_label = default_label(++count);      }            // Renders the centrally symmetric ellipse x^T M x <= 1 with M =      // [[a,h],[h,b]] in the current stroke and label mode.      void write_cs_ellipse(double a,double b,double h)      {	using std::endl;	// Adjust the bounding box: For this, we use the fact that the	// ellipse has semi-axes of lengths (1/sqrt(c),1/sqrt(d)) where	//        //   (c,d) = find_roots(1.0,-(a+b),a b - h^2)	//	// (See Sven's thesis, code on page 87.)  So it it enclosed in	// some (rotated) rectangle of side lengths 2*c,2*d, centered	// at the origin.  Consequently, the circle of radius	// r=sqrt(c^2+d^2) encloses the ellipse, and we use this to	// find the bounding box:	const std::pair<double,double> semi = find_roots(1.0,-(a+b),a*b-h*h);	const double r = std::sqrt(1/semi.first+1/semi.second);	adjust_bounding_box(-r,-r);	adjust_bounding_box(r,r);	// draw the ellipse:	body << "gsave" << endl 	     << "  " << a << ' ' << b << ' ' << h << " cellipse" << endl;	if (bm == Solid_filled)	  body << "  gsave 0.6 setgray eofill grestore" << endl;	if (bm == Dashed)	  body << "  [dashlen] 0 setdash" << endl;	body << "  stroke" << endl << "grestore" << endl;		// output label:	// Todo: Not implemented yet.	if (false && lm != None) {	  const double distance = 5.0;	  body << a << ' ' << b << ' ' << distance << ' ' << next_angle	       << " cellipse-pt moveto (" << next_label << ") show" << endl;	}		// generate next angle (if needed):	if (lm == Random_angle)	  next_angle = static_cast<double>(std::rand());		// update counter and label:	next_label = default_label(++count);      }      // Renders the ellipse      //       //    E = { x | x^T M x + x^T m + mu <= 0 }      //      // where      //      //       [ a  h ]        [ u ]      //   M = [      ],   m = [   ]      //       [ h  b ]        [ v ]      //      // and det(M) > 0 in the current stroke and label mode.      void write_ellipse(double a,double b,double h,			 double u,double v,double mu)      {	using std::endl;		// adjust bounding box (see file boundingbox.mw and my file note):	const double tmp1 = a*b-h*h;	const double tmp2 = ((u*(u*b-2.0*v*h)+v*v*a)/tmp1-4.0*mu)/tmp1;	const double hw   = 0.5*std::sqrt(b*tmp2),  vw = 0.5*std::sqrt(a*tmp2);	const double hoff = -0.5*(u*b-v*h)/tmp1, voff = 0.5*(u*h-v*a)/tmp1;	adjust_bounding_box((std::min)(hw+hoff,-hw+hoff),			    (std::min)(vw+voff,-vw+voff));	adjust_bounding_box((std::max)(hw+hoff,-hw+hoff),			    (std::max)(vw+voff,-vw+voff));	#if 0	// draw bounding box:	body << "newpath " << (std::min)(hw+hoff,-hw+hoff) << " "	     << (std::min)(vw+voff,-vw+voff) << " moveto "	     << (std::max)(hw+hoff,-hw+hoff) << " " 	     << (std::min)(vw+voff,-vw+voff) << " lineto "	     << (std::max)(hw+hoff,-hw+hoff) << " "	     << (std::max)(vw+voff,-vw+voff) << " lineto "	     << (std::min)(hw+hoff,-hw+hoff)  << " "	     << (std::max)(vw+voff,-vw+voff) << " lineto closepath stroke\n";	#endif	// begin drawing:	body << "gsave" << endl;	// draw the ellipse:	body << "  " << a << ' ' << h << ' ' << b	     << ' ' << u << ' ' << v << ' ' << mu	     << " ellipse" << endl;	if (bm == Solid_filled)	  body << "  gsave 0.6 setgray eofill grestore" << endl;	if (bm == Dashed)	  body << "  [dashlen] 0 setdash" << endl;	body << "  stroke" << endl;	// output label:	// Todo: Not implemented yet.	// end drawing:	body << "grestore" << endl;	// generate next angle (if needed):	if (lm == Random_angle)	  next_angle = static_cast<double>(std::rand());		// update counter and label:	next_label = default_label(++count);      }      void adjust_bounding_box(double x,double y)      // Make sure the bounding box is large enough to contain the point (x,y).      {	if (adjust_bb) {	  bb[0] = (std::min)(x,bb[0]);	  bb[2] = (std::max)(x,bb[2]);	  bb[1] = (std::min)(y,bb[1]);	  bb[3] = (std::max)(y,bb[3]);	}      }          private: // utilities:      std::pair<double,double> find_roots(double a,double b,double c)      // Assuming a is nonzero, finds the roots of a x^2 + b x + c = 0.      {	double sd = std::sqrt(b*b-4.0*a*c);	if (b >= 0.0)	  sd = -sd;	return std::pair<double,double>( (sd-b)/(2*a), 2*c/(sd-b) );      }            static std::string default_label(int count)      {	return tostr(count);      }    };      } // namespace Approximate_min_ellipsoid_d_impl  } // namespace CGAL#endif // CGAL_APPROX_MIN_ELL_D_DEBUG_H

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?