Народу на рассмотрение предлагается следующая задачка:
В декартовой системе координат дан эллипс. Известны координаты двух произвольных точек на эллипсе, оба радиуса эллипса а так же угол поворота осей эллипса относительно координатных осей. Найти: координаты центра эллипса. Толи я туплю, то ли действительно данных недостаточно, но что то с наскоку решить не получилось Плюс нету ни одного учебника (аналитической) геометрии под рукой формулы глянуть..
Здравствуйте, Xenia, Вы писали:
X>Народу на рассмотрение предлагается следующая задачка:
X>В декартовой системе координат дан эллипс. Известны координаты двух произвольных точек на эллипсе, оба радиуса эллипса а так же угол поворота осей эллипса относительно координатных осей. Найти: координаты центра эллипса. Толи я туплю, то ли действительно данных недостаточно, но что то с наскоку решить не получилось Плюс нету ни одного учебника (аналитической) геометрии под рукой формулы глянуть..
Если поворот осей известен, а также известно, что радиусы a и b, то вдоль осей сжимаешь/растягиваешь в a и b раз.
Теперь есть две новые точки, через которые нужно провести окружность единичного радиуса. Это уже просто — два варианта (середина отрезка, перпендикуляр нужной длины).
Обратным растяжением/сжатием возвращаешь все на место.
ЗЫ Можно, естественно, и одним растяжением обойтись.
Растяжение это круто. Правда как считать я всё равно не понял.
Сам я мыслю так:
Рисуем эллипс с данными радиусами (a,b) с центром в начале координат. (школьное уравнение: x^2/a + y^2/b = 1)
Если данный угол наклона alfa, то поворачиаем отрезок соединяющий данные точки на угол -alfa (на тот же угол только в обратном направлении). Находим расстояние м/у этими точками и угол наклона полученного отрезка к осям координат ( = beta). Теперь нужно перенести эти точки на нарисованный эллипс (так чтобы отрезок их соединющий лежал на прямой y = k*x + c, где k=tg(beta), а c ещё надо найти). Пусть координатя этих точек — (x1,y1) и (x2,y2). Тогда имеем следующие уравнения:
1) x1^2/a + y1^2/b = 1
2) x2^2/a + y2^2/b = 1
3) y1 = k*x1 + c
4) y2 = k*x2 + c
5) (x2-x1)^2 + (y2-y1)^2 = r^2
Здесь 5 неизвестных: x1,x2,y1,y2,c.
Находим разницу м/у x1 и x2 (delta = sqrt(r^2/(1+k^2))), подставляем 3) в 1), 4) в 2), заменяем x2 на (x1 — delta). Короче получаем 2 квадратных уравнения с 2-я неизвестными (x1 и c), решаем (если кто решит — напишите ).
Находим координаты этих точек.
Поворачиваем любую из этих точек вокруг центра координат на угол alfa, вокруг начала координат.
Затем находим разницу координат полученой точки и данной (из условия задачи) и смещаем центр рисованого эллипса из центра координат на эту разницу и получем искомый центр.
Здравствуйте, Mazay, Вы писали:
M>Здравствуйте, Apapa, Вы писали:
M>Растяжение это круто. Правда как считать я всё равно не понял.
Чего тут непонятного...
Если эллипс повернут на alpha по часовой, его радиус по x до поворота равен a, по y — b, а две данные точки — это x1,y1 и x2,y2, то следующее преобразование повертнет, отмасштабирует и переведет одну из точек в начало координат:
Здравствуйте, Xenia, Вы писали:
X>В декартовой системе координат дан эллипс. Известны координаты двух произвольных точек на эллипсе, оба радиуса эллипса а так же угол поворота осей эллипса относительно координатных осей. Найти: координаты центра эллипса. Толи я туплю, то ли действительно данных недостаточно, но что то с наскоку решить не получилось Плюс нету ни одного учебника (аналитической) геометрии под рукой формулы глянуть..
Задача не такая тривиальная, как кажется, особенно учитывая всевозможные условия, типа достаточности радиусов (чтобы он не провалился в дырку прмеж точек). Вот нарыл из batik-svg на Java:
/**
* This constructs an unrotated Arc2D from the SVG specification of an
* Elliptical arc. To get the final arc you need to apply a rotation
* transform such as:
*
* AffineTransform.getRotateInstance
* (angle, arc.getX()+arc.getWidth()/2, arc.getY()+arc.getHeight()/2);
*/public static Arc2D computeArc(double x0, double y0,
double rx, double ry,
double angle,
boolean largeArcFlag,
boolean sweepFlag,
double x, double y) {
//
// Elliptical arc implementation based on the SVG specification notes
//
// Compute the half distance between the current and the final pointdouble dx2 = (x0 - x) / 2.0;
double dy2 = (y0 - y) / 2.0;
// Convert angle from degrees to radians
angle = Math.toRadians(angle % 360.0);
double cosAngle = Math.cos(angle);
double sinAngle = Math.sin(angle);
//
// Step 1 : Compute (x1, y1)
//double x1 = (cosAngle * dx2 + sinAngle * dy2);
double y1 = (-sinAngle * dx2 + cosAngle * dy2);
// Ensure radii are large enough
rx = Math.abs(rx);
ry = Math.abs(ry);
double Prx = rx * rx;
double Pry = ry * ry;
double Px1 = x1 * x1;
double Py1 = y1 * y1;
// check that radii are large enoughdouble radiiCheck = Px1/Prx + Py1/Pry;
if (radiiCheck > 1) {
rx = Math.sqrt(radiiCheck) * rx;
ry = Math.sqrt(radiiCheck) * ry;
Prx = rx * rx;
Pry = ry * ry;
}
//
// Step 2 : Compute (cx1, cy1)
//double sign = (largeArcFlag == sweepFlag) ? -1 : 1;
double sq = ((Prx*Pry)-(Prx*Py1)-(Pry*Px1)) / ((Prx*Py1)+(Pry*Px1));
sq = (sq < 0) ? 0 : sq;
double coef = (sign * Math.sqrt(sq));
double cx1 = coef * ((rx * y1) / ry);
double cy1 = coef * -((ry * x1) / rx);
//
// Step 3 : Compute (cx, cy) from (cx1, cy1)
//double sx2 = (x0 + x) / 2.0;
double sy2 = (y0 + y) / 2.0;
double cx = sx2 + (cosAngle * cx1 - sinAngle * cy1);
double cy = sy2 + (sinAngle * cx1 + cosAngle * cy1);
//
// Step 4 : Compute the angleStart (angle1) and the angleExtent (dangle)
//double ux = (x1 - cx1) / rx;
double uy = (y1 - cy1) / ry;
double vx = (-x1 - cx1) / rx;
double vy = (-y1 - cy1) / ry;
double p, n;
// Compute the angle start
n = Math.sqrt((ux * ux) + (uy * uy));
p = ux; // (1 * ux) + (0 * uy)
sign = (uy < 0) ? -1d : 1d;
double angleStart = Math.toDegrees(sign * Math.acos(p / n));
// Compute the angle extent
n = Math.sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy));
p = ux * vx + uy * vy;
sign = (ux * vy - uy * vx < 0) ? -1d : 1d;
double angleExtent = Math.toDegrees(sign * Math.acos(p / n));
if(!sweepFlag && angleExtent > 0) {
angleExtent -= 360f;
} else if (sweepFlag && angleExtent < 0) {
angleExtent += 360f;
}
angleExtent %= 360f;
angleStart %= 360f;
//
// We can now build the resulting Arc2D in double precision
//
Arc2D.Double arc = new Arc2D.Double();
arc.x = cx - rx;
arc.y = cy - ry;
arc.width = rx * 2.0;
arc.height = ry * 2.0;
arc.start = -angleStart;
arc.extent = -angleExtent;
return arc;
}
Вот пример использования:
/**
* Adds an elliptical arc, defined by two radii, an angle from the
* x-axis, a flag to choose the large arc or not, a flag to
* indicate if we increase or decrease the angles and the final
* point of the arc.
*
* @param rx, ry the radii of the ellipse
*
* @param theta the angle from the x-axis of the current
* coordinate system to the x-axis of the ellipse in degrees.
*
* @param largeArcFlag the large arc flag. If true the arc
* spanning less than or equal to 180 degrees is chosen, otherwise
* the arc spanning greater than 180 degrees is chosen
*
* @param sweepFlag the sweep flag. If true the line joining
* center to arc sweeps through decreasing angles otherwise it
* sweeps through increasing angles
*
* @param x, y the absolute coordinates of the final point of
* the arc.
*/public synchronized void arcTo(double rx, double ry,
double angle,
boolean largeArcFlag,
boolean sweepFlag,
double x, double y) {
// Ensure radii are validif (rx == 0 || ry == 0) {
lineTo((float) x, (float) y);
return;
}
// Get the current (x, y) coordinates of the path
Point2D p2d = path.getCurrentPoint();
double x0 = p2d.getX();
double y0 = p2d.getY();
if (x0 == x && y0 == y) {
// If the endpoints (x, y) and (x0, y0) are identical, then this
// is equivalent to omitting the elliptical arc segment entirely.return;
}
Arc2D arc = computeArc(x0, y0, rx, ry, angle,
largeArcFlag, sweepFlag, x, y);
if (arc == null) return;
AffineTransform t = AffineTransform.getRotateInstance
(Math.toRadians(angle), arc.getCenterX(), arc.getCenterY());
Shape s = t.createTransformedShape(arc);
path.append(s, true);
}
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, Apapa, Вы писали:
A>Если эллипс повернут на alpha по часовой, его радиус по x до поворота равен a, по y — b, а две данные точки — это x1,y1 и x2,y2, то следующее преобразование повертнет, отмасштабирует и переведет одну из точек в начало координат: A>
X>В декартовой системе координат дан эллипс.
А вот такой вариант: имеется надцать точек на плоскости. Они образуют эллипс. Требуется вычислить координаты центра
eggor wrote: > X>В декартовой системе координат дан эллипс. > А вот такой вариант: имеется надцать точек на плоскости. Они образуют > эллипс. Требуется вычислить координаты центра
Достаточно трех точек. Строим обычную систему уравнений, где
коэффициентами будут характеристические коэффициенты эллипса, и решаем ее.
Здравствуйте, Cyberax, Вы писали:
>> А вот такой вариант: имеется надцать точек на плоскости. Они образуют >> эллипс. Требуется вычислить координаты центра C>Достаточно трех точек. Строим обычную систему уравнений, где C>коэффициентами будут характеристические коэффициенты эллипса, и решаем ее.
ой-ли
x*x-x+y*y-y=0 --- эллипс (на самом деле окружность)
x*x-x+2y*y-2y=0 --- эллипс
Константин wrote: > C>Достаточно трех точек. Строим обычную систему уравнений, где > C>коэффициентами будут характеристические коэффициенты эллипса, и решаем ее. > ой-ли > x*x-x+y*y-y=0 --- эллипс (на самом деле окружность) > x*x-x+2y*y-2y=0 --- эллипс > оба проходят через (0,0), (0,1), (1,0)
Забыл добавить — с центром в начале координат. Иначе нужна еще пара точек.