ADN Club > VBA

Как выборку объектов отсортировать по координате. Скажем полилинии по Z

(1/1)

anatoly53:

фотки с интернета

Задача простая, по выбранным полилиниям я строю треугольники и считаю площадь. Можно, конечно загнать в массив, обработать там, но это сложнее. Пока SelectionSet делаю руками. Утомительно это. Хотел сделать сортировку в новую выборку, тогда код уже готов.
******************************************************************************

--- Код - Visual Basic [Выбрать] ---Sub Plo4()'Посчитать площадь м/у полилиниями по 4 точкам. Или по 3м, разделив их диагональю'По 4м получается пропепеллер и пло не совсем та. Нужно вычислять перпендикуляр,....'Разделив на 2 треугольника получим более простой и точный расчет.'Главное - правильная сортировка пар горизонталей.'Предпологаем, что по Z все получится, иначе можно использовать трангуляцию.'Сортируем и обрабатываем пары. Dim elem As ObjectDim SelSet As AcadSelectionSetDim nS As IntegerDim i As Integer, j As Integer'Dim p1(0 To 3) As Double, p2 As Double  'координаты пар горизонталейDim p1 As Variant, p2 As VariantDim pp(0 To 8) As Double    'массив точек треугольникаDim S As Double, p As DoubleDim sumS As Double'Dim lin3 As Acad3DPolyline'Dim p3(0 To 5) As DoubleDim pntN(0 To 2) As DoubleDim pntK(0 To 2) As DoubleDim l3 As Acad3DPolylineDim ot3 As AcadLineOn Error Resume NextThisDrawing.SelectionSets.Item("mySS").DeleteSet SelSet = ThisDrawing.SelectionSets.Add("mySS")Set SelSet = ThisDrawing.ActiveSelectionSetOn Error GoTo 0'Set SelSet = ThisDrawing.ActiveSelectionSetnS = SelSet.Count'Пока считаем, что все полилинии. И сортировка как надо. Потом добавим массив отсортированных объектов плолилинийFor j = 0 To nS - 2i = i + 1        p1 = SelSet.Item(j).Coordinates        p2 = SelSet.Item(j + 1).CoordinatesIf Abs(p1(0) - p2(0)) > Abs(p1(0) - p2(2)) Then    pntN(0) = p2(0)    pntN(1) = p2(1)    p2(0) = p2(2)    p2(1) = p2(3)    p2(2) = pntN(0)    p2(3) = pntN(1)End If                pp(0) = p1(0)   'т1 x        pp(1) = p1(1)   'т1 y        pp(2) = SelSet.Item(j).Elevation    'т1 z                pp(3) = p1(2)   'т2 x        pp(4) = p1(3)   'т2 y        pp(5) = pp(2)   'т2 z                pp(6) = p2(0)   'т3 x        pp(7) = p2(1)   'т3 y        pp(8) = SelSet.Item(j + 1).Elevation   'т3 zIf 1 = 2 Then        Set l3 = ThisDrawing.ModelSpace.Add3DPoly(pp)        l3.color = acGreenEnd IfpntN(0) = pp(3): pntN(1) = pp(4): pntN(2) = pp(5)GoSub PerimetrsumS = sumS + S'Второй треугольник        pp(0) = p2(0)   'т1/2 x        pp(1) = p2(1)   'т2/2 y        pp(2) = SelSet.Item(j + 1).Elevation    'т1/2 z                pp(3) = p2(2)   'т2/2 x        pp(4) = p2(3)   'т2/2 y        pp(5) = pp(2)   'т2/2 z                pp(6) = p1(2)   'т3/2 x        pp(7) = p1(3)   'т3/2 y        pp(8) = SelSet.Item(j).Elevation    'т3/2 zIf 1 = 2 Then        Set l3 = ThisDrawing.ModelSpace.Add3DPoly(pp)        l3.color = acBlueEnd IfGoSub Perimetr        sumS = sumS + SIf 1 = 1 Then        pntK(0) = pp(0): pntK(1) = pp(1): pntK(2) = pp(5)        Set ot3 = ThisDrawing.ModelSpace.AddLine(pntN, pntK)        ot3.color = acCyan    End IfNextsumS = (Round(sumS, 0))MsgBox (i & " трапеций(я). Площадь =" & sumS)Exit SubPerimetr:'S = p · (p - a) · (p - b) · (p - c) p-полупериметрa = (p2(0) - pp(3)) ^ 2 + (pp(1) - pp(4)) ^ 2 + (pp(2) - pp(5)) ^ 2a = Sqr(a)b = (pp(3) - pp(6)) ^ 2 + (pp(4) - pp(7)) ^ 2 + (pp(5) - pp(8)) ^ 2b = Sqr(b)c = (pp(6) - pp(0)) ^ 2 + (pp(7) - pp(1)) ^ 2 + (pp(8) - pp(2)) ^ 2c = Sqr(c)p = (a + b + c) / 2S = p * (p - a) * (p - b) * (p - c)S = Sqr(S) ReturnEnd Sub

alz:
Мне кажется только писать саму сортировку
что то типа такого, правда на шарпе

       
--- Код - C# [Выбрать] ---//функция сортировки         private List<Polyline> SortPoint(List<Polyline> result)        {            //если есть что сортировать, минимум 2 элемента            //если нечего возвращаем полученный список            if (result.Count > 1)            {                //создаем список с отсортированными значениями                List<Polyline> sorted_coll = new List<Polyline>();                //проходим по первоначальному списку пока в нем еще есть неотсортированные элементы                while (result.Count > 0)                {                    //переменная для хранения полилинии с минимальной высотой                    Polyline lowPoly;                    //переменная для хранения минимальной высоты                    double minElev = 0;                    //проходим по всем полилиниям в переданном списке                     for (int i = 0; i < result.Count; i++)                    {                        //если полилинии в переменной еще нет то первую записываем в нее а так же ее высоту в минимальную                        if (i == 0)                        {                            lowPoly = result[i];                            minElev = result[i].Elevation;                        }                        else                        {                            //если в переменной полилинии что-то хранится то сравниваем ее отметку с текущей                            //если отметка ниже то перезаписываем минимальную полилинию и ее отметку                            if (result[i].Elevation < minElev)                            {                                lowPoly = result[i];                                minElev = result[i].Elevation ;                            }                        }                    }                    //после прохода по всем полилиниям в списке удаляем минимальную по высоте и добавляем ее в отсортированный список                    result.Remove(lowPoly );                    sorted_coll.Add(lowPoly );                }                //возвращаем отсортированный список                return sorted_coll;            }            return result;        }

Ну и как вариант вроде можно создать кортеж типа (высота , полилиния) забить их в список и просто отсортировать через линк, выглядит компактнее, но насколько это оптимально даже не знаю кортежи списки и линк вроде как в vba доступны

--- Код - C# [Выбрать] ---  private List<Polyline> SortPoint(List<Polyline> result)        {            if (result.Count > 1)            {                      //создаем список кортежей                        List<(double, Polyline)> cor = new List<(double, Polyline)>();                foreach (Polyline p in result)                {                    //добавляем  кортеж из высоты и полилинии в список                    cor.Add((p.Elevation, p));                }                //сортируем кортеж                cor = cor.OrderBy(c => c.Item1).ToList();                //заменяем элементы первоначального списка отсортированными                result.Clear();                foreach ((double, Point3d) c in cor)                {                    result.Add(c.Item2);                }                            }            return result;        }
Ну и третий вариант в голову пришел просто собрать в список отметки всех линий, отсортировать стандартной сортировкой а потом пройтись по списку и закинуть в отсортированный список полилинии соответствующие отметкам


--- Код - C# [Выбрать] ---  private List<Polyline> SortPoint(List<Polyline> result)        {            if (result.Count > 1)            {                      //создаем список с отметками                List<double> el = new List<double>();                foreach (Polyline p in result)                {                    el.Add(p.Elevation);                }                //сортируем отметки                el.Sort();                //создаем список отсортированных результатов                List<Point3d> reslist = new List<Point3d>();                //записываем в него полилинии в соответствии с отметками                foreach (double e in el)                {                    for (int i = 0; i < result.Count; i++)                    {                        if (e.Equals(result[i].Elevation))                        {                            reslist.Add(result[i]);                            result.Remove(result[i]);                            break;                        }                    }                }                return reslist;                }            return result;        }
Может кто тут из корифеев скажет что из этого эффективнее? Или свой вариант попроще покажет.

alz:
Блин, посидел покумекал, и понял что все это с линком делается вообще через одну  строчку а городил до этого ((


--- Код - C# [Выбрать] ---SelSet = SelSet.OrderBy(c => c.Elevation).ToList();

Навигация

[0] Главная страница сообщений

Перейти к полной версии