Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Точка пересечения прямой и плоскости 
V
    Опции темы
BoomeR
  Дата 17.6.2008, 17:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 79
Регистрация: 24.12.2006
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Функция выдаёт серьёзные ошибки, но только в случае маленького угла линии к плоскости с которой ищется пересечение. Помогите советом, всё перепроверил по формулам вроде так...  smile 

Код

        public struct point 
        {
            public    PointF XY;
            public    float Z;
        }
                
        public struct platitude
        {
            public double A,B,C,D;
            public bool invers;
        }


.....


        private point LinexPl (point p1,point p2, platitude Pl)
        {
            double cosa,cosb,cosg,M,t;
            point Cross = new point();

            M = Math.Sqrt((p2.XY.X-p1.XY.X)*(p2.XY.X-p1.XY.X)+(p2.XY.Y-p1.XY.Y)*(p2.XY.Y-p1.XY.Y)+(p2.Z-p1.Z)*(p2.Z-p1.Z));
            cosa = (p2.XY.X - p1.XY.X)/M;
            cosb = (p2.XY.Y - p1.XY.Y)/M;
            cosg = (p2.Z-p1.Z)/M;
            t = (Pl.A*p1.XY.X + Pl.B*p1.XY.Y + Pl.C*p1.Z + Pl.D)/(Pl.A*cosa + Pl.B*cosb + Pl.C*cosg);

            if (((Pl.A*cosa + Pl.B*cosb + Pl.C*cosg)!=0)&&((Pl.A*p1.XY.X+Pl.B*p1.XY.Y+Pl.C*p1.Z+Pl.D)!=0)) //Если прямая не паралельна и не принадлежит
            {
                Cross.XY.X = (float)(p1.XY.X - t*cosa);
                Cross.XY.Y = (float)(p1.XY.Y - t*cosb);
                Cross.Z    = (float)(p1.Z - t*cosg);
            }
            else {Cross.XY.X=0;Cross.XY.Y=0;Cross.Z=0;}

            return Cross;
        }


Точка p1 - координаты лампочки, точка p2 - координаты вершины которая отбрасывает тень, плоскость Pl - пол или стенка на которую отбрасываться тень.

Это сообщение отредактировал(а) BoomeR - 26.6.2008, 18:28
PM MAIL WWW ICQ Skype   Вверх
Dennnis
Дата 17.6.2008, 17:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 145
Регистрация: 23.3.2008

Репутация: нет
Всего: 4



А ты не мог бы привести значения параметров при которых выдается ошибка, а то в твоем коде фиг разберешься)
--------------------
Get Rich or Die Tryin'
PM   Вверх
mihryak
Дата 17.6.2008, 17:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 731
Регистрация: 28.4.2007
Где: С-Пб

Репутация: 19
Всего: 36



не разбирался с самими формулами, но так
Код

((Pl.A*cosa + Pl.B*cosb + Pl.C*cosg)!=0)

сравнивать вещественные числа нельзя, точного значения "0" никогда (почти) не будет
заведи некую маленькую дельту, вычитай её из абсолютного значения левой части, проверяй, меньше ли 0 результат
PM MAIL ICQ   Вверх
BoomeR
Дата 17.6.2008, 17:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 79
Регистрация: 24.12.2006
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Dennnis, 
p2 = -50 -50 50 или -50 -50 -50
а p1 = 83 -73 0


mihryak, 

спасибо щас попробую
PM MAIL WWW ICQ Skype   Вверх
BoomeR
Дата 20.6.2008, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 79
Регистрация: 24.12.2006
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Ошибку так и не выявил. Есть ещё идеи?
PM MAIL WWW ICQ Skype   Вверх
Zakonnic
Дата 20.6.2008, 16:26 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 161
Регистрация: 25.4.2006

Репутация: 2
Всего: 6



Цитата(BoomeR @  20.6.2008,  11:29 Найти цитируемый пост)
Ошибку так и не выявил. Есть ещё идеи?
Телепатия это хорошо и встроенный в мозг дебаггер - тоже. Но если бы прилагался бы текст эксепшена, а в коде были комментарии, то понять, что не так, было бы гораздо проще.

На первый взгляд здесь может быть только DivideByZeroException:
Код

cosa = (p2.XY.X - p1.XY.X)/M;
cosb = (p2.XY.Y - p1.XY.Y)/M;
cosg = (p2.Z-p1.Z)/M;
t = (Pl.A*p1.XY.X + Pl.B*p1.XY.Y + Pl.C*p1.Z + Pl.D)/(Pl.A*cosa + Pl.B*cosb + Pl.C*cosg);

Нулем могут быть переменная M и выражение (Pl.A*cosa + Pl.B*cosb + Pl.C*cosg). Тупой и злобный способ - завернуть все в трай/кеч:
Код

        try
        {
            M = Math.Sqrt((p2.XY.X-p1.XY.X)*(p2.XY.X-p1.XY.X)+(p2.XY.Y-p1.XY.Y)*(p2.XY.Y-p1.XY.Y)+(p2.Z-p1.Z)*(p2.Z-p1.Z));
            cosa = (p2.XY.X - p1.XY.X)/M;
            cosb = (p2.XY.Y - p1.XY.Y)/M;
            cosg = (p2.Z-p1.Z)/M;
            t = (Pl.A*p1.XY.X + Pl.B*p1.XY.Y + Pl.C*p1.Z + Pl.D)/(Pl.A*cosa + Pl.B*cosb + Pl.C*cosg);

            Cross.XY.X = (float)(p1.XY.X - t*cosa);
            Cross.XY.Y = (float)(p1.XY.Y - t*cosb);
            Cross.Z    = (float)(p1.Z - t*cosg);
        }
        catch {Cross.XY.X=0;Cross.XY.Y=0;Cross.Z=0;}
Можно и напрямую нули отлавливать, как уже здесь было предложено.
--------------------
...и никогда не пишите в комментариях правду
PM MAIL ICQ   Вверх
Dennnis
Дата 20.6.2008, 20:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 145
Регистрация: 23.3.2008

Репутация: нет
Всего: 4



У тебя  класс point немного криво реализован). 
Мне кажется сдесь ошибка переполения, потому что в случае маленького угла линии к плоскости
 координата точки пересеч. получается очень большая. Попробуй сделать новый класс point и вместо
float использовать double.
--------------------
Get Rich or Die Tryin'
PM   Вверх
marcusmae
Дата 21.6.2008, 02:27 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 22
Всего: 39



BoomeR, во-первых, это - пять баллов :

Код

        public struct point 
        {
            public    PointF XY;
            public    float Z;
        }


smile 

Во-вторых, начать бы с этого :

Код

    /// <summary>
    /// Defines a 3d point.
    /// </summary>
    public struct Point
    {
        public double x, y, z;

        /// <summary>
        /// Get distance between two points.
        /// </summary>
        public double Distance(Point other)
        {
            double
                x = this.x - other.x,
                y = this.y - other.y,
                z = this.z - other.z;
            return Math.Sqrt(x * x + y * y + z * z);
        }

        public Point ScalarMultiply(double scalar)
        {
            return new Point(this.x * scalar, this.y * scalar, this.z * scalar);
        }

        public Point Add(Point other)
        {
            return new Point(this.x + other.x, this.y + other.y, this.z + other.z);
        }

        public Point(double x, double y, double z)
        {
            this.x = x; this.y = y; this.z = z;
        }
    }

    /// <summary>
    /// Defines a 3d line of two points.
    /// </summary>
    public struct PointLine
    {
        public Point point1, point2;
    }

    /// <summary>
    /// Defines a parametric plane.
    /// </summary>
    public struct ParametricPlane
    {
        public double a, b, c, d;
        public bool invers;

        /// <summary>
        /// Get value at the specified point.
        /// </summary>
        public double GetValue(Point point)
        {
            return this.a * point.x + this.b * point.y + this.c * point.z +
                this.d;
        }

        public Point Intersect(PointLine pointLine)
        {
            Point
                point1 = pointLine.point1,
                point2 = pointLine.point2;

            double
                distance = point1.Distance(point2);

            Point
                cosPoint = new Point(
                    (point2.x - point1.x) / distance,
                    (point2.y - point1.y) / distance,
                    (point2.z - point1.z) / distance);

            double
                point1Value = this.GetValue(point1),
                cosValue = this.GetValue(cosPoint) - this.d;

            if ((cosValue > Double.Epsilon) && (point1Value > Double.Epsilon))
                return point1.Add(cosPoint.ScalarMultiply(point1Value / cosValue));
            return new Point();
        }
    }


Хочу потестировать, но Вы выдали лишь координаты пары точек. Необходимы также коэффициенты A, B, C, D для параметрического уравнения плоскости.


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
BoomeR
Дата 21.6.2008, 07:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 79
Регистрация: 24.12.2006
Где: Санкт-Петербург

Репутация: нет
Всего: нет



marcusmae, 
Вот параметры выдающие ошибки :
p2 = (-50 -50 50) или (-50 -50 -50)
p1 = (83 -73 0)
A      0.0
B    -2100800.0    
C    252096.0    
D    546208000.0    

Могу подобрать ещё если будет нужно

З.Ы. Спасибо за помощь  smile 

PM MAIL WWW ICQ Skype   Вверх
marcusmae
Дата 21.6.2008, 09:05 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 22
Всего: 39



Ну что-то получилось, конечно :

Цитата

Result = [2422.23529411776, -477.529411764725, -879.411764705924]


- неправильно?

Код

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Intersection
{
    /// <summary>
    /// Defines a 3d point.
    /// </summary>
    public struct Point
    {
        public double x, y, z;

        /// <summary>
        /// Get distance between two points.
        /// </summary>
        public double Distance(Point other)
        {
            double
                x = this.x - other.x,
                y = this.y - other.y,
                z = this.z - other.z;
            return Math.Sqrt(x * x + y * y + z * z);
        }

        public Point ScalarMultiply(double scalar)
        {
            return new Point(this.x * scalar, this.y * scalar, this.z * scalar);
        }

        public Point Add(Point other)
        {
            return new Point(this.x + other.x, this.y + other.y, this.z + other.z);
        }

        public Point(double x, double y, double z)
        {
            this.x = x; this.y = y; this.z = z;
        }

        public override string ToString()
        {
            return String.Format("[{0}, {1}, {2}]", this.x, this.y, this.z);
        }
    }

    /// <summary>
    /// Defines a 3d line of two points.
    /// </summary>
    public struct PointLine
    {
        public Point point1, point2;

        public PointLine(Point point1, Point point2)
        {
            this.point1 = point1; this.point2 = point2;
        }
    }

    /// <summary>
    /// Defines a parametric plane.
    /// </summary>
    public struct ParametricPlane
    {
        public double a, b, c, d;

        /// <summary>
        /// Get value at the specified point.
        /// </summary>
        public double GetValue(Point point)
        {
            return this.a * point.x + this.b * point.y + this.c * point.z +
                this.d;
        }

        public Point Intersect(PointLine pointLine)
        {
            Point
                point1 = pointLine.point1,
                point2 = pointLine.point2;

            double
                distance = point1.Distance(point2);

            Point
                cosPoint = new Point(
                    (point2.x - point1.x) / distance,
                    (point2.y - point1.y) / distance,
                    (point2.z - point1.z) / distance);

            double
                point1Value = this.GetValue(point1),
                cosValue = this.GetValue(cosPoint) - this.d;

            if ((cosValue > Double.Epsilon) && (point1Value > Double.Epsilon))
                return point1.Add(cosPoint.ScalarMultiply(point1Value / cosValue));
            return new Point();
        }

        public ParametricPlane(double a, double b, double c, double d)
        {
            this.a = a; this.b = b; this.c = c; this.d = d;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Point
                point1 = new Point(-50, -50, 50), // или (-50 -50 -50)
                point2 = new Point(83, -73, 0);

            double
                a = 0.0, b = -2100800.0, c = 252096.0, d = 546208000.0;

            Point result = new ParametricPlane(a, b, c, d).Intersect(
                new PointLine(point1, point2));

            Console.WriteLine("Result = " + result);
        }
    }
}



--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
vlsaf
Дата 24.6.2008, 17:24 (ссылка)   | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 423
Регистрация: 9.5.2007

Репутация: нет
Всего: 1



Народ, откуда у вас там косинусы с синусами повылазили?
Может я, конечно, уже и забыл. Давно это было...

Возьмите книжку "аналитическая геометрия".
Там есть прямо пример, как находится точка пересечения прямой и плоскости.

Прямая задана двумя точками. Плоскость тремя или (линией и точкой), что одно...уйственно.
Матричный метод решения задачи. Без всяких косинусов. 

Это сообщение отредактировал(а) vlsaf - 24.6.2008, 17:26
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0684 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.