[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Draw a ellipse



On Sun, 27 Jun 2004, Gunnar wrote:

> I'm trying to draw the following figure with epix:
> |x|^n + |y|^n = 1   for n=2,3,4,5...
>
> Here is the c++ code.
>
> [snip]
>
> double f(double x){return exp(log(1.0-abs(x*x))/2.0);}
> double g(double x){return -exp(log(1.0-abs(x*x))/2.0);}
>
Dear Gunnar,

When I try to compile the file, there are nan errors at the endpoints
from evaluating log(0). :)

When the bounding_box or plot range are changed, e.g.

  bounding_box(P(-0.999,-1),P(0.999,1))

the graphs look the same for me.

By the way, you can plot parametrically, even for fractional exponents. A
sample file is attached, commentary follows:

---(snip)---
// phi traces out the real portion of |x|^pwr + |y|^pwr = 1
// as t traces a full turn in the current angular units
//
P phi(double t, double pwr)
{
  double x = ePiX::cos(t); // for clarity, and to re-use the values
  double y = ePiX::sin(t);

  // sgn(x) = sign of x = x/|x|
  // Must double the exponent since cos^2 + sin^2 = 1
  return P(sgn(x)*pow(fabs(x), 2*pwr), sgn(y)*pow(fabs(y), 2*pwr));
}
---(snip)---

Then either:
* use multiplot2 (whose syntax is obscure, I'm afraid, but it plots
several curves by holding the second variable constant in each curve)

* define the actual curves you'll plot manually

---(snip)---
  // Method I, in figure body:
  // Plot 6 (5+1) curves with exponents ranging from 0.25 to 2,
  // using 120 points per curve.
  revolutions();
  multiplot2(phi, P(0,0.25), P(1,2), mesh(1, 5), 120);

  // Method II, in preamble:
  inline double f1(double t) { return phi(t, 2.5); }
  // ...then in the body, assuming revolutions()
  plot(f1, 0, 1, 120);
---(snip)---

I'm thinking about better (that is, simpler) ways of plotting curves in a
family. The current idea (for all types of plot) is to define a "domain"
class that consists of a coordinate box and two integer meshes ("coarse"
and "fine"). The box determines the bounds on plot intervals, the coarse
mesh says how many curves to plot, and the fine mesh says how many points
per curve to use. Each "plot" function will then deal intelligently (in
some sense:) with a domain. The idea is for users to be able to write

// In the preamble
double f(double, double); //... real-valued function
P F(double, double); //... vector-valued map

// The rectangle [-1,2] x [-1,4] with an 8 x 12 grid
domain R(P(-1,-1), P(2,4), mesh(8,12), mesh(80,80));

// In the body
  plot(f, R); // function graph
  plot(f, R.slice2(0.5)); // graph of t -> f(t, 0.5)
  plot(f, R.slice2()); // plot all slices with 2nd variable held constant

  plot(F, R); // parametric surface


I didn't make as much progress over the weekend as I'd hoped, though. :(

--Andy

Andrew D. Hwang			ahwang@mathcs.holycross.edu
Department of Math and CS	http://math.holycross.edu/~ahwang
College of the Holy Cross	(508) 793-2458 (Office: 320 Swords)
Worcester, MA, 01610-2395	(508) 793-3530 (fax)
#include "epix.h"
using namespace ePiX;

P phi(double t, double n)
{
  double x = ePiX::cos(t);
  double y = ePiX::sin(t);

  return P(sgn(x)*pow(fabs(x), 2*n), sgn(y)*pow(fabs(y), 2*n));
}


main(){
  bounding_box(P(-1,-1),P(1,1));
  unitlength("1in");      
  picture(P(4,4));
  
  begin();
  grid(8,8);

  revolutions();
  red();
  bold();

  // plot over [0,1] x [0.25,2], at 5+1 equally-spaced x2-values,
  // using 120 points per curve
  multiplot2(phi, P(0,0.25), P(1,2), mesh(1, 5), 120);

  end();
}