Тема: Как найти координаты вершин прямоугольника по координатам его диагонали и углу?

хочу рисовать прямоугольник при помощи мауса по дум точкам (диогональ), и через угол показывать линию, на которой лежит одно ребро. Вот только не помню геометрию как, просчитать еще две вершины ;) может кто подкинет код :)

Re: Как найти координаты вершин прямоугольника по координатам его диагонали и углу?

Sub aa()
Dim pACD As AcadDocument
Dim pRect As New TRectangle
Dim pAngle As Double
Dim pT1, pT2
    Set pACD = ThisDrawing
    pAngle = Pi * 30 / 180
    PrintMessage vbCrLf & "Пусть будет угол " & 30 & " градусов."
    PrintMessage vbCrLf & "Первая точка "
    pT1 = pACD.Utility.GetPoint
    PrintMessage vbCrLf & "Вторая точка "
    pT2 = pACD.Utility.GetPoint(pT1)
    pRect.InitTTA pT1, pT2, pAngle
    pRect.CreateLWPolyLine pACD.ModelSpace
End Sub

Класс TRectangle

'Class TRectangle
Option Explicit
Private mTS(1) As Double, mTE(1) As Double
Private mT(3, 1) As Double
Private Angle As Double, hw As Double, L As Double
Private mTmin(1) As Double, mTmax(1) As Double
Public Sub InitSEW(Tstart, Tend, Width As Double)
Dim pT As Variant
    mTS(0) = Tstart(0): mTS(1) = Tstart(1)
    mTE(0) = Tend(0): mTE(1) = Tend(1)
    Angle = AngleFromXAxis(mTS, mTE)
    hw = Width / 2
    pT = PolarPoint(mTS, Angle - Pi_2, hw)
    mT(0, 0) = pT(0): mT(0, 1) = pT(1)
    pT = PolarPoint(mTE, Angle - Pi_2, hw)
    mT(1, 0) = pT(0): mT(1, 1) = pT(1)
    pT = PolarPoint(mTE, Angle + Pi_2, hw)
    mT(2, 0) = pT(0): mT(2, 1) = pT(1)
    pT = PolarPoint(mTS, Angle + Pi_2, hw)
    mT(3, 0) = pT(0): mT(3, 1) = pT(1)
    SearchMinMaxMultyCol mT, 0, mTmin(0), mTmax(0)
    SearchMinMaxMultyCol mT, 1, mTmin(1), mTmax(1)
End Sub
Public Sub InitTTA(TLeftBottom, TRightTop, Angle As Double)
Dim pT(1) As Double, L As Double, m As Double, d As Double
Dim t1(1) As Double, t2(1) As Double, t3(1) As Double, t4(1) As Double
    PolarPoint TLeftBottom, Angle, 100, pT
    L = pT(0) - TLeftBottom(0): m = pT(1) - TLeftBottom(1)
    d = -(m * (TRightTop(0) - TLeftBottom(0)) _
        - L * (TRightTop(1) - TLeftBottom(1))) _
        / Sqr(L * L + m * m)
    If d < 0 Then
        PolarPoint TLeftBottom, Angle + Pi_2, d, t1
        t4(0) = TLeftBottom(0): t4(1) = TLeftBottom(1)
        PolarPoint TRightTop, Angle - Pi_2, d, t3
        t2(0) = TRightTop(0): t2(1) = TRightTop(1)
    Else
        PolarPoint TLeftBottom, Angle + Pi_2, d, t4
        t1(0) = TLeftBottom(0): t1(1) = TLeftBottom(1)
        PolarPoint TRightTop, Angle - Pi_2, d, t2
        t3(0) = TRightTop(0): t3(1) = TRightTop(1)
    End If
    mT(0, 0) = t1(0): mT(0, 1) = t1(1)
    mT(1, 0) = t2(0): mT(1, 1) = t2(1)
    mT(2, 0) = t3(0): mT(2, 1) = t3(1)
    mT(3, 0) = t4(0): mT(3, 1) = t4(1)
    mTS(0) = (t1(0) + t4(0)) / 2: mTS(1) = (t1(1) + t4(1)) / 2
    mTE(0) = (t2(0) + t3(0)) / 2: mTE(1) = (t2(1) + t3(1)) / 2
    SearchMinMaxMultyCol mT, 0, mTmin(0), mTmax(0)
    SearchMinMaxMultyCol mT, 1, mTmin(1), mTmax(1)
    hw = Distance(t2, t3) / 2
    L = Distance(t1, t2)
End Sub
Public Sub GetBoundingBox(TMin, TMax, Optional DX, Optional DY)
    TMin = mTmin: TMax = mTmax
    If Not IsMissing(DX) Then DX = mTmax(0) - mTmin(0)
    If Not IsMissing(DY) Then DY = mTmax(1) - mTmin(1)
End Sub
Public Function CreateLWPolyLine(acBlock As AcadBlock, Optional CenterLine As Boolean = False) As AcadLWPolyline
Dim pLWP As AcadLWPolyline
Dim pVrtx() As Double
Dim W As Double
    If CenterLine Then
        ReDim pVrtx(0 To 3)
        pVrtx(0) = mTS(0): pVrtx(1) = mTS(1): pVrtx(2) = mTE(0): pVrtx(3) = mTE(1)
        Set pLWP = acBlock.AddLightWeightPolyline(pVrtx)
        W = 2 * hw
        pLWP.SetWidth 0, W, W
    Else
        ReDim pVrtx(0 To 7)
        pVrtx(0) = mT(0, 0): pVrtx(1) = mT(0, 1): pVrtx(2) = mT(1, 0): pVrtx(3) = mT(1, 1)
        pVrtx(4) = mT(2, 0): pVrtx(5) = mT(2, 1): pVrtx(6) = mT(3, 0): pVrtx(7) = mT(3, 1)
        Set pLWP = acBlock.AddLightWeightPolyline(pVrtx)
        pLWP.Closed = True
    End If
    Set CreateLWPolyLine = pLWP
End Function
Public Property Get startPoint() As Variant
    startPoint = mTS
End Property
'Public Property Let StartPoint(ByVal vNewValue As Variant)
'End Property
Public Property Get endPoint() As Variant
    endPoint = mTE
End Property
'Public Property Let EndPoint(ByVal vNewValue As Variant)
'End Property
Public Function BorderPoint(Index As Long) As Variant
    BorderPoint = Array(mT(Index, 0), mT(Index, 1))
End Function
Public Property Get HalfWidth() As Double
    HalfWidth = hw
End Property
'Public Property Let HalfWidth(ByVal vNewValue As Variant)
'End Property

Используемые процедуры:

Public Const Pi = 3.14159265358979
Public Const Pi2 = 6.28318530717959
Public Const Pi_2 = 1.5707963267949
Public Const Pi_3 = 4.71238898038469
Public Const Pi_4 = 0.785398163397448
Public Const Sin_Pi_4 = 0.707106781186548
Public Const Tan_Pi_8 = 0.414213562373095
Public Sub SearchMinMaxMultyCol(ByRef ArrayOfNumbers, ncol As Long, _
            ByRef MinVal, ByRef MaxVal)
Dim i As Long, n1 As Long, n2 As Long
    n1 = LBound(ArrayOfNumbers, 1): n2 = UBound(ArrayOfNumbers, 1)
    MinVal = ArrayOfNumbers(n1, ncol): MaxVal = ArrayOfNumbers(n2, ncol)
    For i = n1 + 1 To n2
        If MinVal > ArrayOfNumbers(i, ncol) Then MinVal = ArrayOfNumbers(i, ncol)
        If MaxVal < ArrayOfNumbers(i, ncol) Then MaxVal = ArrayOfNumbers(i, ncol)
    Next i
End Sub
Public Function PolarPoint(ByVal t0 As Variant, ByVal ang As Double, _
            ByVal Dist As Double, Optional Result) As Variant
Dim pVal(2) As Double
    pVal(0) = t0(0) + Cos(ang) * Dist
    pVal(1) = t0(1) + Sin(ang) * Dist
    pVal(2) = 0
    PolarPoint = pVal
    If Not IsMissing(Result) Then
        Result(0) = pVal(0)
        Result(1) = pVal(1)
    End If
End Function
Public Function AngleFromXAxis(t0 As Variant, t1 As Variant)
Dim x As Double, y As Double
    x = t1(0) - t0(0): y = t1(1) - t0(1)
    If x >= Abs(y) Then
        AngleFromXAxis = Atn(y / x)
    ElseIf -x >= Abs(y) Then
        AngleFromXAxis = Pi + Atn(y / x)
    ElseIf y >= Abs(x) Then
        AngleFromXAxis = Pi_2 + Atn(-x / y)
    Else
        AngleFromXAxis = Pi_3 + Atn(-x / y)
    End If
End Function

Класс TRectangle можно инициализировать двумя способами: так как ты спрашиваешь - две диагональные точки и угол, или - две противоположные точки и ширина. После этого построить прямоугольник. Построить можно либо контур, либо полилинию с ненулевой шириной сегмента.

Re: Как найти координаты вершин прямоугольника по координатам его диагонали и углу?

Спасибо, в данном вводятся те данные которыми я не обладаю. Я придумал другой ввод прямоугольника. Я не ввожу угол вообще т.к. у меня прямоугольник т.е. 90. Исходные данные диагональ, и угол который нужен для того чтоб показать, что на нем именно лежит одна из сторон.
А вот как построить прямоугольник. диагональ это диаметр окружности, угол это косательная, ее пересечение с окружностью и соединение с другой стороной диаметра и дает угол 90градусов, а для того чтоб найти вторую вершину есть еще несколько вариантов. Осталось настрочить :) вот не знаю как узнать координату пересечения. окружности с косательной.
р.s. колизия насчет того, что все равно 90градусов не получится т.к. окружность это набор прямых. не особо важна.

Re: Как найти координаты вершин прямоугольника по координатам его диагонали и углу?

> SmeL
В Cad 2006 команда rectangle уже делает всё что нужно.
Ну а если не устраивает,
то Пифагор Вам поможет: угол известен, гипотенуза тоже.

Re: Как найти координаты вершин прямоугольника по координатам его диагонали и углу?

> Shogun
Угол то как раз и не известен, т.е. он известен относительно оси а не относительно диагонали. Так что Ваш метод не подходит. Конечно можно угол пересчитать, но это другой путь который не короче моего, описанного выше.
Конечно при одном условии, если есть возможность в AutoCAD -е (Как) узнать координату пересечения окружности и линии. Либо найти координату точки на линии.

Re: Как найти координаты вершин прямоугольника по координатам его диагонали и углу?

Новый вопрос -- новая тема: Как найти координату пересечения линии и окружности?.
/Администратор./

Re: Как найти координаты вершин прямоугольника по координатам его диагонали и углу?

> SmeL
По моему легче чем построение прямоугольника (при условии что дана диагональ) через правильный треугольник ещё никто не придумал.
Как бы там не было, для построения прямоугольника нужны как минимум две велечины:
диагональ и угол или диагональ и одна из сторон.
Вы же пишете "Я не ввожу угол вообще т.к. у меня прямоугольник т.е. 90" и тут же "Исходные данные диагональ, и угол который нужен для того чтоб показать, что на нем именно лежит одна из сторон."
И ещё, касательная не может пересекать окружность, на то она и касательная. И если касательная проходит через одну из конечных точек диагонали, тогда она перпендикулярна этой диагонале.
Надеюсь я Вас ничем не обидел. Просто не совсем понятно какие данные Вы собираетесь вводить для построения фигуры. Ваши действия по пунктам, если можно.
P.S. Вариант JS-а очень неплох.

Re: Как найти координаты вершин прямоугольника по координатам его диагонали и углу?

> Shogun
Все делаю маусом!
1. два клика (запоминаем координаты) они являются противоположными вершинами нашего прямоуголиника.
2. на основе второй координаты делаем вот что
retAngle = ThisDrawing.Utility.GetAngle(Pnt2).
все все данные для построения прямоугольника введены.
___________
Теперь начинается геометрия.
данные действия проделывает уже VBA
1. На основе двух координат (введенных выше) чертим окружность, таким образом чтоб они образовали диаметр.
2. На основе угла ведем прямую от Pnt2, которая пересекет нашу окружность. (Ваша заметка, что касательная не пересекает окружность принимается но точка соприкосновения существует ;) я так написал чтоб проще было объяснить)
3. Узнаем координату пересечения окружности и построенной прямой. Теперь у нас есть три вершины, которые образуют прямоугольный трейгольник!
4. Для того как найти четвертую вершину есть несколько вариантов.
___________
Вот весь алгоритм ;)
Вариант JS не плох но у меня другие данные вводятся.

Re: Как найти координаты вершин прямоугольника по координатам его диагонали и углу?

> SmeL
По пунктам:
1. Вы фиксируете положение прямоугольника "двумя кликами", т.е вращять прямоугольник после этого не собираетесь.
Верно?
2. Получили угол, без вопросов.
Геометрия:
1. Без вопросов.
2. Прямые, также как полилинии, лучи и Х-линии строятся по точкам, а не по углу. Но не в этом суть, применим PolarPoint(Point, Angle, Distance) и найдем Pnt3 нужную для построения прямой, а ещё лучше луча который должен будет пересечь окружность. Только вот никакого пересечения может и не быть!
Для наглядности округлимся до 1-ого градуса.
Так вот:
1. Если угол между диагональю и лучом в пределах 1-89 градусов, то пересечение состоится.
2. При угле в 0 или 90, Ваша диагональ становится одной из сторон.
3. Угл свыше 90 делает пересечение невозможным.

> SmeL
Не помню себя в 7-ом классе, но даже визуально (логически) формула подходит для определения точек из центра окружности, а не из точки касательной.

Re: Как найти координаты вершин прямоугольника по координатам его диагонали и углу?

Shogun пишет:

Вы фиксируете положение прямоугольника "двумя кликами", т.е вращять прямоугольник после этого не собираетесь.

Нет, но было бы не плохо до 3 клика перересовывать прямоугольник, т.е пока двигается маус меняются длины сторон, но это пока только в мечтах.
Крнечно стоящее описание колизии на счет угла равному 0 or 90, но не сомневайтесь я это учел бы и так.

... но даже визуально (логически) формула подходит для определения точек из центра окружности, а не из точки касательной.

Пока только такие формулы, т.е. я думаю пересчитать данные таким образом, чтоб привести задачу к данному виду :) Может кто то имеет формулы по лучше не стесняйтесь поделитесь.

Re: Как найти координаты вершин прямоугольника по координатам его диагонали и углу?

Я может и не оригинален но, по-моему, надо открыть любой вузовский учебник математики и посмотреть раздел "Аналитическая геометрия" и по формулам все решать, без всяких построений
1 По имеющемуся углу и точке находите уравнение одной из сторон
в общем виде выглядит это уравнение так
У=КнХ+Ув
где Кн=tg(угла),
       Ув-координата У той точки от которой откладывался угол(здесь от точки В)
2 По имеющемуся уравнению и точке(А) нахожу уравнение прямой перпендикулярной заданной и проходящей через заданную точку
в общем виде это уравнение выглядит так
У-Уа=(-1/Кн)*(Х-Ха)
3 имея 2 уравнения  решаю их через систему и получаю точку пересечения сторон прямоугольника, т.е. получаю 3 вершину.
4 нахожу уравнение прямой проходящей через точку В и параллельной найденной в п.3
У-Ув=(-1/Кн)*(Х-Хв)
5 нахожу уравнение прямой параллельной найденной в п.2 и проходящей  через точку А
У-Уа=Кн(Х-Ха)
6 Решая систему из уравнений пунктов 5 и 6 получаю координаты еще одной вершины
вот собственно и все. Опускаю все выкладки и причесывания. Привел только теорию.
Все преобразования в уравнениях на уровне 5 класса

Re: Как найти координаты вершин прямоугольника по координатам его диагонали и углу?

ИзвИзвиняюсь в пунктах 4 и 5 забыл поправить ссылки, там соответственно
4 - найденной в п.2
5 - найденной в п.1
и забыл вставить условие задачки
ДАно: А(Ха,Уа); В(Хв,Ув); Угол