|
|
« Предыдущая тема | Следующая тема » |
Опции темы | Опции просмотра |
|
|
|||||
Направление обхода точек многоугольника, перспектива помещения(вид сверху)
Добрый день! Есть массив точек, который образует непересекающийся многоугольник. Точки даны по порядку(добавляет пользователь), т.е. первая и вторая точки образуют сторону многоугольника. Это пол помещения. Нужно нарисовать вид сверху с перспективами стен:
Это пример для прямоугольника. Рабочий код, который определяет точки со сдвигом в зависимости от высоты помещения: for (var j:uint = 0; j < length; j++) { //находим текущую, прошлую и следующую точку _currPoint = points[j]; if (j < points.length - 1) _nextPoint = points[j + 1]; else _nextPoint = points[0]; if (j == 0) _prevPoint = points[points.length - 1]; else _prevPoint = points[j - 1]; //находим отрезки, биссектрису norm1 = _currPoint.subtract(_prevPoint); norm1.normalize(1); norm2 = _currPoint.subtract(_nextPoint); norm2.normalize(1); bisectrix = norm1.add(norm2); //направление обхода cw = (_currPoint.x - _prevPoint.x) * (_nextPoint.y - _currPoint.y) - (_currPoint.y - _prevPoint.y) * (_nextPoint.x - _currPoint.x) > 0; if (!cw) bisectrix.normalize(h); else bisectrix.normalize( -h); //умножаем вектор биссектрисы на высоту стен normRatio = h / Math.abs(bisectrix.x * norm1.y - bisectrix.y * norm1.x); bisectrix.x *= normRatio; bisectrix.y *= normRatio; _pointsOffset.push(_currPoint.add(bisectrix)); } НО! Проблема 1: точки должны добавляться против часовой стрелки, если по часовой добавляешь - стены рисуются внутрь помещения и получается каламбур: Проблема 2: если точки лежат на одной прямой - неправильно определяется биссектриса(на картинке ниже верхний отрезок многоугольника состоит из двух): Буду благодарен за любую помощь как решить эти проблемы. Код родился из этой темы. Последний раз редактировалось fresh.flash; 26.03.2015 в 14:35. Причина: изменил название |
|
|||||
Регистрация: Jan 2013
Сообщений: 322
|
1. посчитать площадь полигона. если площадь положительное число - перевернуть полигон.
http://www.mathopenref.com/coordpolygonarea2.html https://github.com/deltaluca/nape/bl...omPoly.cx#L261 2. можно изначально не добавлять проблемные вершины. от них только лишний шум идет. |
|
|||||
1. можно соориентироваться по сумме всех внешних и внутренних углов
2. для соосных отрезков (не считается биссектриса в такой схеме)) просто брать перпендикуляр package { import flash.display.Graphics; import flash.display.Sprite; import flash.geom.Point; public class Main extends Sprite { public function Main():void { var a:Point = new Point(100, 200); var b:Point = new Point(200, 100); var c:Point = new Point(400, 200); var d:Point = new Point(250, 310); var e:Point = new Point(200, 300); var f:Point = new Point(150, 290); var points:Array = [a, b, c, d, e, f]; // другое направление обхода //var points:Array = [f, e, d, c, b, a]; graphics.lineStyle(0); drawPoly(graphics, points); graphics.lineStyle(0, 0xFF0000); var offsetPoints:Array = calcOffsetPoints(points, 20); drawPoly(graphics, offsetPoints); } public static function calcOffsetPoints(points:Array, distance:Number = 0):Array { var res:Array = []; var len:int = points.length; // нправление обхода var angle1:Number = 0; var angle2:Number = 0; for (var j:int = 0; j < len; j++) { var dp1:Point = points[(j + 1) % len].subtract(points[(j + 0) % len]); var dp2:Point = points[(j + 1) % len].subtract(points[(j + 2) % len]); var a1:Number = Math.atan2(dp1.y, dp1.x); var a2:Number = Math.atan2(dp2.y, dp2.x); var da1:Number = a1 - a2; var da2:Number = a2 - a1; if (da1 < 0) da1 += Math.PI * 2; if (da2 < 0) da2 += Math.PI * 2; angle1 += da1; angle2 += da2; } var winding:Boolean = angle2 - angle1 > 0; // расчет точек for (var i:int = 0; i < len; i++) { var p0:Point = points[i]; var p1:Point = points[(i + 1) % len]; var p2:Point = points[(i + 2) % len]; var norm1:Point = p0.subtract(p1); var norm2:Point = p2.subtract(p1); norm1.normalize(1); norm2.normalize(1); var bisectrix:Point = norm1.add(norm2); // соосность отрезков if (bisectrix.length == 0) { bisectrix.y = norm1.x; bisectrix.x = norm1.y; } var normRatio:Number = distance / (bisectrix.x * norm1.y - bisectrix.y * norm1.x); bisectrix.x *= normRatio; bisectrix.y *= normRatio; // учитываем направление обхода var offsetPoint:Point = winding ? p1.subtract(bisectrix) : p1.add(bisectrix); res.push(offsetPoint); } return (res); } public static function drawPoly(graphics:Graphics, points:Array):void { graphics.moveTo(points[points.length - 1].x, points[points.length - 1].y); for (var i:int = 0; i < points.length; i++) { graphics.lineTo(points[i].x, points[i].y); } } } } |
|
|||||
nubideus, спасибо огромное)) Как просто оказалось. С первым пунктом проблема разрешилась.
Не добавлять вершины не вариант, т.к. заказчику нужна такая возможность(1 стену разбивать на две, чтобы раскладывать разные плитки) silin, благодарю, у Вас, как обычно, код-эталон Всё работает и всё логически понятно. Будет возможность - закину деньгу, а то по Вашим примерам учил as3 и забыл поблагодарить)) Последний раз редактировалось fresh.flash; 26.03.2015 в 17:13. |
Часовой пояс GMT +4, время: 15:58. |
|
« Предыдущая тема | Следующая тема » |
Теги |
AS3 , вектор , многоугольник , точка |
|
|