#c #line #linear-algebra #points
#c #строка #линейная алгебра #Очки
Вопрос:
Я пытаюсь выяснить, виден ли набор точек для другой точки. У меня есть геометрическая сетка и точка наблюдения (красная точка на изображении). Сетка разбита на отрезки, каждый с центром (синие стрелки). Мне нужно определить, может ли точка наблюдения видеть центр отрезков без каких-либо других отрезков, находящихся между ними.
Метод, которому я следую, пытается вычислить линию, перпендикулярную линии между точкой наблюдения и каждым из центров. Затем проецируем каждый из сегментов линии на эту линию и проверяем, находится ли центр, о котором я говорю, между начальной и конечной точками проецируемого сегмента линии. Я либо получаю все, что видно, либо невидимо для точки наблюдения.
Я использую это в качестве ссылки
Мой вопрос состоит из двух частей. Во-первых, я не могу понять, почему это не работает, а во-вторых, есть ли лучший способ сделать это?
bool projectPointOntoLine(point observation, vector<segment> segments, int currentIndex){
point currentPoint = segments[currentIndex].getCenter();
double dx = observation.getX() - currentPoint.getX();
double dy = observation.getY() - currentPoint.getY();
double m = -dy/dx;
double mm = m*m;
double newX = calculateNewX(currentPoint.getX(), currentPoint.getY(), m, mm);
double newY = calculateNewY(currentPoint.getX(), currentPoint.getY(), m, mm);
long double minDist = sqrt((currentPoint.getX() - observation.getX())*(currentPoint.getX() - observation.getX()) (currentPoint.getY() - observation.getY())*(currentPoint.getY() - observation.getY()));
bool visible = true;
for(unsigned ii = 0; ii < segments.size(); ii ){
if(ii != currentIndex){
point mid = segments[ii].getStart();
long double dist = sqrt((mid.getX() - observation.getX())*(mid.getX() - observation.getX()) (mid.getY() - observation.getY())*(mid.getY() - observation.getY()));
if(dist < minDist) {
point start = segments[ii].getStart();
point end = segments[ii].getEnd();
double newStartX = calculateNewX(start.getX(), start.getY(), m, mm);
double newStartY = calculateNewY(start.getX(), start.getY(), m, mm);
double newEndX = calculateNewX(end.getX(), end.getY(), m, mm);
double newEndY = calculateNewY(end.getX(), end.getY(), m, mm);
if ((newX >= newStartX amp;amp; newEndX >= newX)){// amp;amp; (newY >= newStartY amp;amp; newEndY >= newY)) {
visible = false;
}
else if ((newX >= newEndX amp;amp; newStartX >= newX)){//} amp;amp; (newY >= newEndY amp;amp; newStartY >= newY)) {
visible = false;
}
}
}
}
return visible;
}
double calculateNewX(double x, double y, double gradient, double gradientSquared){
return (1/(1 gradientSquared))*(x) (gradient/(1 gradientSquared))*(y);
}
double calculateNewY(double x, double y, double gradient, double gradientSquared){
return (gradient/(1 gradientSquared))*(x) (gradientSquared/(1 gradientSquared))*(y);
}
Это дает мне следующий результат:
Это только половина затенения.
Комментарии:
1. Что делать
calculateNewX
иcalculateNewY
делать? Для удобства чтения рассмотрите возможность объединения их в одну функцию, которая принимает apoint
и возвращает apoint
. Какова цельscale
? Масштабирование, похоже, учитывается при вычисленииm
.2. Извините за это. Масштабирование было, когда я пытался что-то сделать раньше. Теперь я обновил раздел кода.
Ответ №1:
По-видимому, проблема здесь:
if((newX > newStartX amp;amp; newEndX > newX) amp;amp; (newY > newStartY amp;amp; newEndY > newY)){
visible = false;
}
Вы предполагаете, что newStartX
это всегда меньше newEndX
(то же самое с Y
). Это не обязательно так. В зависимости от взаимной ориентации сегмента и линии, на которую проецируется, конечные точки могут перевернуться.
Комментарии:
1. Тогда мне просто нужно было бы добавить и дополнительно проверить,
originalStartX
меньше ли значение, чем вoriginalEndX
противном случае, поменять местами точки и сделать то же самое для координат y?