Переход на матричные преобразования: различия между версиями

Материал из Common History development
Перейти к навигации Перейти к поиску
(‎)
(результаты)
 
(не показано 17 промежуточных версий этого же участника)
Строка 1: Строка 1:
[[Category:Модель для меридиана]]
+
[[Category:Алгоритм моделирования рельефа‎ ]]
 
{{live|17526}}
 
{{live|17526}}
 +
= и снятся парты аудиторий =
 
Ещё недавно косинусы углов считал функцией System.Math.Cos().
 
Ещё недавно косинусы углов считал функцией System.Math.Cos().
  
 +
Углов стало больше - перешел на скалярное произведение единичных векторов. Крайние условия для тех, что коллинеарны, пришлось тщательно описывать, куда же денешься.
  
Позавчера распробовал вкус скалярного произведения единичных векторов. Крайние условия для тех, что коллинеарны, пришлось тщательно описывать, куда же денешься.
 
  
 +
И тут понял, что [[матричные преобразования]] компактнее, учитывают крайние условия, считают косинусы связанных углов и проще оптимизируются.
  
И вот только сейчас понял, что матричные преобразования лучше всех; и косинусы связанных углов считают, и предлагают неожиданное...
+
Вот результирующий код для расчета матрицами:
 +
<source lang=CSharp>
 +
var aOnSurface = axisOrtohonal.Direction * b.Matrix;
 +
aTraverse = -a * aOnSurface[1];
 +
var aMerid = (b.Vartheta < 0 ? 1 : -1) * a * aOnSurface[2];
 +
return aMerid;
 +
</source>
  
 +
и вот для сравнения, как считалось скалярным произведением вначале:
 +
<source lang=CSharp>
 +
var surfaceCalm = new Plane(b.NormalCalm, b.r);
 +
var QonAxisPlane = new Plane(axisEnd, b.Q3, Basin.O3);
  
Простите, что так медленно рисую карты сдвига полюсов. Но дело это будет завершено, и скоро.
+
// aSphere direction
 +
var aSphereLine = surfaceCalm.IntersectionWith(QonAxisPlane);
  
 +
var b3unit = new Line3D(Basin.O3, b.Q3).Direction;
 +
// lays in surfaceCalm plane, directed to equator of AxisOfRotation if Math.Abs used
 +
var aSphere = //Math.Abs
 +
    (a * AxisOfRotation.DotProduct(b3unit));// axisOrtohonal.Direction.DotProduct(aSphereLine.Direction));
  
 +
var aMeridianLine = surfaceCalm.IntersectionWith(b.MeridianCalm); //new Plane(OzEnd, Q3, O3);
 +
var aTraverseLine = surfaceCalm.IntersectionWith(b.TraverseCalm);
 +
Assert.AreEqual(0, aMeridianLine.Direction.DotProduct(aTraverseLine.Direction), .000000001);
  
= =
+
aTraverse = Math.Abs(aSphere * aSphereLine.Direction.DotProduct(aTraverseLine.Direction));
[[file:RotationAxis vectors.png]]
+
 
= результаты =
+
var planeOZ = new Plane(Basin.Oz);
одолел-таки скалярные произведения векторов
+
var planeAxis = new Plane(AxisOfRotation);
 +
 
 +
//directed to equator of Oz if Math.Abs used
 +
double aMeridian;
 +
/*if (aSphereLine.IsCollinear(aMeridianLine, .1))
 +
{
 +
    aMeridian = aSphere;
 +
}
 +
else*/
 +
{
 +
    var dotProduct = aSphereLine.Direction.DotProduct(aMeridianLine.Direction);
 +
    aMeridian = Math.Abs(aSphere * dotProduct);
 +
}
 +
 
 +
 
 +
// if (AxisOfRotation != Basin.Oz)
 +
var spin = new Plane(Basin.OzEnd, b3unit.ToPoint3D(), axisEnd).Normal.DotProduct(b3unit);
 +
 
 +
// "north" hemisphere of AxisOfRotation
 +
if (b3unit.DotProduct(AxisOfRotation) > 0)
 +
{
 +
    if (spin > 0)
 +
    {
 +
        aTraverse = -aTraverse;
 +
    }
 +
}
 +
else
 +
{
 +
    if (spin < 0)
 +
    {
 +
        aTraverse = -aTraverse;
 +
    }
 +
}
  
в модели океана без дна сдвиг полюса на 17 градусов (из текущего положение в 40 зап.долг. 73 сев.шир.) вызывает волну относительно текущего геоида высотой около 5 км
+
//aMeridian<0 if Q3 between planes or inside of cones (bug when angle is near 90) of OZ and AxisOfRotation
 +
if (planeOZ.SignedDistanceTo(b.Q3) * planeAxis.SignedDistanceTo(b.Q3) < 0)
 +
{
 +
    aMeridian = -aMeridian;
 +
}
 +
else
 +
{
 +
    var coneAxis = new UnitVector3D((Basin.Oz + AxisOfRotation).ToVector());
 +
    if (new UnitVector3D(b.Q3.ToVector()).DotProduct(coneAxis) > coneAxis.DotProduct(Basin.Oz))
 +
    {
 +
        //inside cone
 +
        aMeridian = -aMeridian;
 +
    }
 +
}
 +
return aMeridian;
 +
</source>
  
полюс показан розовыми точками
+
= диаграмма векторов =
[[file:OceanMap_lines96.gif]]
+
[[file:RotationAxis vectors.png]]
  
этот пост будет изменяться...
+
= [[Тазики на сфере]] =

Текущая версия на 13:54, 23 апреля 2019

комментарии в LiveJournal

и снятся парты аудиторий[править]

Ещё недавно косинусы углов считал функцией System.Math.Cos().

Углов стало больше - перешел на скалярное произведение единичных векторов. Крайние условия для тех, что коллинеарны, пришлось тщательно описывать, куда же денешься.


И тут понял, что матричные преобразования компактнее, учитывают крайние условия, считают косинусы связанных углов и проще оптимизируются.

Вот результирующий код для расчета матрицами:

var aOnSurface = axisOrtohonal.Direction * b.Matrix;
aTraverse = -a * aOnSurface[1];
var aMerid = (b.Vartheta < 0 ? 1 : -1) * a * aOnSurface[2];
return aMerid;

и вот для сравнения, как считалось скалярным произведением вначале:

var surfaceCalm = new Plane(b.NormalCalm, b.r);
var QonAxisPlane = new Plane(axisEnd, b.Q3, Basin.O3);

// aSphere direction
var aSphereLine = surfaceCalm.IntersectionWith(QonAxisPlane);

var b3unit = new Line3D(Basin.O3, b.Q3).Direction;
// lays in surfaceCalm plane, directed to equator of AxisOfRotation if Math.Abs used
var aSphere = //Math.Abs
    (a * AxisOfRotation.DotProduct(b3unit));// axisOrtohonal.Direction.DotProduct(aSphereLine.Direction)); 

var aMeridianLine = surfaceCalm.IntersectionWith(b.MeridianCalm); //new Plane(OzEnd, Q3, O3);
var aTraverseLine = surfaceCalm.IntersectionWith(b.TraverseCalm);
Assert.AreEqual(0, aMeridianLine.Direction.DotProduct(aTraverseLine.Direction), .000000001);

aTraverse = Math.Abs(aSphere * aSphereLine.Direction.DotProduct(aTraverseLine.Direction));

var planeOZ = new Plane(Basin.Oz);
var planeAxis = new Plane(AxisOfRotation);

//directed to equator of Oz if Math.Abs used
double aMeridian;
/*if (aSphereLine.IsCollinear(aMeridianLine, .1))
{
    aMeridian = aSphere;
}
else*/
{
    var dotProduct = aSphereLine.Direction.DotProduct(aMeridianLine.Direction);
    aMeridian = Math.Abs(aSphere * dotProduct);
}


// if (AxisOfRotation != Basin.Oz)
var spin = new Plane(Basin.OzEnd, b3unit.ToPoint3D(), axisEnd).Normal.DotProduct(b3unit);

// "north" hemisphere of AxisOfRotation
if (b3unit.DotProduct(AxisOfRotation) > 0) 
{
    if (spin > 0)
    {
        aTraverse = -aTraverse;
    }
}
else
{
    if (spin < 0)
    {
        aTraverse = -aTraverse;
    }
}

//aMeridian<0 if Q3 between planes or inside of cones (bug when angle is near 90) of OZ and AxisOfRotation
if (planeOZ.SignedDistanceTo(b.Q3) * planeAxis.SignedDistanceTo(b.Q3) < 0)
{
    aMeridian = -aMeridian;
}
else
{
    var coneAxis = new UnitVector3D((Basin.Oz + AxisOfRotation).ToVector());
    if (new UnitVector3D(b.Q3.ToVector()).DotProduct(coneAxis) > coneAxis.DotProduct(Basin.Oz))
    {
        //inside cone
        aMeridian = -aMeridian;
    }
}
return aMeridian;

диаграмма векторов[править]

RotationAxis vectors.png

Тазики на сфере[править]