1 {
2 *****************************************************************************
3 *                                                                           *
4 *  This file is part of the ZCAD                                            *
5 *                                                                           *
6 *  See the file COPYING.modifiedLGPL.txt, included in this distribution,    *
7 *  for details about the copyright.                                         *
8 *                                                                           *
9 *  This program is distributed in the hope that it will be useful,          *
10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                     *
12 *                                                                           *
13 *****************************************************************************
14 }
15 {
16 @author(Vladimir Bobrov)
17 }
18 {$mode objfpc}
19 
20 unit uzvtreedevice;
21 {$INCLUDE def.inc}
22 
23 interface
24 uses
25 
26    sysutils, math,
27 
28   URecordDescriptor,TypeDescriptors,
29 
30   Forms, //uzcfblockinsert,
31    uzcfarrayinsert,
32 
33   uzeentblockinsert,      //unit describes blockinsert entity
34                        //модуль описывающий примитив вставка блока
35   uzeentline,             //unit describes line entity
36                        //модуль описывающий примитив линия
37   uzeentmtext,
38 
39   uzeentlwpolyline,             //unit describes line entity
40                        //модуль описывающий примитив двухмерная ПОЛИлиния
41 
42   uzeentpolyline,             //unit describes line entity
43                        //модуль описывающий примитив трехмерная ПОЛИлиния
44   uzeenttext,             //unit describes line entity
45                        //модуль описывающий примитив текст
46 
47   uzeentdimaligned, //unit describes aligned dimensional entity
48                        //модуль описывающий выровненный размерный примитив
49   uzeentdimrotated,
50 
51   uzeentdimdiametric,
52 
53   uzeentdimradial,
54   uzeentarc,
55   uzeentcircle,
56   uzeentity,
57   uzbgeomtypes,
58 
59 
60   gvector,garrayutils, // Подключение Generics и модуля для работы с ним
61   uzcstrconsts,
62   uzcentcable,
63   uzeentdevice,
64   UGDBOpenArrayOfPV,
65 
66   uzegeometry,
67   uzeentitiesmanager,
68 
69   uzcshared,
70   uzeentityfactory,    //unit describing a "factory" to create primitives
71                       //модуль описывающий "фабрику" для создания примитивов
72   uzcsysvars,        //system global variables
73                       //системные переменные
74   uzgldrawcontext,
75   uzcinterface,
76   uzbtypesbase,uzbtypes, //base types
77                       //описания базовых типов
78   uzeconsts, //base constants
79                       //описания базовых констант
80   uzccommandsmanager,
81   uzccommandsabstract,
82   uzccommandsimpl, //Commands manager and related objects
83                       //менеджер команд и объекты связанные с ним
84   uzcdrawing,
85   uzedrawingsimple,
86   uzcdrawings,     //Drawings manager, all open drawings are processed him
87                       //"Менеджер" чертежей
88   uzcutils,         //different functions simplify the creation entities, while there are very few
89                       //разные функции упрощающие создание примитивов, пока их там очень мало
90   varmandef,
91   Varman,
92   {UGDBOpenArrayOfUCommands,}zcchangeundocommand,
93 
94   uzclog,                //log system
95                       //<**система логирования
96   uzcvariablesutils, // для работы с ртти
97 
98    gzctnrvectortypes,                  //itrec
99 
100   //для работы графа
101   ExtType,
102   Pointerv,
103   Graphs,
104   AttrType,
105   AttrSet,
106   //*
107 
108    uzcenitiesvariablesextender,
109    UUnitManager,
110    uzbpaths,
111    uzctranslations,
112   uzventsuperline,
113   uzvcom,
114   uzvtmasterdev,
115   uzvvisualgraph,
116   uzvconsts,
117   uzvtestdraw;
118 
119 
120 type
121  TDummyComparer=class
Comparenull122  function Compare (Edge1, Edge2: Pointer): Integer;
CompareEdgesnull123  function CompareEdges (Edge1, Edge2: Pointer): Integer;
124  end;
125  TSortTreeLengthComparer=class
Comparenull126  function Compare (vertex1, vertex2: Pointer): Integer;
127  end;
128 
129 
130 
131  procedure errorSearchList(ourGraph:TGraphBuilder;Epsilon:double;var listError:TListError;listSLname:TGDBlistSLname);
132  procedure errorList(allGraph:TListAllGraph;Epsilon:double;var listError:TListError;listSLname,listAllSLname:TGDBlistSLname);
133 
134  procedure visualMasterGroupLine(listVertexEdge:TGraphBuilder;listMasterDevice:TVectorOfMasterDevice;isMetricNumeric:boolean;heightText:double;numDevice:boolean);
135  procedure visualGraphConnection(GGraph:TGraphBuilder;listMasterDevice:TVectorOfMasterDevice;graphFull,graphEasy:boolean;var fTreeVertex:GDBVertex;var eTreeVertex:GDBVertex);
136 
137  procedure cabelingMasterGroupLine(listVertexEdge:TGraphBuilder;listMasterDevice:TVectorOfMasterDevice;isMetricNumeric:boolean);
buildListAllConnectDevicenull138  function buildListAllConnectDevice(listVertexEdge:TGraphBuilder;Epsilon:double; var listError:TListError):TVectorOfMasterDevice;
139 
buildListAllConnectDeviceNewnull140  function buildListAllConnectDeviceNew(listVertexEdge:TGraphBuilder;Epsilon:double; var listError:TListError):TVectorOfMasterDevice;
141 
142 implementation
143 var
144   DummyComparer:TDummyComparer;
145   SortTreeLengthComparer:TSortTreeLengthComparer;
146 
147 
148 
149 //** Поиск номера по имени устройства из списка из списка устройства
getNumHeadDevicenull150     function getNumHeadDevice(listVertex:TListDeviceLine;name:string;G: TGraph;numDev:integer):integer;
151     var
152        i: Integer;
153        pvd:pvardesk; //для работы со свойствами устройств
154        T: Float;
155        EdgePath, VertexPath: TClassList;
156     begin
157          result:=-1;
158          for i:=0 to listVertex.Size-1 do
159             begin
160                if listVertex[i].deviceEnt<>nil then
161                begin
162                    pvd:=FindVariableInEnt(listVertex[i].deviceEnt,'NMO_Name');
163                    if pvd <> nil then
164                    if pgdbstring(pvd^.data.Instance)^ = name then begin
165                       //result:=-1;
166 
167                       //работа с библиотекой Аграф
168                       EdgePath:=TClassList.Create;     //Создаем реберный путь
169                       VertexPath:=TClassList.Create;   //Создаем вершиный путь
170 
171                       // Получение ребер минимального пути в графи из одной точки в другую
172                       T:=G.FindMinWeightPath(G[i], G[numDev], EdgePath);
173                       // Получение вершин минимального пути в графи на основе минимального пути в ребер, указывается из какой точки старт
174                       G.EdgePathToVertexPath(G[i], EdgePath, VertexPath);
175 
176                       if VertexPath.Count > 1 then
177                         result:= i;
178 
179                       EdgePath.Free;
180                       VertexPath.Free;
181                    end;
182                end;
183 
184             end;
185     end;
186 
187 
getListMasterDevnull188 function getListMasterDev(listVertexEdge:TGraphBuilder;globalGraph: TGraph):TVectorOfMasterDevice;
189   type
190       //**список для кабельной прокладки
191       PTCableLaying=^TCableLaying;
192        TCableLaying=record
193            headName:string;
194            GroupNum:string;
195            typeSLine:string;
196 
197       end;
198       TVertexofCableLaying=specialize TVector<TCableLaying>;
199 
200       TVertexofString=specialize TVector<string>;
201   var
202   /////////////////////////
203 
204   listCableLaying:TVertexofCableLaying; //список кабельной прокладки
205 
206   masterDevInfo:TMasterDevice;
207   groupInfo:TMasterDevice.TGroupInfo;
208   infoSubDev:TMasterDevice.TGroupInfo.TInfoSubDev;
209   //deviceInfo:TMasterDevice.TGroupInfo.TDeviceInfo;
210   i,j,k,m,counter,tnum: Integer;
211   numHead,numHeadGroup,numHeadDev : integer;
212 
213   isHeadnum:boolean;
214   shortNameHead, headDevName, groupName:string;
215   pvd:pvardesk; //для работы со свойствами устройств
216 
217     //** Получаем количество кабелей подключения данного устройства к головным устройствам, с последующим разбором
listCollectConnectnull218     function listCollectConnect(nowDev:PGDBObjDevice;var listCableLaying:TVertexofCableLaying;nameSL:string):boolean;
219     var
220        pvd:pvardesk; //для работы со свойствами устройств
221        polyObj:PGDBObjPolyLine;
222        i,counter1,counter2,counter3:integer;
223        tempName,nameParam:gdbstring;
224        infoLay:TCableLaying;
225        listStr1,listStr2,listStr3:TVertexofString;
226 
227     begin
228          listStr1:=TVertexofString.Create;
229          listStr2:=TVertexofString.Create;
230          listStr3:=TVertexofString.Create;
231 
232          pvd:=FindVariableInEnt(nowDev,'SLCABAGEN_HeadDeviceName');
233          if pvd<>nil then
234             BEGIN
235          tempName:=pgdbstring(pvd^.data.Instance)^;
236          repeat
237                GetPartOfPath(nameParam,tempName,';');
238                listStr1.PushBack(nameParam);
239               // HistoryOutStr(' code2 = ' + nameParam);
240          until tempName='';
241 
242          pvd:=FindVariableInEnt(nowDev,'SLCABAGEN_NGHeadDevice');
243                    if pvd<>nil then
244             BEGIN
245          tempName:=pgdbstring(pvd^.data.Instance)^;
246          repeat
247                GetPartOfPath(nameParam,tempName,';');
248                listStr2.PushBack(nameParam);
249          until tempName='';
250 
251          pvd:=FindVariableInEnt(nowDev,'SLCABAGEN_SLTypeagen');
252               if pvd<>nil then
253             BEGIN
254          tempName:=pgdbstring(pvd^.data.Instance)^;
255          repeat
256                GetPartOfPath(nameParam,tempName,';');
257                listStr3.PushBack(nameParam);
258          until tempName='';
259 
260          for i:=0 to listStr1.size-1 do
261              begin
262              infoLay.headName:=listStr1[i];
263              infoLay.GroupNum:=listStr2[i];
264              infoLay.typeSLine:=listStr3[i];
265              if infoLay.typeSLine = nameSL then
266                 listCableLaying.PushBack(infoLay);
267              end;
268             end;
269             end;
270 
271          end;
272          if listCableLaying.size > 0 then
273             result:=true
274             else
275             result:=false;
276     end;
277 
278 
279   begin
280     result:=TVectorOfMasterDevice.Create;
281     listCableLaying := TVertexofCableLaying.Create;
282 
283     //counter:=0;
284 
285     //на базе listVertexEdge заполняем список головных устройств и все что в них входит
286     for i:=0 to listVertexEdge.listVertex.Size-1 do
287       begin
288          //если это устройство и не разрыв
289          if (listVertexEdge.listVertex[i].deviceEnt<>nil) and (listVertexEdge.listVertex[i].break<>true) then
290          begin
291              //Получаем список сколько у устройства хозяев
292              if listCollectConnect(listVertexEdge.listVertex[i].deviceEnt,listCableLaying,listVertexEdge.nameSuperLine) then
293              begin
294                //inc(counter);
295                for m:=0 to listCableLaying.size-1 do begin
296 
297                  headDevName:=listCableLaying[m].headName;
298                  //Поиск хозяина внутри графа полученного из listVertexEdge и возврат номера устройства
299                  numHeadDev:=getNumHeadDevice(listVertexEdge.listVertex,headDevName,globalGraph,i); // если минус значит нету хозяина
300 
301                  if numHeadDev >= 0 then
302                    begin
303                    //**Проверяем существует ли хоть одно главное устройство с таким именем,
304                    //если нет то создаем, если есть то или добавляем к существующему или создаем еще одно устройство
305                     numHead := -1;
306                     for j:=0 to result.Size-1 do    //проверяем существует ли уже такое же головное устройство
307                        if result[j].name = headDevName then begin
308                              numHead := j;
309 
310                              //ZCMsgCallBackInterface.TextMessage('NAMENUMmaster = '+inttostr(numHead) + 'namemaster = ' + headDevName + ' = ' + result[j].name,TMWOHistoryOut);
311                              isHeadnum:=true;
312                              //устройства иногда могут использоватся на разных планах и иметь подчиненных
313                              //при обработке всех планов одно и тоже устройство может иметь несколько номеров в глобальном графе
314                              for tnum in result[j].LIndex do  begin
315                                  //ZCMsgCallBackInterface.TextMessage('tnum = '+inttostr(tnum) + 'numHeadDev = ' + headDevName + ' = ' + inttostr(numHeadDev),TMWOHistoryOut);
316                                  if tnum = numHeadDev then
317                                     isHeadnum:=false;
318                                  end;
319                              if isHeadnum then
320                                result.mutable[j]^.LIndex.PushBack(numHeadDev);
321                        end;
322 
323                     if numHead < 0 then        // если в списки устройства есть. Но нашего устройства нет, то добавляем его
324                        begin
325                              masterDevInfo:=TMasterDevice.Create;
326                              masterDevInfo.name:=headDevName;
327                              masterDevInfo.LIndex.PushBack(numHeadDev);
328                              masterDevInfo.shortName:='nil';
329                              pvd:=FindVariableInEnt(listVertexEdge.listVertex[numHeadDev].deviceEnt,'NMO_Suffix');
330                              if pvd<>nil then
331                                    masterDevInfo.shortName:=pgdbstring(pvd^.data.Instance)^;
332                              result.PushBack(masterDevInfo);
333                              numHead:=result.Size-1;
334                              masterDevInfo:=nil;
335                        end;
336 
337                    //**работа по поиску и заполнению групп к головному устройству
338                        groupName:=listCableLaying[m].GroupNum;
339                        numHeadGroup:=-1;
340                        for j:=0 to result[numHead].LGroup.Size-1 do       // ищем среди существующих групп нашу
341                           if result[numHead].LGroup[j].name = groupName then
342                              numHeadGroup:=j;
343                        if  numHeadGroup<0 then                    //если нет то создаем новую группу в существующий список групп
344                          begin
345                            groupInfo:=TMasterDevice.TGroupInfo.Create;
346                            groupInfo.name:=groupName;
347                            infoSubDev.indexMaster:=numHeadDev;
348                            infoSubDev.indexSub:=i;
349                            infoSubDev.isVertexAdded:=false;
350                             //ZCMsgCallBackInterface.TextMessage('master = '+inttostr(infoSubDev.indexMaster)+' sub - ' + inttostr(infoSubDev.indexSub),TMWOHistoryOut);
351 
352                            groupInfo.LNumSubDevice.PushBack(infoSubDev);
353                            //HeadGroupInfo.listVertexTerminalBox:=nil;
354                            //HeadGroupInfo.listVertexWayGroup:=nil;
355                            //HeadGroupInfo.listVertexWayOnlyVertex:=nil;
356                            result.Mutable[numHead]^.LGroup.PushBack(groupInfo);
357                            numHeadGroup:=result[numHead].LGroup.Size-1;
358                            groupInfo:=nil;
359                          end
360                        else
361                        begin
362                            infoSubDev.indexMaster:=numHeadDev;
363                            infoSubDev.indexSub:=i;
364                            //ZCMsgCallBackInterface.TextMessage('master = '+inttostr(infoSubDev.indexMaster)+' sub - ' + inttostr(infoSubDev.indexSub),TMWOHistoryOut);
365                            infoSubDev.isVertexAdded:=false;
366                            result.mutable[numHead]^.LGroup.mutable[numHeadGroup]^.LNumSubDevice.PushBack(infoSubDev);
367                        end;
368                    end;
369 
370                end;
371                listCableLaying.Clear;
372             end;
373           end;
374         end;
375   end;
376 
Comparenull377 function TSortTreeLengthComparer.Compare (vertex1, vertex2: Pointer): Integer;
378 var
379   e1,e2:TAttrSet;
380 begin
381    result:=0;
382    e1:=TAttrSet(vertex1);
383    e2:=TAttrSet(vertex2);
384 
385        //Edge1
386    //ZCMsgCallBackInterface.TextMessage(floattostr(e1.AsFloat64[vGLengthFromEnd]) + ' сравниваем ' + floattostr(e2.AsFloat64[vGLengthFromEnd]),TMWOHistoryOut);
387    //   ZCMsgCallBackInterface.TextMessage(floattostr(e2.AsFloat32[vGLength]) + '   ',TMWOHistoryOut);
388 
389    //e1.GetAsFloat32
390    if e1.AsFloat64[vGLengthFromEnd] <> e2.AsFloat64[vGLengthFromEnd] then
391      if e1.AsFloat64[vGLengthFromEnd] > e2.AsFloat64[vGLengthFromEnd] then
392         result:=1
393      else
394         result:=-1;
395 
396    //тут e1 и e2 надо както сравнить по какомуто критерию и вернуть -1 0 1
397    //в зависимости что чего меньше-больше
398 end;
399 
400 
401 //** Создание деревьев устройств
402   procedure getEasyTreeDevice(var listMasterDevice:TVectorOfMasterDevice);
403   var
404      i,j,k,l:integer;
405      VertexPath: TClassList;
406      VPath: TClassList;
407      infoGTree:TGraph;
408      tempVertexGraph:TVertex;
409      edgeLen:float;
410      edgeWay:string;
411      nextvert:boolean;
412 
413      // получения вершины в графе на основе вершины из другого графа
getLocalVertnull414      function getLocalVert(gTree:TGraph;vt:tvertex):tVertex;
415      var
416        i:integer;
417      begin
418        result:=nil;
419         for i:=0 to gTree.VertexCount-1 do
420           if gTree.Vertices[i].AsInt32[vGGIndex] = vt.AsInt32[vGGIndex] then
421              result:=gTree.Vertices[i];
422      end;
423 
424   begin
425       for i:=0 to listMasterDevice.Size-1 do
426       begin
427          for j:=0 to listMasterDevice[i].LGroup.Size -1 do
428             begin
429               for k:=0 to listMasterDevice[i].LGroup[j].LTreeDev.Size -1 do begin
430                 infoGTree:=TGraph.Create;
431                 infoGTree.Features:=[Tree];
432                 infoGTree.CreateVertexAttr(vGGIndex, AttrInt32);
433                 infoGTree.CreateEdgeAttr(vGLength, AttrFloat64);
434                 infoGTree.CreateVertexAttr(vGIsDevice, AttrBool);
435                 infoGTree.CreateEdgeAttr(vGInfoEdge, AttrString);
436                 infoGTree.CreateVertexAttr(vGInfoVertex, AttrString);
437 
438                 //**получаем обход графа
439                 VPath:=TClassList.Create;
440                 listMasterDevice.mutable[i]^.LGroup.mutable[j]^.LTreeDev.mutable[k]^.TreeTraversal(tvertex(listMasterDevice[i].LGroup[j].LTreeDev[k].Root), VPath); //получаем путь обхода графа
441 
442                 //** создаем граф в котором будут только устройства и ответвления
443                 tempVertexGraph:=nil;
444 
445                 infoGTree.AddVertex;
446                 infoGTree.Root:=infoGTree.Vertices[infoGTree.VertexCount-1];
447                 infoGTree.Vertices[infoGTree.VertexCount-1].AsInt32[vGGIndex]:=tvertex(VPath[0]).AsInt32[vGGIndex];
448                 infoGTree.Vertices[infoGTree.VertexCount-1].AsString[vGInfoVertex]:=tvertex(VPath[0]).AsString[vGInfoVertex];
449                 infoGTree.Vertices[infoGTree.VertexCount-1].AsBool[vGIsDevice]:=tvertex(VPath[0]).AsBool[vGIsDevice];
450                 tempVertexGraph:=infoGTree.Vertices[infoGTree.VertexCount-1];
451                 edgeLen:=0;
452                 edgeWay:='';
453                 nextvert:=false;
454                 for l:= 1 to VPath.Count - 1 do
455                  begin
456                    //**организция изменения родительской вершины tempVertexGraph если обход графа начался после ответвления
457                      if nextvert then
458                      begin
459                         nextvert:=false;
460                         tempVertexGraph:=getLocalVert(infoGTree,tvertex(VPath[l]).Parent);
461                      end;
462                      if (tvertex(VPath[l]).ChildCount < 1) then
463                        begin
464                          nextvert:=true;
465                        end;
466                     ///
467 
468                    if (tvertex(VPath[l]).ChildCount > 1) or tvertex(VPath[l]).AsBool[vGIsDevice] then begin
469                       infoGTree.AddVertex;
470                       infoGTree.Vertices[infoGTree.VertexCount-1].AsInt32[vGGIndex]:=tvertex(VPath[l]).AsInt32[vGGIndex];
471                       infoGTree.Vertices[infoGTree.VertexCount-1].AsBool[vGIsDevice]:=tvertex(VPath[l]).AsBool[vGIsDevice];
472 
473                       //**НОВОЕ!!! Добавил ссылку на устройство
474                       infoGTree.Vertices[infoGTree.VertexCount-1].AsPointer[vGPGDBObjDevice]:=tvertex(VPath[l]).AsPointer[vGPGDBObjDevice];
475 
476                       infoGTree.Vertices[infoGTree.VertexCount-1].AsString[vGInfoVertex]:=tvertex(VPath[l]).AsString[vGInfoVertex];
477 
478                       //if infoGTree.Vertices[infoGTree.VertexCount-1].AsPointer[vGPGDBObjDevice] <> nil then
479                          //infoGTree.Vertices[infoGTree.VertexCount-1].AsString[vGInfoVertex]:= '+' + infoGTree.Vertices[infoGTree.VertexCount-1].AsString[vGInfoVertex]
480                       //else
481                          infoGTree.Vertices[infoGTree.VertexCount-1].AsString[vGInfoVertex]:= '-' + infoGTree.Vertices[infoGTree.VertexCount-1].AsString[vGInfoVertex];
482 
483                       edgeLen+=listMasterDevice[i].LGroup[j].LTreeDev[k].GetEdge(tvertex(VPath[l]),tvertex(VPath[l]).Parent).AsFloat64[vGLength];
484 
485                       edgeLen:=RoundTo(edgeLen,-1);
486                       infoGTree.AddEdge(tempVertexGraph,infoGTree.Vertices[infoGTree.VertexCount-1]);
487 
488                       //**НОВОЕ!!! Добавил ссылку на устройство
489                       infoGTree.Edges[infoGTree.EdgeCount-1].AsPointer[vGPGDBObjSuperLine]:=listMasterDevice[i].LGroup[j].LTreeDev[k].GetEdge(tvertex(VPath[l]),tvertex(VPath[l]).Parent).AsPointer[vGPGDBObjSuperLine];
490 
491                       infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat64[vGLength]:=edgeLen;
492                       //if infoGTree.Edges[infoGTree.EdgeCount-1].AsPointer[vGPGDBObjSuperLine] <> nil then
493                         //infoGTree.Edges[infoGTree.EdgeCount-1].AsString[vGInfoEdge]:='+way: '+ edgeWay + '\P L=' + floattostr(edgeLen)+'m'
494                       //else
495                         infoGTree.Edges[infoGTree.EdgeCount-1].AsString[vGInfoEdge]:='-way: '+ edgeWay + '\P L=' + floattostr(edgeLen)+'m';
496 
497                       edgeLen:=0;
498                       edgeWay:='';
499                       tempVertexGraph:=infoGTree.Vertices[infoGTree.VertexCount-1];
500                    end
501                    else
502                    begin
503                      edgeWay+='-';
504                      edgeWay+=inttostr(tvertex(VPath[l]).AsInt32[vGGIndex]);
505                      //edgeWay+='-';
506 
507                      edgeLen+=listMasterDevice[i].LGroup[j].LTreeDev[k].GetEdge(tvertex(VPath[l]),tvertex(VPath[l]).Parent).AsFloat64[vGLength];
508                      edgeLen:=RoundTo(edgeLen,-1);
509                    end;
510 
511                    //if
512                   //    //listMasterDevice[i].LGroup[j].LTreeDev[k].GetEdge(VPath[l]);
513                   //ZCMsgCallBackInterface.TextMessage(' vertex = ' + inttostr(tvertex(VPath[l]).AsInt32[vGGIndex]),TMWOHistoryOut);
514                   //ZCMsgCallBackInterface.TextMessage(' vertex childercount = ' + inttostr(tvertex(VPath[l]).ChildCount),TMWOHistoryOut);
515                   //ZCMsgCallBackInterface.TextMessage(' edge length = ' + floattostr(listMasterDevice[i].LGroup[j].LTreeDev[k].GetEdge(tvertex(VPath[l]),tvertex(VPath[l]).Parent).AsFloat64[vGLength]),TMWOHistoryOut);
516 
517                   //ZCMsgCallBackInterface.TextMessage(' vertex = ' + inttostr(listMasterDevice[i].LGroup[j].LTreeDev[k].Vertices[tvertex(VPath[l]).Index].AsInt32[vGGIndex]),TMWOHistoryOut);
518                   //if listMasterDevice[i].LGroup[j].LTreeDev[k].Vertices[Tvertex(VertexPath[l]).Index].ChildCount<1 then
519 
520                  end;
521 
522                 //for l:= 0 to infoGTree.VertexCount - 1 do
523                 // begin
524                 //    ZCMsgCallBackInterface.TextMessage('вершинffffff - ' + inttostr(infoGTree.Vertices[l].Index),TMWOHistoryOut);
525                 // end;
526                 //for l:= 0 to infoGTree.EdgeCount - 1 do
527                 // begin
528                 //    ZCMsgCallBackInterface.TextMessage('реброооffffff - ' + inttostr(infoGTree.edges[l].V1.Index)+'---'+inttostr(infoGTree.edges[l].V2.Index),TMWOHistoryOut);
529                 // end;
530                 //ZCMsgCallBackInterface.TextMessage('col vertex = ' + inttostr(listMasterDevice[i].LGroup[j].LTreeDev[k].VertexCount),TMWOHistoryOut);
531                 //ZCMsgCallBackInterface.TextMessage(inttostr(listMasterDevice[i].LGroup[j].LTreeDev[k].Root.Index),TMWOHistoryOut);
532                //visualGraph(listMasterDevice[i].LGroup[j].LTreeDev[k],gg,1);
533 
534               // ZCMsgCallBackInterface.TextMessage('Количство ребер - ' + inttostr(infoGTree.EdgeCount),TMWOHistoryOut);
535               //ZCMsgCallBackInterface.TextMessage('Количство вершин - ' + inttostr(infoGTree.VertexCount),TMWOHistoryOut);
536 
537               infoGTree.CorrectTree;
538 
539               listMasterDevice.mutable[i]^.LGroup.mutable[j]^.LEasyTreeDev.PushBack(infoGTree);
540               infoGTree:=nil;
541               tempVertexGraph:=nil;
542                end;
543             end;
544 
545       end;
546   end;
547 
548 //  //** Добавляет пункт к ребрам графа длина с начала (от головного устройства)
549 //  procedure addItemLengthFromBegin(var listMasterDevice:TVectorOfMasterDevice);
550 //  var
551 //     i,j,k,l:integer;
552 //
553 //     VPath: TClassList;
554 //
555 //     edgeLength,edgeLengthParent:float;
556 //
557 //
558 //  begin
559 //      for i:=0 to listMasterDevice.Size-1 do
560 //      begin
561 //         for j:=0 to listMasterDevice[i].LGroup.Size -1 do
562 //            begin
563 //              for k:=0 to listMasterDevice[i].LGroup[j].LTreeDev.Size -1 do begin
564 //
565 //                listMasterDevice.mutable[i]^.LGroup.mutable[j]^.LTreeDev.mutable[k]^.CreateEdgeAttr('lengthfrombegin', AttrFloat32);
566 //
567 //                //**получаем обход графа
568 //                VPath:=TClassList.Create;
569 //                listMasterDevice.mutable[i]^.LGroup.mutable[j]^.LTreeDev.mutable[k]^.TreeTraversal(tvertex(listMasterDevice[i].LGroup[j].LTreeDev[k].Root), VPath); //получаем путь обхода графа
570 //
571 //
572 //                for l:= 1 to VPath.Count - 1 do
573 //                 begin
574 //
575 //                     if tvertex(VPath[l]).Parent.Parent = nil then
576 //                       edgeLengthParent:=0
577 //                     else
578 //                       edgeLengthParent:=listMasterDevice.mutable[i]^.LGroup.mutable[j]^.LTreeDev.mutable[k]^.GetEdge(tvertex(VPath[l]).Parent,tvertex(VPath[l]).Parent.Parent).AsFloat32['lengthfrombegin'];
579 //
580 //                       edgeLength:=listMasterDevice.mutable[i]^.LGroup.mutable[j]^.LTreeDev.mutable[k]^.GetEdge(tvertex(VPath[l]),tvertex(VPath[l]).Parent).AsFloat32[vGLength];
581 //                       listMasterDevice.mutable[i]^.LGroup.mutable[j]^.LTreeDev.mutable[k]^.GetEdge(tvertex(VPath[l]),tvertex(VPath[l]).Parent).AsFloat32['lengthfrombegin']:=edgeLength+edgeLengthParent;
582 ////
583 ////                       listMasterDevice.mutable[i]^.LGroup.mutable[j]^.LTreeDev.mutable[k]^.GetEdge(tvertex(VPath[l]),tvertex(VPath[l]).Parent).AsString[vGInfoEdge]:='ddd = '+floattostr(listMasterDevice.mutable[i]^.LGroup.mutable[j]^.LTreeDev.mutable[k]^.GetEdge(tvertex(VPath[l]),tvertex(VPath[l]).Parent).AsFloat32['lengthfrombegin']);
584 //                 end;
585 //               end;
586 //            end;
587 //
588 //      end;
589 //  end;
590 
591 procedure visualGraphConnection(GGraph:TGraphBuilder;listMasterDevice:TVectorOfMasterDevice;graphFull,graphEasy:boolean;var fTreeVertex:GDBVertex;var eTreeVertex:GDBVertex);
592 var
593     globalGraph: TGraph;
594     //sumWeightPath: Float;
595     easyListMasterDevice:TVectorOfMasterDevice;
596 
597     i,j,k: Integer;
598     //l,m,tnum: Integer;
599     //counter,counter2,counterColor:integer; //счетчики
600 
601     //listAllTree:tvectorofGraph;
602     inVertex:GDBVertex;
603 
604   begin
605     //визуализация номеров точек на плане для совмещения их с деревом
606     if graphFull or graphEasy then
607        visualPtNameSL(GGraph,0.8);
608     //Построение полного дерева
609     if graphFull then begin
610          for i:=0 to listMasterDevice.Size-1 do
611          begin
612            for j:=0 to listMasterDevice[i].LGroup.Size -1 do
613               begin
614                 for k:=0 to listMasterDevice[i].LGroup[j].LTreeDev.Size -1 do begin
615                   visualGraph(GGraph,listMasterDevice[i].LGroup[j].LTreeDev[k],fTreeVertex,1);
616                   end;
617               end;
618 
619          end;
620     end;
621     //Построение полного урезанного дерева, места поворотов кабелей не показаны
622     if graphEasy then begin
623       getEasyTreeDevice(listMasterDevice);
624 
625          for i:=0 to listMasterDevice.Size-1 do
626          begin
627            for j:=0 to listMasterDevice[i].LGroup.Size -1 do
628               begin
629                 for k:=0 to listMasterDevice[i].LGroup[j].LEasyTreeDev.Size -1 do begin
630                   visualGraph(GGraph,listMasterDevice[i].LGroup[j].LEasyTreeDev[k],eTreeVertex,1);
631                   end;
632               end;
633             end;
634 
635     end;
636 
637 
638 
639   end;
640 
641 
642   //Визуализация построения шлейфов головных устройств с целью визуального изучения того как будут прокладываться кабельные линии
643 //дабы исключить возмоные программные ошибки
644 procedure visualMasterGroupLine(listVertexEdge:TGraphBuilder;listMasterDevice:TVectorOfMasterDevice;isMetricNumeric:boolean;heightText:double;numDevice:boolean);
645 type
646        counterGroupDevice=record
647            name:string;
648            counter:Integer;
649        end;
650 
651        TCounterGroupDevice=specialize TVector<counterGroupDevice>;
652        TVectorofInteger=specialize TVector<integer>;
653 var
654   globalGraph: TGraph;
655   i,j,k,l:integer;
656 
657      VPath: TClassList;
658 
659      edgeLength,edgeLengthParent:float;
660 
661 
662     polyObj:PGDBObjPolyLine;
663     //i,j,counter:integer;
664     mtext:string;
665     notVertex:boolean;
666     pvdHeadDevice,pvdHDGroup:pvardesk; //для работы со свойствами устройств
667 
668 
669     colorNum,numberGDev:integer;
670     listCounterGroupDevice:TCounterGroupDevice;
671     listInteger:TVectorofInteger;
672     needParent:boolean;
673     nowDevCounter:counterGroupDevice;
674 
675 //    добавляем в список новое устройство из метрики и получаем устройство
addGetCounterGroupDevicenull676     function addGetCounterGroupDevice(num:integer):counterGroupDevice ;
677     var
678     i,counter:integer;
679     name:string;
680     pvd:pvardesk; //для работы со свойствами устройств
681     //devCounter:counterGroupDevice;
682     begin
683       name:='';
684       if isMetricNumeric then
685         begin
686          pvd:=FindVariableInEnt(listVertexEdge.listVertex[num].deviceEnt,'NMO_BaseName');
687          if pvd <> nil then
688             name:=pgdbstring(pvd^.data.Instance)^
689         end;
690      if listCounterGroupDevice.size = 0 then
691        begin
692           result.name:=name;
693           result.counter:=1;
694           listCounterGroupDevice.PushBack(result);
695        end
696      else
697        begin
698          counter:=-1;
699          for i:=0 to listCounterGroupDevice.size-1 do
700              if listCounterGroupDevice[i].name = name then
701                counter:=i;
702          if counter<0 then
703            begin
704               result.name:=name;
705               result.counter:=1;
706               listCounterGroupDevice.PushBack(result);
707            end
708          else
709            begin
710            inc(listCounterGroupDevice.mutable[counter]^.counter);
711            result.name:=listCounterGroupDevice[counter].name;
712            result.counter:=listCounterGroupDevice[counter].counter;
713          end;
714        end;
715     end;
716 
717     //Визуализация текста его p1-координата, mText-текст, color-цвет, размер
visualDrawTextnull718     function visualDrawText(p1:GDBVertex;mText:GDBString;color:integer;heightText:double):TCommandResult;
719     var
720         ptext:PGDBObjText;
721     begin
722           ptext := GDBObjText.CreateInstance;
723           zcSetEntPropFromCurrentDrawingProp(ptext); //добавляем дефаултные свойства
724           ptext^.TXTStyleIndex:=drawings.GetCurrentDWG^.GetCurrentTextStyle; //добавляет тип стиля текста, дефаултные свойства его не добавляют
725           ptext^.Local.P_insert:=p1;  // координата
726           ptext^.Template:=mText;     // сам текст
727           ptext^.vp.LineWeight:=LnWt100;
728           ptext^.vp.Color:=color;
729           ptext^.vp.Layer:=uzvtestdraw.getTestLayer(vTempLayerName);
730           ptext^.textprop.size:=heightText;
731           zcAddEntToCurrentDrawingWithUndo(ptext);   //добавляем в чертеж
732           result:=cmd_ok;
733     end;
734 
735     //Визуализация круга его p1-координата, rr-радиус, color-цвет
visualDrawCirclenull736     function visualDrawCircle(p1:GDBVertex;rr:GDBDouble;color:integer):TCommandResult;
737     var
738         pcircle:PGDBObjCircle;
739     begin
740         begin
741           pcircle := AllocEnt(GDBCircleID);                                             //выделяем память
742           pcircle^.init(nil,nil,0,p1,rr);                                             //инициализируем и сразу создаем
743 
744           zcSetEntPropFromCurrentDrawingProp(pcircle);                                        //присваиваем текущие слой, вес и т.п
745           pcircle^.vp.LineWeight:=LnWt100;
746           pcircle^.vp.Color:=color;
747           pcircle^.vp.Layer:=uzvtestdraw.getTestLayer(vTempLayerName);
748           zcAddEntToCurrentDrawingWithUndo(pcircle);                                    //добавляем в чертеж
749         end;
750         result:=cmd_ok;
751     end;
visualDrawPolyLinenull752     function visualDrawPolyLine(listInteger:TVectorofInteger;color:Integer):TCommandResult;
753     var
754         polyObj:PGDBObjPolyLine;
755         i:integer;
756     begin
757          polyObj:=GDBObjPolyline.CreateInstance;
758          zcSetEntPropFromCurrentDrawingProp(polyObj);
759          polyObj^.Closed:=false;
760          polyObj^.vp.Color:=color;
761          polyObj^.vp.LineWeight:=LnWt200;
762          polyObj^.vp.Layer:=getTestLayer(vTempLayerName);
763 
764          for i:=0 to listInteger.size-1 do
765           begin
766             polyObj^.VertexArrayInOCS.PushBackData(listVertexEdge.listVertex[listInteger[i]].centerPoint);
767           end;
768 
769          zcAddEntToCurrentDrawingWithUndo(polyObj);
770          result:=cmd_ok;
771     end;
772 
773 begin
774 
775     //heightText:=2.5;
776 
777       //Создаем граф на основе класса TGraphBuilder полученого при обработке устройств и суперлиний
778     globalGraph:=TGraph.Create;
779     globalGraph.Features:=[Weighted];
780     globalGraph.AddVertices(listVertexEdge.listVertex.Size);
781     for i:=0 to listVertexEdge.listEdge.Size-1 do
782     begin
783       globalGraph.AddEdges([listVertexEdge.listEdge[i].VIndex1, listVertexEdge.listEdge[i].VIndex2]);
784       globalGraph.Edges[i].Weight:=listVertexEdge.listEdge[i].edgeLength;
785     end;
786 
787     colorNum:=1;
788      for i:=0 to listMasterDevice.Size-1 do
789          for j:=0 to listMasterDevice[i].LGroup.Size -1 do
790          begin
791               if colorNum=6 then
792                  colorNum:=1;
793 
794               listCounterGroupDevice:=TCounterGroupDevice.Create;
795 
796               for k:=0 to listMasterDevice[i].LGroup[j].LTreeDev.Size -1 do
797                begin
798 
799                 //**получаем обход графа
800                 VPath:=TClassList.Create;
801                 listMasterDevice.mutable[i]^.LGroup.mutable[j]^.LTreeDev.mutable[k]^.TreeTraversal(tvertex(listMasterDevice[i].LGroup[j].LTreeDev[k].Root), VPath); //получаем путь обхода графа
802 
803                 listInteger:=TVectorofInteger.Create;
804 
805                 needParent:=false;
806                 for l:= 0 to VPath.Count - 1 do
807                  begin
808 
809                   if (l <> 0) and tvertex(VPath[l]).AsBool[vGIsDevice] then
810                     begin
811                        numberGDev:=tvertex(VPath[l]).AsInt32[vGGIndex];
812                        if not listVertexEdge.listVertex[numberGDev].break then begin
813                          nowDevCounter:= addGetCounterGroupDevice(numberGDev);
814                          if numDevice then
815                             visualDrawText(listVertexEdge.listVertex[numberGDev].centerPoint,listMasterDevice[i].name+'-'+listMasterDevice[i].LGroup[j].name+'-'+nowDevCounter.name+'-'+inttostr(nowDevCounter.counter),colorNum,heightText);
816                          visualDrawCircle(listVertexEdge.listVertex[numberGDev].centerPoint,5,colorNum);
817                        end;
818                     end;
819 
820                    if needParent then  begin
821                      listInteger.PushBack(tvertex(VPath[l]).Parent.AsInt32[vGGIndex]);
822                    end;
823 
824                    listInteger.PushBack(tvertex(VPath[l]).AsInt32[vGGIndex]);
825 
826                    if listInteger.Size > 1 then
827                    if (tvertex(VPath[l]).ChildCount > 1) or (tvertex(VPath[l]).ChildCount = 0) or tvertex(VPath[l]).AsBool[vGIsDevice] then
828                      begin
829                         visualDrawPolyLine(listInteger,colorNum);
830                         listInteger:=TVectorofInteger.Create;
831 
832                         needParent:=true;
833                         //ZCMsgCallBackInterface.TextMessage('numvertex'+inttostr(tvertex(VPath[l]).AsInt32[vGGIndex])+'  Количство дтей - ' + inttostr(tvertex(VPath[l]).ChildCount),TMWOHistoryOut);
834                      end;
835 
836                   end;
837                end;
838               inc(colorNum);
839          end;
840 end;
841 
842 
843 
844 
845 procedure cabelingMasterGroupLine(listVertexEdge:TGraphBuilder;listMasterDevice:TVectorOfMasterDevice;isMetricNumeric:boolean);
846 type
847        counterGroupDevice=record
848            name:string;
849            counter:Integer;
850        end;
851 
852        TCounterGroupDevice=specialize TVector<counterGroupDevice>;
853        TVectorofInteger=specialize TVector<integer>;
854 var
855   globalGraph: TGraph;
856   i,j,k,l,counterSegment:integer;
857 
858      VPath: TClassList;
859 
860      edgeLength,edgeLengthParent:float;
861 
862 
863     polyObj:PGDBObjPolyLine;
864     //i,j,counter:integer;
865     mtext:string;
866     notVertex:boolean;
867     pvdHeadDevice,pvdHDGroup:pvardesk; //для работы со свойствами устройств
868     //myVertex,vertexAnalized:TListVertexWayOnlyVertex;
869     //myTerminalBox:TListVertexTerminalBox;
870 
871     heightText:double;
872     colorNum,numberGDev:integer;
873     listCounterGroupDevice:TCounterGroupDevice;
874     listInteger:TVectorofInteger;
875     needParent:boolean;
876     nowDevCounter:counterGroupDevice;
877 
878 
879     //Метрирование датчиков
880     procedure metricNumeric(dev:PGDBObjDevice);
881     var
882         pvd:pvardesk;
883         name:string;
884     begin
885         name:='';
886         if isMetricNumeric then begin
887          pvd:=FindVariableInEnt(dev,'NMO_BaseName');
888          if pvd<>nil then
889            name:=pgdbstring(pvd^.data.Instance)^;
890          end;
891 
892          pvd:=FindVariableInEnt(dev,'GC_InGroup_Metric');
893            if pvd<>nil then
894                pgdbstring(pvd^.data.Instance)^:=name ;
895     end;
896 
897     procedure drawCableLine(listInteger:TVectorofInteger;numLMaster,numLGroup,counterSegment:Integer);
898     var
899     cableLine:PGDBObjCable;
900     i:integer;
901     pvd:pvardesk; //для работы со свойствами устройств
902     psu:ptunit;
903     pvarext:PTVariablesExtender;
904 
905     begin
906      cableLine := AllocEnt(GDBCableID);
907      cableLine^.init(nil,nil,0);
908      zcSetEntPropFromCurrentDrawingProp(cableLine);
909 
910      for i:=0 to listInteger.Size-1 do
911          cableLine^.VertexArrayInOCS.PushBackData(listVertexEdge.listVertex[listInteger[i]].centerPoint);
912 
913      //**добавление кабельных свойств
914       pvarext:=cableLine^.GetExtension(typeof(TVariablesExtender)); //подклчаемся к инспектору
915       if pvarext<>nil then
916       begin
917         psu:=units.findunit(SupportPath,@InterfaceTranslate,'cable'); //
918         if psu<>nil then
919           pvarext^.entityunit.copyfrom(psu);
920       end;
921       zcSetEntPropFromCurrentDrawingProp(cableLine);
922       //***//
923 
924       //** Имя мастера устройства
925        pvd:=FindVariableInEnt(cableLine,'GC_HeadDevice');
926        if pvd<>nil then
927              pgdbstring(pvd^.data.Instance)^:=listMasterDevice[numLMaster].name;
928 
929        pvd:=FindVariableInEnt(cableLine,'GC_HDShortName');
930        if pvd<>nil then
931              pgdbstring(pvd^.data.Instance)^:=listMasterDevice[numLMaster].shortName;
932 
933       //** обавляем суффикс
934       pvd:=FindVariableInEnt(cableLine,'NMO_Suffix');
935        if pvd<>nil then
936              pgdbstring(pvd^.data.Instance)^:=listMasterDevice[numLMaster].LGroup[numLGroup].name;
937 
938        pvd:=FindVariableInEnt(cableLine,'CABLE_AutoGen');
939               if pvd<>nil then
940                     pgdbboolean(pvd^.data.Instance)^:=true;
941 
942        pvd:=FindVariableInEnt(cableLine,'GC_HDGroup');
943        if pvd<>nil then
944        pgdbstring(pvd^.data.Instance)^:=listMasterDevice[numLMaster].LGroup[numLGroup].name;
945 
946 
947       pvd:=FindVariableInEnt(cableLine,'NMO_BaseName');
948        if pvd<>nil then
949              pgdbstring(pvd^.data.Instance)^:=listMasterDevice[numLMaster].name + '-';
950 
951        pvd:=FindVariableInEnt(cableLine,'CABLE_Segment');
952        if pvd<>nil then
953           begin
954              pgdbinteger(pvd^.data.Instance)^:=counterSegment;
955           end;
956 
957 
958      zcAddEntToCurrentDrawingWithUndo(cableLine);
959      //result:=cmd_ok;
960      end;
961 
962 begin
963 
964       //Создаем граф на основе класса TGraphBuilder полученого при обработке устройств и суперлиний
965     globalGraph:=TGraph.Create;
966     globalGraph.Features:=[Weighted];
967     globalGraph.AddVertices(listVertexEdge.listVertex.Size);
968     for i:=0 to listVertexEdge.listEdge.Size-1 do
969     begin
970       globalGraph.AddEdges([listVertexEdge.listEdge[i].VIndex1, listVertexEdge.listEdge[i].VIndex2]);
971       globalGraph.Edges[i].Weight:=listVertexEdge.listEdge[i].edgeLength;
972     end;
973 
974 
975 
976     //colorNum:=1;
977      for i:=0 to listMasterDevice.Size-1 do
978          for j:=0 to listMasterDevice[i].LGroup.Size -1 do
979          begin
980 
981           for k:=0 to listMasterDevice[i].LGroup[j].LNumSubDevice.Size -1 do
982             metricNumeric(listVertexEdge.listVertex[listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexSub].deviceEnt);
983 
984            counterSegment:=0;
985               for k:=0 to listMasterDevice[i].LGroup[j].LTreeDev.Size -1 do
986                begin
987                 //**получаем обход графа
988                 VPath:=TClassList.Create;
989                 listMasterDevice.mutable[i]^.LGroup.mutable[j]^.LTreeDev.mutable[k]^.TreeTraversal(tvertex(listMasterDevice[i].LGroup[j].LTreeDev[k].Root), VPath); //получаем путь обхода графа
990 
991                 listInteger:=TVectorofInteger.Create;
992 
993                 needParent:=false;
994                 for l:= 0 to VPath.Count - 1 do
995                  begin
996                   //ZCMsgCallBackInterface.TextMessage('вершина - '+inttostr(tvertex(VPath[l]).AsInt32[vGGIndex]),TMWOHistoryOut);
997                    //Создаем список точек кабеля который передадим в отрисовку кабельной линии
998                    if needParent then begin
999                      listInteger.PushBack(tvertex(VPath[l]).Parent.AsInt32[vGGIndex]);
1000                      needParent:=false;
1001                      end;
1002 
1003                      listInteger.PushBack(tvertex(VPath[l]).AsInt32[vGGIndex]);
1004 
1005                      if listVertexEdge.listVertex[tvertex(VPath[l]).AsInt32[vGGIndex]].break and listVertexEdge.listVertex[tvertex(VPath[l]).Parent.AsInt32[vGGIndex]].break then begin
1006                        needParent:=true;
1007                        listInteger:=TVectorofInteger.Create;
1008                      end else
1009 
1010                    //ZCMsgCallBackInterface.TextMessage('длина списка - '+inttostr(listInteger.Size),TMWOHistoryOut);
1011                    if listInteger.Size > 1 then
1012                    if (tvertex(VPath[l]).ChildCount > 1) or (tvertex(VPath[l]).ChildCount = 0) or tvertex(VPath[l]).AsBool[vGIsDevice] or (listVertexEdge.listVertex[tvertex(VPath[l]).AsInt32[vGGIndex]].break and listVertexEdge.listVertex[tvertex(VPath[l]).Parent.AsInt32[vGGIndex]].break) then
1013                    //if (tvertex(VPath[l]).ChildCount > 1) or (tvertex(VPath[l]).ChildCount = 0) or (listVertexEdge.listVertex[tvertex(VPath[l]).AsInt32[vGGIndex]].break and listVertexEdge.listVertex[tvertex(VPath[l]).Parent.AsInt32[vGGIndex]].break) then
1014                      begin
1015                        //ZCMsgCallBackInterface.TextMessage('Строем кабель',TMWOHistoryOut);
1016                         drawCableLine(listInteger,i,j,counterSegment);
1017                         listInteger:=TVectorofInteger.Create;
1018                         inc(counterSegment);
1019                         needParent:=true;
1020                      end;
1021 
1022                   end;
1023                end;
1024               //inc(colorNum);
1025          end;
1026 end;
1027 
1028   //** Добавляет пункт к вершинам графа длина с Конца (от головного устройства)
1029   procedure addItemLengthFromEnd(var listMasterDevice:TVectorOfMasterDevice);
1030   var
1031      i,j,k,l:integer;
1032 
1033      VPath: TClassList;
1034 
1035      edgeLength,edgeLengthChilds:float;
1036 
1037 
1038      // получения вершины в графе на основе вершины из другого графа
getLengthChildsnull1039      function getLengthChilds(gTree:TGraph;vt:tvertex):float;
1040      var
1041        i:integer;
1042      begin
1043        result:=0;
1044        for i:=0 to vt.ChildCount-1 do
1045          result+=vt.Childs[i].AsFloat64[vGLengthFromEnd];
1046      end;
1047 
1048   begin
1049       for i:=0 to listMasterDevice.Size-1 do
1050          for j:=0 to listMasterDevice[i].LGroup.Size -1 do
1051               for k:=0 to listMasterDevice[i].LGroup[j].LTreeDev.Size -1 do
1052                begin
1053                 listMasterDevice.mutable[i]^.LGroup.mutable[j]^.LTreeDev.mutable[k]^.CreateVertexAttr(vGLengthFromEnd, AttrFloat64);
1054 
1055                 //**получаем обход графа
1056                 VPath:=TClassList.Create;
1057                 listMasterDevice.mutable[i]^.LGroup.mutable[j]^.LTreeDev.mutable[k]^.TreeTraversal(tvertex(listMasterDevice[i].LGroup[j].LTreeDev[k].Root), VPath); //получаем путь обхода графа
1058 
1059                 for l:= VPath.Count - 1 downto 1 do
1060                  begin
1061                    edgeLengthChilds:=getLengthChilds(listMasterDevice[i].LGroup[j].LTreeDev[k],tvertex(VPath[l]));
1062                    edgeLength:=listMasterDevice.mutable[i]^.LGroup.mutable[j]^.LTreeDev.mutable[k]^.GetEdge(tvertex(VPath[l]),tvertex(VPath[l]).Parent).AsFloat64[vGLength];
1063                    tvertex(VPath[l]).AsFloat64[vGLengthFromEnd]:=edgeLength+edgeLengthChilds;
1064                  end;
1065                end;
1066   end;
1067 
1068 
1069 
1070 
1071   //** Создание деревьев устройств
1072   procedure addTreeDevice(listVertexEdge:TGraphBuilder;globalGraph:TGraph;var listMasterDevice:TVectorOfMasterDevice);
1073   //type
1074     //tempuseVertex:Tvectorofinteger;
1075   var
1076      pvd:pvardesk; //для работы со свойствами устройств
1077      polyObj:PGDBObjPolyLine;
1078      i,j,k,m,n,counter1,counter2,counter3:integer;
1079      tIndex,tIndexLocal,tIndexGlobal:integer;
1080      EdgePath, VertexPath: TClassList;
1081      infoGTree:TGraph;
1082 
1083      tempString:string;
1084      sumWeightPath,tempFloat: Float;
1085      tempLVertex:TvectorOfInteger;
1086      gg:GDBVertex;
1087 
isVertexAddednull1088      function isVertexAdded(tempLVertex:tvectorofinteger;index:integer):boolean;
1089      var
1090        i:integer;
1091      begin
1092        result:=true;
1093         for i:=0 to tempLVertex.Size-1 do begin
1094             //ZCMsgCallBackInterface.TextMessage('ищем - ' + inttostr(tempLVertex[i])+' наш - ' + inttostr(index),TMWOHistoryOut);
1095             if tempLVertex[i]=index then begin
1096              result:=false;
1097              //ZCMsgCallBackInterface.TextMessage('совпало: ' + inttostr(tempLVertex[i])+' = ' + inttostr(index),TMWOHistoryOut);
1098             end;
1099         end;
1100      end;
1101 
1102 
getLengthnull1103      function getLength(listVertexEdge:TGraphBuilder;pt1,pt2:integer):Float;
1104      var
1105        i:integer;
1106      begin
1107        result:=-1;
1108         for i:=0 to listVertexEdge.listEdge.Size-1 do
1109             if ((listVertexEdge.listEdge[i].VIndex1=pt1) and (listVertexEdge.listEdge[i].VIndex2=pt2)) or
1110             ((listVertexEdge.listEdge[i].VIndex1=pt2) and (listVertexEdge.listEdge[i].VIndex2=pt1)) then
1111              result:=listVertexEdge.listEdge[i].edgeLength;
1112      end;
1113 
getvGPGDBObjSuperLinenull1114      function getvGPGDBObjSuperLine(listVertexEdge:TGraphBuilder;pt1,pt2:integer):PGDBObjSuperLine;
1115      var
1116        i:integer;
1117      begin
1118        result:=nil;
1119         for i:=0 to listVertexEdge.listEdge.Size-1 do
1120             if ((listVertexEdge.listEdge[i].VIndex1=pt1) and (listVertexEdge.listEdge[i].VIndex2=pt2)) or
1121             ((listVertexEdge.listEdge[i].VIndex1=pt2) and (listVertexEdge.listEdge[i].VIndex2=pt1)) then
1122              result:=listVertexEdge.listEdge[i].cableEnt;
1123      end;
1124 
getLocalIndexnull1125      function getLocalIndex(gTree:TGraph;indexGlobal:integer):LongInt;
1126      var
1127        i:integer;
1128      begin
1129        result:=-1;
1130         for i:=0 to gTree.VertexCount-1 do
1131           if gTree.Vertices[i].AsInt32[vGGIndex] = indexGlobal then
1132              result:=i;
1133      end;
1134 
1135     //** Есть ли соединение данного устройства с данным номером головного устройства
1136     //** суть в том что одно и тоже устройство может быть на разных планах, это нужно для избежания ошибок связей
isHaveLineMasternull1137     function isHaveLineMaster(isMaster,isSub:integer):boolean;
1138     begin
1139       //ZCMsgCallBackInterface.TextMessage('isMaster : ' + inttostr(isMaster)+' - isSub -  ' + inttostr(isSub),TMWOHistoryOut);
1140 
1141         result:=true; // нет пути между головным устройством и подключаемым
1142         EdgePath:=TClassList.Create;     //Создаем реберный путь
1143         VertexPath:=TClassList.Create;   //Создаем вершиный путь
1144         //Получение ребер минимального пути в графе из одной точки в другую
1145         sumWeightPath:=globalGraph.FindMinWeightPath(globalGraph[isMaster], globalGraph[isSub], EdgePath);
1146         //Получение вершин минимального пути в графе на основе минимального пути в ребер, указывается из какой точки старт
1147         globalGraph.EdgePathToVertexPath(globalGraph[isMaster], EdgePath, VertexPath);
1148 
1149         //Узнать существует уже граф если нет то создать его и добавляем начальную вершину
1150         if VertexPath.Count > 1 then
1151           result:=false;  //путь есть между головным устройством и подключаемым
1152 
1153     end;
1154 
1155   begin
1156     for i:=0 to listMasterDevice.Size-1 do
1157       begin
1158          for j:=0 to listMasterDevice[i].LGroup.Size -1 do
1159             begin
1160               for n:=0 to listMasterDevice[i].LIndex.Size -1 do
1161               begin
1162 
1163               //ZCMsgCallBackInterface.TextMessage('khfskldhfskdhflksdhflksdhflksdflkshd - ' + inttostr(n),TMWOHistoryOut);
1164 
1165               infoGTree:=TGraph.Create;
1166               infoGTree.Features:=[Tree];
1167               //infoGTree.Root;
1168               infoGTree.CreateVertexAttr(vGGIndex, AttrInt32);
1169               infoGTree.CreateVertexAttr(vGIsDevice, AttrBool);
1170               infoGTree.CreateVertexAttr(vGInfoVertex, AttrString);
1171 
1172               infoGTree.CreateVertexAttr(vGPGDBObjDevice,AttrPointer);  // добавили ссылку сразу на само устройство
1173 
1174               infoGTree.CreateEdgeAttr(vGLength, AttrFloat64);
1175               infoGTree.CreateEdgeAttr(vGInfoEdge, AttrString);
1176 
1177               infoGTree.CreateEdgeAttr(vGPGDBObjSuperLine,AttrPointer);  // добавили ссылку сразу на саму линию
1178 
1179               //ZCMsgCallBackInterface.TextMessage('yfx Количство ребер - ' + inttostr(infoGTree.EdgeCount),TMWOHistoryOut);
1180               //ZCMsgCallBackInterface.TextMessage('yfx Количство вершин - ' + inttostr(infoGTree.VertexCount),TMWOHistoryOut);
1181 
1182 
1183               tempLVertex:=tvectorofinteger.create;
1184                 //listMasterDevice[i].LGroup[j].LNumSubDevice;
1185               for k:=0 to listMasterDevice[i].LGroup[j].LNumSubDevice.Size-1 do
1186                 begin
1187 
1188                   if isHaveLineMaster(listMasterDevice[i].LIndex[n],listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexSub) then
1189                      continue;
1190 
1191                   EdgePath:=TClassList.Create;     //Создаем реберный путь
1192                   VertexPath:=TClassList.Create;   //Создаем вершиный путь
1193                   //Получение ребер минимального пути в графе из одной точки в другую
1194                   sumWeightPath:=globalGraph.FindMinWeightPath(globalGraph[listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexMaster], globalGraph[listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexSub], EdgePath);
1195                   //Получение вершин минимального пути в графе на основе минимального пути в ребер, указывается из какой точки старт
1196                   //ZCMsgCallBackInterface.TextMessage('master = '+inttostr(listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexMaster)+' sub - ' + inttostr(listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexSub),TMWOHistoryOut);
1197 
1198                   globalGraph.EdgePathToVertexPath(globalGraph[listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexMaster], EdgePath, VertexPath);
1199 
1200                   tIndexLocal:=-1; //промежуточная вершина для создание ребер графа
1201                   tIndexGlobal:=-1; //промежуточная вершина для построения пути глобального графа
1202 
1203                   //ZCMsgCallBackInterface.TextMessage('количество - ' + inttostr(VertexPath.Count),TMWOHistoryOut);
1204 
1205                   //Узнать существует уже граф если нет то создать его и добавляем начальную вершину
1206                   if infoGTree.VertexCount <= 0 then begin
1207                      infoGTree.AddVertex;
1208                      infoGTree.Vertices[infoGTree.VertexCount-1].AsInt32[vGGIndex]:=listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexMaster;
1209 
1210                      //Добавил ссылку на устройство
1211                      infoGTree.Vertices[infoGTree.VertexCount-1].AsPointer[vGPGDBObjDevice]:=listVertexEdge.listVertex[listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexMaster].deviceEnt;
1212 
1213                     if listVertexEdge.listVertex[listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexMaster].deviceEnt <> nil then
1214                       begin
1215                         infoGTree.Vertices[infoGTree.VertexCount-1].AsBool[vGIsDevice]:=true;
1216                         //tempString:='№';
1217                         tempString:=inttostr(infoGTree.Vertices[infoGTree.VertexCount-1].AsInt32[vGGIndex]);
1218                         tempString+='\P';
1219                         tempString+='dev';
1220                         infoGTree.Vertices[infoGTree.VertexCount-1].AsString[vGInfoVertex]:=tempString;
1221                       end
1222                     else
1223                       begin
1224                         infoGTree.Vertices[infoGTree.VertexCount-1].AsBool[vGIsDevice]:=false;
1225                         //tempString:='№';
1226                         tempString:=inttostr(infoGTree.Vertices[infoGTree.VertexCount-1].AsInt32[vGGIndex]);
1227                         tempString+='\P';
1228                         tempString+='nul';
1229                         infoGTree.Vertices[infoGTree.VertexCount-1].AsString[vGInfoVertex]:=tempString;
1230                       end;
1231                     //infoGTree.Vertices[infoGTree.VertexCount-1].AsBool['isFork']:=false;
1232 
1233                      //ZCMsgCallBackInterface.TextMessage('РУУТ - ' + inttostr(infoGTree.VertexCount-1),TMWOHistoryOut);
1234 
1235                      infoGTree.Root:=infoGTree.Vertices[infoGTree.VertexCount-1];
1236                      tempLVertex.PushBack(listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexMaster);
1237                   end;
1238 
1239                   if VertexPath.Count > 1 then
1240                     for m:=VertexPath.Count - 1 downto 0 do begin
1241                       // Добавляет цифрц ы центре каждого устройства
1242                       // uzvtestdraw.testTempDrawText(listVertexEdge.listVertex[TVertex(VertexPath[m]).Index].centerPoint,inttostr(TVertex(VertexPath[m]).Index));
1243 
1244 
1245                       //ZCMsgCallBackInterface.TextMessage('way - ' + inttostr(TVertex(VertexPath[m]).Index),TMWOHistoryOut);
1246                       if isVertexAdded(tempLVertex,TVertex(VertexPath[m]).Index) then
1247                         begin
1248                             //ZCMsgCallBackInterface.TextMessage('отработка кода ',TMWOHistoryOut);
1249 
1250                             infoGTree.AddVertex;
1251                             infoGTree.Vertices[infoGTree.VertexCount-1].AsInt32[vGGIndex]:=TVertex(VertexPath[m]).Index;
1252 
1253                             //НОВОЕ! Добавил ссылку на устройство
1254                             infoGTree.Vertices[infoGTree.VertexCount-1].AsPointer[vGPGDBObjDevice]:=listVertexEdge.listVertex[TVertex(VertexPath[m]).Index].deviceEnt;
1255 
1256 
1257                             if listVertexEdge.listVertex[TVertex(VertexPath[m]).Index].deviceEnt <> nil then
1258                             begin
1259                               infoGTree.Vertices[infoGTree.VertexCount-1].AsBool[vGIsDevice]:=true;
1260                               //tempString:='№';
1261                               tempString:=inttostr(infoGTree.Vertices[infoGTree.VertexCount-1].AsInt32[vGGIndex]);
1262                               tempString+='\P';
1263                               tempString+='dev';
1264                               infoGTree.Vertices[infoGTree.VertexCount-1].AsString[vGInfoVertex]:=tempString;
1265                             end
1266                           else
1267                             begin
1268                               infoGTree.Vertices[infoGTree.VertexCount-1].AsBool[vGIsDevice]:=false;
1269                               //tempString:='№';
1270                               tempString:=inttostr(infoGTree.Vertices[infoGTree.VertexCount-1].AsInt32[vGGIndex]);
1271                               tempString+='\P';
1272                               tempString+='nul';
1273                               infoGTree.Vertices[infoGTree.VertexCount-1].AsString[vGInfoVertex]:=tempString;
1274                             end;
1275                             //infoGTree.Vertices[infoGTree.VertexCount-1].AsBool['isFork']:=false;
1276 
1277                             tempLVertex.PushBack(TVertex(VertexPath[m]).Index);
1278 
1279                              if tIndexLocal < 0 then begin
1280                                tIndexLocal:=infoGTree.VertexCount-1;
1281                                tIndexGlobal:=TVertex(VertexPath[m]).Index;
1282                              end
1283                              else
1284                              begin
1285                               //ZCMsgCallBackInterface.TextMessage('edgeGlobal : ' + inttostr(tIndexGlobal)+' - ' + inttostr(TVertex(VertexPath[m]).index),TMWOHistoryOut);
1286                               //ZCMsgCallBackInterface.TextMessage('edgelocal : ' + inttostr(tIndexLocal)+' - ' + inttostr(infoGTree.VertexCount-1),TMWOHistoryOut);
1287                               infoGTree.AddEdge(infoGTree.Vertices[tIndexLocal],infoGTree.Vertices[infoGTree.VertexCount-1]);
1288 
1289                               //ZCMsgCallBackInterface.TextMessage('edgelength : ' + floattostr(getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index)),TMWOHistoryOut);
1290                               //tempFloat:=1*RoundTo(getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index),-1);
1291                               //tempFloat:=20;
1292                               infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat64[vGLength]:=getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index);
1293                               infoGTree.Edges[infoGTree.EdgeCount-1].AsString[vGInfoEdge]:='\\P L='+floattostr(RoundTo(infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat64[vGLength],-1))+'m';
1294                               //ZCMsgCallBackInterface.TextMessage('edgedddddlength : ' + floattostr(infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat32[vGLength]) + ' - - - ' + floattostr(tempFloat),TMWOHistoryOut);
1295 
1296 
1297                               //infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat32[vGLength]:=RoundTo(getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index),-1);
1298                               //infoGTree.Edges[infoGTree.EdgeCount-1].AsString[vGInfoEdge]:='\\P L='+floattostr(infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat32[vGLength])+'m';
1299                               //ZCMsgCallBackInterface.TextMessage('edgelength : ' + floattostr(getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index)) + ' - - - ' + floattostr(RoundTo(getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index),-1)),TMWOHistoryOut);
1300                               //ZCMsgCallBackInterface.TextMessage('edgelength : ' + floattostr(infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat32[vGLength]) + ' - округ - ' + infoGTree.Edges[infoGTree.EdgeCount-1].AsString[vGInfoEdge],TMWOHistoryOut);
1301 
1302                               tIndexLocal:=infoGTree.VertexCount-1;
1303                               tIndexGlobal:=TVertex(VertexPath[m]).Index;
1304                              end;
1305 
1306                          end
1307                       else begin
1308                         if tIndexLocal >= 0 then
1309                            begin
1310                             tIndex:=getLocalIndex(infoGTree,TVertex(VertexPath[m]).index);
1311                             //ZCMsgCallBackInterface.TextMessage('edgeGlobal : ' + inttostr(tIndexGlobal)+' - ' + inttostr(TVertex(VertexPath[m]).index),TMWOHistoryOut);
1312                             //ZCMsgCallBackInterface.TextMessage('edgelocal : ' + inttostr(tIndexLocal)+' - ' + inttostr(tIndex),TMWOHistoryOut);
1313                             infoGTree.AddEdge(infoGTree.Vertices[tIndexLocal],infoGTree.Vertices[tIndex]);
1314 
1315                             //НОВОЕ!!!! Добавил ссылку на устройство
1316                             infoGTree.Edges[infoGTree.EdgeCount-1].AsPointer[vGPGDBObjSuperLine]:=getvGPGDBObjSuperLine(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index);
1317 
1318 
1319                               //ZCMsgCallBackInterface.TextMessage('edgelength : ' + floattostr(getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index)),TMWOHistoryOut);
1320                               infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat64[vGLength]:=getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index);
1321                               infoGTree.Edges[infoGTree.EdgeCount-1].AsString[vGInfoEdge]:='\\P L='+floattostr(RoundTo(infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat64[vGLength],-1))+'m';
1322 
1323                               //ZCMsgCallBackInterface.TextMessage('edgelength : ' + floattostr(getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index)) + ' - - - ' + floattostr(RoundTo(getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index),-1)),TMWOHistoryOut);
1324                               //ZCMsgCallBackInterface.TextMessage('edgelength : ' + floattostr(infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat32[vGLength]) + ' - округ - ' + infoGTree.Edges[infoGTree.EdgeCount-1].AsString[vGInfoEdge],TMWOHistoryOut);
1325 
1326                             tIndexLocal:=-1;
1327                             tIndexGlobal:=-1;
1328                         end;
1329                       end;
1330                     end;
1331 
1332                   EdgePath.Destroy;
1333                   VertexPath.Destroy;
1334                 end;
1335 
1336               //ZCMsgCallBackInterface.TextMessage('Количство ребер - ' + inttostr(infoGTree.EdgeCount),TMWOHistoryOut);
1337               //ZCMsgCallBackInterface.TextMessage('Количство вершин - ' + inttostr(infoGTree.VertexCount),TMWOHistoryOut);
1338 
1339               // Такая проверку нужна, тогда когда бывает что головное устройство на разных планах установлено
1340               // и может возникнуть ситуация когда на плане разные группы, что вызовит пустой граф
1341               //что бы не было проблем выполнена данная проверка
1342               if infoGTree.VertexCount > 0 then begin
1343               infoGTree.CorrectTree; //Делает дерево корректным, добавляет родителей детей
1344               listMasterDevice.mutable[i]^.LGroup.mutable[j]^.LTreeDev.PushBack(infoGTree);
1345               end;
1346 
1347               infoGTree:=nil;
1348               tempLVertex.Destroy;
1349             end;
1350          end;
1351       end;
1352   end;
1353 
buildListAllConnectDevicenull1354 function buildListAllConnectDevice(listVertexEdge:TGraphBuilder;Epsilon:double; var listError:TListError):TVectorOfMasterDevice;
1355 var
1356 
1357     globalGraph: TGraph;
1358     listMasterDevice:TVectorOfMasterDevice;
1359 
1360     i,j,k: Integer;
1361 
1362     gg:GDBVertex;
1363 
1364 
1365     //** Поиск существует ли устройства с нужным именем
isHaveDevicenull1366     function isHaveDevice(listVertex:TListDeviceLine;name:string):boolean;
1367     var
1368        i: Integer;
1369        pvd:pvardesk; //для работы со свойствами устройств
1370     begin
1371          result:=true;
1372          for i:=0 to listVertex.Size-1 do
1373                if listVertex[i].deviceEnt<>nil then
1374                begin
1375                    pvd:=FindVariableInEnt(listVertex[i].deviceEnt,'NMO_Name');
1376                    if pvd <> nil then
1377                    if pgdbstring(pvd^.data.Instance)^ = name then
1378                       result:= false;
1379                end;
1380     end;
1381 
1382   begin
1383 
1384     //Создаем граф на основе класса TGraphBuilder полученого при обработке устройств и суперлиний
1385     globalGraph:=TGraph.Create;
1386     globalGraph.Features:=[Weighted];
1387     globalGraph.AddVertices(listVertexEdge.listVertex.Size);
1388     for i:=0 to listVertexEdge.listEdge.Size-1 do
1389     begin
1390       globalGraph.AddEdges([listVertexEdge.listEdge[i].VIndex1, listVertexEdge.listEdge[i].VIndex2]);
1391       globalGraph.Edges[i].Weight:=listVertexEdge.listEdge[i].edgeLength;
1392     end;
1393 
1394     //**получаем список подключенных устройств к головным устройствам
1395     listMasterDevice:=getListMasterDev(listVertexEdge,globalGraph);
1396 
1397     //for i:=0 to listMasterDevice.Size-1 do
1398     //  begin
1399     //     ZCMsgCallBackInterface.TextMessage('мастер = '+ listMasterDevice[i].name,TMWOHistoryOut);
1400     //     for j:=0 to listMasterDevice[i].LGroup.Size -1 do
1401     //        begin
1402     //          ZCMsgCallBackInterface.TextMessage('колво приборы = '+ inttostr(listMasterDevice[i].LGroup[j].LNumSubDevice.size),TMWOHistoryOut);
1403     //          for k:=0 to listMasterDevice[i].LGroup[j].LNumSubDevice.Size -1 do
1404     //            ZCMsgCallBackInterface.TextMessage('приборы = '+ inttostr(listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexSub),TMWOHistoryOut);
1405     //        end;
1406     //  end;
1407 
1408     //**Переробатываем список устройств подключенный к группам и на основе него создание деревьев усройств
1409     addTreeDevice(listVertexEdge,globalGraph,listMasterDevice);
1410 
1411     //**Переробатываем большой граф в упрощенный,для удобной визуализации
1412     //addEasyTreeDevice(globalGraph,listMasterDevice);
1413 
1414     //**Добавляем к вершинам длины кабелей с конца, для правильной сортировки дерева по длине
1415     addItemLengthFromEnd(listMasterDevice);
1416 
1417     ZCMsgCallBackInterface.TextMessage('*** Суперлиния - ' + listVertexEdge.nameSuperLine + ' - обработка выполнена! ***',TMWOHistoryOut);
1418 
1419     //visualGraph(listMasterDevice[0].LGroup[0].LTreeDev[0],gg,1) ;
1420     //gg:=uzegeometry.CreateVertex(0,0,0);
1421 
1422     //visualAllTreesLMD(listMasterDevice,gg,1);
1423 
1424     for i:=0 to listMasterDevice.Size-1 do
1425       begin
1426          for j:=0 to listMasterDevice[i].LGroup.Size -1 do
1427             begin
1428               for k:=0 to listMasterDevice[i].LGroup[j].LTreeDev.Size -1 do begin
1429                 //visualGraph(listMasterDevice[i].LGroup[j].LTreeDev[k],gg,1);
1430 
1431                 listMasterDevice.mutable[i]^.LGroup.mutable[j]^.LTreeDev.mutable[k]^.SortTree(listMasterDevice[i].LGroup[j].LTreeDev[k].Root,@SortTreeLengthComparer.Compare);
1432 
1433                 //visualGraph(listMasterDevice[i].LGroup[j].LTreeDev[k],gg,1);
1434                end;
1435             end;
1436 
1437       end;
1438 
1439       result:=listMasterDevice;
1440 
1441   end;
1442 
1443 
1444 //** Создает список головных устройств
getListMasterDevNewnull1445 function getListMasterDevNew(listVertexEdge:TGraphBuilder;globalGraph: TGraph):TVectorOfMasterDevice;
1446   type
1447       //**список для кабельной прокладки
1448       PTCableLaying=^TCableLaying;
1449        TCableLaying=record
1450            headName:string;
1451            GroupNum:string;
1452            typeSLine:string;
1453 
1454       end;
1455       TVertexofCableLaying=specialize TVector<TCableLaying>;
1456 
1457       TVertexofString=specialize TVector<string>;
1458   var
1459   /////////////////////////
1460 
1461   listCableLaying:TVertexofCableLaying; //список кабельной прокладки
1462 
1463   masterDevInfo:TMasterDevice;
1464   groupInfo:TMasterDevice.TGroupInfo;
1465   infoSubDev:TMasterDevice.TGroupInfo.TInfoSubDev;
1466   //deviceInfo:TMasterDevice.TGroupInfo.TDeviceInfo;
1467   i,j,k,m,counter,tnum: Integer;
1468   numHead,numHeadGroup,numHeadDev : integer;
1469 
1470   isHeadnum:boolean;
1471   shortNameHead, headDevName, groupName:string;
1472   pvd:pvardesk; //для работы со свойствами устройств
1473 
1474     //** Получаем количество кабелей подключения данного устройства к головным устройствам, с последующим разбором
listCollectConnectnull1475     function listCollectConnect(nowDev:PGDBObjDevice;var listCableLaying:TVertexofCableLaying;nameSL:string):boolean;
1476     var
1477        pvd:pvardesk; //для работы со свойствами устройств
1478        polyObj:PGDBObjPolyLine;
1479        i,counter1,counter2,counter3:integer;
1480        tempName,nameParam:gdbstring;
1481        infoLay:TCableLaying;
1482        listStr1,listStr2,listStr3:TVertexofString;
1483 
1484     begin
1485          listStr1:=TVertexofString.Create;
1486          listStr2:=TVertexofString.Create;
1487          listStr3:=TVertexofString.Create;
1488 
1489          pvd:=FindVariableInEnt(nowDev,'SLCABAGEN_HeadDeviceName');
1490          if pvd<>nil then
1491             BEGIN
1492          nameParam:=pgdbstring(pvd^.data.Instance)^;
1493          listStr1.PushBack(nameParam);
1494          //repeat
1495          //      GetPartOfPath(nameParam,tempName,';');
1496          //      listStr1.PushBack(nameParam);
1497          //     // HistoryOutStr(' code2 = ' + nameParam);
1498          //until tempName='';
1499 
1500          pvd:=FindVariableInEnt(nowDev,'SLCABAGEN_NGHeadDevice');
1501                    if pvd<>nil then
1502             BEGIN
1503          nameParam:=pgdbstring(pvd^.data.Instance)^;
1504          //repeat
1505          //      GetPartOfPath(nameParam,tempName,';');
1506          listStr2.PushBack(nameParam);
1507          //until tempName='';
1508 
1509          pvd:=FindVariableInEnt(nowDev,'SLCABAGEN_SLTypeagen');
1510               if pvd<>nil then
1511             BEGIN
1512          nameParam:=pgdbstring(pvd^.data.Instance)^;
1513          //repeat
1514          //      GetPartOfPath(nameParam,tempName,';');
1515                listStr3.PushBack(nameParam);
1516          //until tempName='';
1517 
1518          for i:=0 to listStr1.size-1 do
1519              begin
1520              infoLay.headName:=listStr1[i];
1521              infoLay.GroupNum:=listStr2[i];
1522              infoLay.typeSLine:=listStr3[i];
1523              if infoLay.typeSLine = nameSL then
1524                 listCableLaying.PushBack(infoLay);
1525              end;
1526             end;
1527             end;
1528 
1529          end;
1530          if listCableLaying.size > 0 then
1531             result:=true
1532             else
1533             result:=false;
1534     end;
1535 
1536 
1537   begin
1538     result:=TVectorOfMasterDevice.Create;
1539     listCableLaying := TVertexofCableLaying.Create;
1540 
1541     //counter:=0;
1542 
1543     //на базе listVertexEdge заполняем список головных устройств и все что в них входит
1544     for i:=0 to listVertexEdge.listVertex.Size-1 do
1545       begin
1546          //если это устройство и не разрыв
1547          if (listVertexEdge.listVertex[i].deviceEnt<>nil) and (listVertexEdge.listVertex[i].break<>true) then
1548          begin
1549              //Получаем список сколько у устройства хозяев
1550              if listCollectConnect(listVertexEdge.listVertex[i].deviceEnt,listCableLaying,listVertexEdge.nameSuperLine) then
1551              begin
1552                //inc(counter);
1553                for m:=0 to listCableLaying.size-1 do begin
1554 
1555                  headDevName:=listCableLaying[m].headName;
1556                  //Поиск хозяина внутри графа полученного из listVertexEdge и возврат номера устройства
1557                  numHeadDev:=getNumHeadDevice(listVertexEdge.listVertex,headDevName,globalGraph,i); // если минус значит нету хозяина
1558 
1559                  if numHeadDev >= 0 then
1560                    begin
1561                    //**Проверяем существует ли хоть одно главное устройство с таким именем,
1562                    //если нет то создаем, если есть то или добавляем к существующему или создаем еще одно устройство
1563                     numHead := -1;
1564                     for j:=0 to result.Size-1 do    //проверяем существует ли уже такое же головное устройство
1565                        if result[j].name = headDevName then begin
1566                              numHead := j;
1567 
1568                              //ZCMsgCallBackInterface.TextMessage('NAMENUMmaster = '+inttostr(numHead) + 'namemaster = ' + headDevName + ' = ' + result[j].name,TMWOHistoryOut);
1569                              isHeadnum:=true;
1570                              //устройства иногда могут использоватся на разных планах и иметь подчиненных
1571                              //при обработке всех планов одно и тоже устройство может иметь несколько номеров в глобальном графе
1572                              for tnum in result[j].LIndex do  begin
1573                                  //ZCMsgCallBackInterface.TextMessage('tnum = '+inttostr(tnum) + 'numHeadDev = ' + headDevName + ' = ' + inttostr(numHeadDev),TMWOHistoryOut);
1574                                  if tnum = numHeadDev then
1575                                     isHeadnum:=false;
1576                                  end;
1577                              if isHeadnum then
1578                                result.mutable[j]^.LIndex.PushBack(numHeadDev);
1579                        end;
1580 
1581                     if numHead < 0 then        // если в списки устройства есть. Но нашего устройства нет, то добавляем его
1582                        begin
1583                              masterDevInfo:=TMasterDevice.Create;
1584                              masterDevInfo.name:=headDevName;
1585                              masterDevInfo.LIndex.PushBack(numHeadDev);
1586                              masterDevInfo.shortName:='nil';
1587                              pvd:=FindVariableInEnt(listVertexEdge.listVertex[numHeadDev].deviceEnt,'NMO_Suffix');
1588                              if pvd<>nil then
1589                                    masterDevInfo.shortName:=pgdbstring(pvd^.data.Instance)^;
1590                              result.PushBack(masterDevInfo);
1591                              numHead:=result.Size-1;
1592                              masterDevInfo:=nil;
1593                        end;
1594 
1595                    //**работа по поиску и заполнению групп к головному устройству
1596                        groupName:=listCableLaying[m].GroupNum;
1597                        numHeadGroup:=-1;
1598                        for j:=0 to result[numHead].LGroup.Size-1 do       // ищем среди существующих групп нашу
1599                           if result[numHead].LGroup[j].name = groupName then
1600                              numHeadGroup:=j;
1601                        if  numHeadGroup<0 then                    //если нет то создаем новую группу в существующий список групп
1602                          begin
1603                            groupInfo:=TMasterDevice.TGroupInfo.Create;
1604                            groupInfo.name:=groupName;
1605                            infoSubDev.indexMaster:=numHeadDev;
1606                            infoSubDev.indexSub:=i;
1607                            infoSubDev.isVertexAdded:=false;
1608                             //ZCMsgCallBackInterface.TextMessage('master = '+inttostr(infoSubDev.indexMaster)+' sub - ' + inttostr(infoSubDev.indexSub),TMWOHistoryOut);
1609 
1610                            groupInfo.LNumSubDevice.PushBack(infoSubDev);
1611                            //HeadGroupInfo.listVertexTerminalBox:=nil;
1612                            //HeadGroupInfo.listVertexWayGroup:=nil;
1613                            //HeadGroupInfo.listVertexWayOnlyVertex:=nil;
1614                            result.Mutable[numHead]^.LGroup.PushBack(groupInfo);
1615                            numHeadGroup:=result[numHead].LGroup.Size-1;
1616                            groupInfo:=nil;
1617                          end
1618                        else
1619                        begin
1620                            infoSubDev.indexMaster:=numHeadDev;
1621                            infoSubDev.indexSub:=i;
1622                            //ZCMsgCallBackInterface.TextMessage('master = '+inttostr(infoSubDev.indexMaster)+' sub - ' + inttostr(infoSubDev.indexSub),TMWOHistoryOut);
1623                            infoSubDev.isVertexAdded:=false;
1624                            result.mutable[numHead]^.LGroup.mutable[numHeadGroup]^.LNumSubDevice.PushBack(infoSubDev);
1625                        end;
1626                    end;
1627 
1628                end;
1629                listCableLaying.Clear;
1630             end;
1631           end;
1632         end;
1633   end;
1634 
1635 
1636 
1637 
1638   //** Создание деревьев устройств
1639   procedure addNewTreeDevice(listVertexEdge:TGraphBuilder;globalGraph:TGraph;var listMasterDevice:TVectorOfMasterDevice);
1640   //type
1641     //tempuseVertex:Tvectorofinteger;
1642   var
1643      pvd:pvardesk; //для работы со свойствами устройств
1644      polyObj:PGDBObjPolyLine;
1645      i,j,k,m,n,counter1,counter2,counter3:integer;
1646      tIndex,tIndexLocal,tIndexGlobal:integer;
1647      EdgePath, VertexPath: TClassList;
1648      infoGTree:TGraph;
1649 
1650      tempString:string;
1651      sumWeightPath,tempFloat: Float;
1652      tempLVertex:TvectorOfInteger;
1653      gg:GDBVertex;
1654 
isVertexAddednull1655      function isVertexAdded(tempLVertex:tvectorofinteger;index:integer):boolean;
1656      var
1657        i:integer;
1658      begin
1659        result:=true;
1660         for i:=0 to tempLVertex.Size-1 do begin
1661             //ZCMsgCallBackInterface.TextMessage('ищем - ' + inttostr(tempLVertex[i])+' наш - ' + inttostr(index),TMWOHistoryOut);
1662             if tempLVertex[i]=index then begin
1663              result:=false;
1664              //ZCMsgCallBackInterface.TextMessage('совпало: ' + inttostr(tempLVertex[i])+' = ' + inttostr(index),TMWOHistoryOut);
1665             end;
1666         end;
1667      end;
1668 
1669 
getLengthnull1670      function getLength(listVertexEdge:TGraphBuilder;pt1,pt2:integer):Float;
1671      var
1672        i:integer;
1673      begin
1674        result:=-1;
1675         for i:=0 to listVertexEdge.listEdge.Size-1 do
1676             if ((listVertexEdge.listEdge[i].VIndex1=pt1) and (listVertexEdge.listEdge[i].VIndex2=pt2)) or
1677             ((listVertexEdge.listEdge[i].VIndex1=pt2) and (listVertexEdge.listEdge[i].VIndex2=pt1)) then
1678              result:=listVertexEdge.listEdge[i].edgeLength;
1679      end;
1680 
getvGPGDBObjSuperLinenull1681      function getvGPGDBObjSuperLine(listVertexEdge:TGraphBuilder;pt1,pt2:integer):PGDBObjSuperLine;
1682      var
1683        i:integer;
1684      begin
1685        result:=nil;
1686         for i:=0 to listVertexEdge.listEdge.Size-1 do
1687             if ((listVertexEdge.listEdge[i].VIndex1=pt1) and (listVertexEdge.listEdge[i].VIndex2=pt2)) or
1688             ((listVertexEdge.listEdge[i].VIndex1=pt2) and (listVertexEdge.listEdge[i].VIndex2=pt1)) then
1689              result:=listVertexEdge.listEdge[i].cableEnt;
1690      end;
1691 
getLocalIndexnull1692      function getLocalIndex(gTree:TGraph;indexGlobal:integer):LongInt;
1693      var
1694        i:integer;
1695      begin
1696        result:=-1;
1697         for i:=0 to gTree.VertexCount-1 do
1698           if gTree.Vertices[i].AsInt32[vGGIndex] = indexGlobal then
1699              result:=i;
1700      end;
1701 
1702     //** Есть ли соединение данного устройства с данным номером головного устройства
1703     //** суть в том что одно и тоже устройство может быть на разных планах, это нужно для избежания ошибок связей
isHaveLineMasternull1704     function isHaveLineMaster(isMaster,isSub:integer):boolean;
1705     begin
1706       //ZCMsgCallBackInterface.TextMessage('isMaster : ' + inttostr(isMaster)+' - isSub -  ' + inttostr(isSub),TMWOHistoryOut);
1707 
1708         result:=true; // нет пути между головным устройством и подключаемым
1709         EdgePath:=TClassList.Create;     //Создаем реберный путь
1710         VertexPath:=TClassList.Create;   //Создаем вершиный путь
1711         //Получение ребер минимального пути в графе из одной точки в другую
1712         sumWeightPath:=globalGraph.FindMinWeightPath(globalGraph[isMaster], globalGraph[isSub], EdgePath);
1713         //Получение вершин минимального пути в графе на основе минимального пути в ребер, указывается из какой точки старт
1714         globalGraph.EdgePathToVertexPath(globalGraph[isMaster], EdgePath, VertexPath);
1715 
1716         //Узнать существует уже граф если нет то создать его и добавляем начальную вершину
1717         if VertexPath.Count > 1 then
1718           result:=false;  //путь есть между головным устройством и подключаемым
1719 
1720     end;
1721 
1722   begin
1723     for i:=0 to listMasterDevice.Size-1 do
1724       begin
1725          for j:=0 to listMasterDevice[i].LGroup.Size -1 do
1726             begin
1727               for n:=0 to listMasterDevice[i].LIndex.Size -1 do
1728               begin
1729 
1730               //ZCMsgCallBackInterface.TextMessage('khfskldhfskdhflksdhflksdhflksdflkshd - ' + inttostr(n),TMWOHistoryOut);
1731               listMasterDevice.Mutable[i]^.LGroup.Mutable[j]^.groupTreeDev:=TGraph.Create;
1732               infoGTree:=listMasterDevice.Mutable[i]^.LGroup.Mutable[j]^.groupTreeDev;
1733               infoGTree.Features:=[Tree];
1734               //infoGTree.Root;
1735               infoGTree.CreateVertexAttr(vGGIndex, AttrInt32);
1736               infoGTree.CreateVertexAttr(vGIsDevice, AttrBool);
1737               infoGTree.CreateVertexAttr(vGInfoVertex, AttrString);
1738               infoGTree.CreateVertexAttr(vGPGDBObjDevice,AttrPointer);  // добавили ссылку сразу на само устройство
1739 
1740               infoGTree.CreateEdgeAttr(vGLength, AttrFloat64);
1741               infoGTree.CreateEdgeAttr(vGInfoEdge, AttrString);
1742               infoGTree.CreateEdgeAttr(vGPGDBObjSuperLine,AttrPointer);  // добавили ссылку сразу на саму линию
1743 
1744               //ZCMsgCallBackInterface.TextMessage('yfx Количство ребер - ' + inttostr(infoGTree.EdgeCount),TMWOHistoryOut);
1745               //ZCMsgCallBackInterface.TextMessage('yfx Количство вершин - ' + inttostr(infoGTree.VertexCount),TMWOHistoryOut);
1746 
1747 
1748               tempLVertex:=tvectorofinteger.create;
1749                 //listMasterDevice[i].LGroup[j].LNumSubDevice;
1750               for k:=0 to listMasterDevice[i].LGroup[j].LNumSubDevice.Size-1 do
1751                 begin
1752 
1753                   if isHaveLineMaster(listMasterDevice[i].LIndex[n],listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexSub) then
1754                      continue;
1755 
1756                   EdgePath:=TClassList.Create;     //Создаем реберный путь
1757                   VertexPath:=TClassList.Create;   //Создаем вершиный путь
1758                   //Получение ребер минимального пути в графе из одной точки в другую
1759                   sumWeightPath:=globalGraph.FindMinWeightPath(globalGraph[listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexMaster], globalGraph[listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexSub], EdgePath);
1760                   //Получение вершин минимального пути в графе на основе минимального пути в ребер, указывается из какой точки старт
1761                   //ZCMsgCallBackInterface.TextMessage('master = '+inttostr(listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexMaster)+' sub - ' + inttostr(listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexSub),TMWOHistoryOut);
1762 
1763                   globalGraph.EdgePathToVertexPath(globalGraph[listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexMaster], EdgePath, VertexPath);
1764 
1765                   tIndexLocal:=-1; //промежуточная вершина для создание ребер графа
1766                   tIndexGlobal:=-1; //промежуточная вершина для построения пути глобального графа
1767 
1768                   //ZCMsgCallBackInterface.TextMessage('количество - ' + inttostr(VertexPath.Count),TMWOHistoryOut);
1769 
1770 
1771 
1772                   //Узнать существует уже граф если нет то создать его и добавляем начальную вершину
1773                   if infoGTree.VertexCount <= 0 then begin
1774                      infoGTree.AddVertex;
1775                      infoGTree.Vertices[infoGTree.VertexCount-1].AsInt32[vGGIndex]:=listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexMaster;
1776 
1777                      //Добавил ссылку на устройство
1778                      infoGTree.Vertices[infoGTree.VertexCount-1].AsPointer[vGPGDBObjDevice]:=listVertexEdge.listVertex[listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexMaster].deviceEnt;
1779 
1780                     if listVertexEdge.listVertex[listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexMaster].deviceEnt <> nil then
1781                       begin
1782                         infoGTree.Vertices[infoGTree.VertexCount-1].AsBool[vGIsDevice]:=true;
1783                         //tempString:='№';
1784                         tempString:=inttostr(infoGTree.Vertices[infoGTree.VertexCount-1].AsInt32[vGGIndex]);
1785                         tempString+='\P';
1786                         tempString+='dev';
1787                         infoGTree.Vertices[infoGTree.VertexCount-1].AsString[vGInfoVertex]:=tempString;
1788                       end
1789                     else
1790                       begin
1791                         infoGTree.Vertices[infoGTree.VertexCount-1].AsBool[vGIsDevice]:=false;
1792                         //tempString:='№';
1793                         tempString:=inttostr(infoGTree.Vertices[infoGTree.VertexCount-1].AsInt32[vGGIndex]);
1794                         tempString+='\P';
1795                         tempString+='nul';
1796                         infoGTree.Vertices[infoGTree.VertexCount-1].AsString[vGInfoVertex]:=tempString;
1797                       end;
1798                     //infoGTree.Vertices[infoGTree.VertexCount-1].AsBool['isFork']:=false;
1799 
1800                      //ZCMsgCallBackInterface.TextMessage('РУУТ - ' + inttostr(infoGTree.VertexCount-1),TMWOHistoryOut);
1801 
1802                      infoGTree.Root:=infoGTree.Vertices[infoGTree.VertexCount-1];
1803                      tempLVertex.PushBack(listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexMaster);
1804                   end;
1805 
1806 
1807                   //**Если граф уже начал построение
1808                   if VertexPath.Count > 1 then
1809                     for m:=VertexPath.Count - 1 downto 0 do begin
1810                       // Добавляет цифрц ы центре каждого устройства
1811                       // uzvtestdraw.testTempDrawText(listVertexEdge.listVertex[TVertex(VertexPath[m]).Index].centerPoint,inttostr(TVertex(VertexPath[m]).Index));
1812 
1813 
1814                       //ZCMsgCallBackInterface.TextMessage('way - ' + inttostr(TVertex(VertexPath[m]).Index),TMWOHistoryOut);
1815 
1816 
1817                       if isVertexAdded(tempLVertex,TVertex(VertexPath[m]).Index) then
1818                         begin
1819                             //ZCMsgCallBackInterface.TextMessage('отработка кода ',TMWOHistoryOut);
1820 
1821                             infoGTree.AddVertex;
1822                             infoGTree.Vertices[infoGTree.VertexCount-1].AsInt32[vGGIndex]:=TVertex(VertexPath[m]).Index;
1823 
1824                             //НОВОЕ! Добавил ссылку на устройство
1825                             infoGTree.Vertices[infoGTree.VertexCount-1].AsPointer[vGPGDBObjDevice]:=listVertexEdge.listVertex[TVertex(VertexPath[m]).Index].deviceEnt;
1826 
1827 
1828                             if listVertexEdge.listVertex[TVertex(VertexPath[m]).Index].deviceEnt <> nil then
1829                             begin
1830                               infoGTree.Vertices[infoGTree.VertexCount-1].AsBool[vGIsDevice]:=true;
1831                               //tempString:='№';
1832                               tempString:=inttostr(infoGTree.Vertices[infoGTree.VertexCount-1].AsInt32[vGGIndex]);
1833                               tempString+='\P';
1834                               tempString+='dev';
1835                               infoGTree.Vertices[infoGTree.VertexCount-1].AsString[vGInfoVertex]:=tempString;
1836                             end
1837                           else
1838                             begin
1839                               infoGTree.Vertices[infoGTree.VertexCount-1].AsBool[vGIsDevice]:=false;
1840                               //tempString:='№';
1841                               tempString:=inttostr(infoGTree.Vertices[infoGTree.VertexCount-1].AsInt32[vGGIndex]);
1842                               tempString+='\P';
1843                               tempString+='nul';
1844                               infoGTree.Vertices[infoGTree.VertexCount-1].AsString[vGInfoVertex]:=tempString;
1845                             end;
1846                             //infoGTree.Vertices[infoGTree.VertexCount-1].AsBool['isFork']:=false;
1847 
1848                             tempLVertex.PushBack(TVertex(VertexPath[m]).Index);
1849 
1850                              if tIndexLocal < 0 then begin
1851                                tIndexLocal:=infoGTree.VertexCount-1;
1852                                tIndexGlobal:=TVertex(VertexPath[m]).Index;
1853                              end
1854                              else
1855                              begin
1856                               //ZCMsgCallBackInterface.TextMessage('edgeGlobal : ' + inttostr(tIndexGlobal)+' - ' + inttostr(TVertex(VertexPath[m]).index),TMWOHistoryOut);
1857                               //ZCMsgCallBackInterface.TextMessage('edgelocal : ' + inttostr(tIndexLocal)+' - ' + inttostr(infoGTree.VertexCount-1),TMWOHistoryOut);
1858                               infoGTree.AddEdge(infoGTree.Vertices[tIndexLocal],infoGTree.Vertices[infoGTree.VertexCount-1]);
1859 
1860                               //ZCMsgCallBackInterface.TextMessage('edgelength : ' + floattostr(getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index)),TMWOHistoryOut);
1861                               //tempFloat:=1*RoundTo(getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index),-1);
1862                               //tempFloat:=20;
1863                               infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat64[vGLength]:=getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index);
1864                               infoGTree.Edges[infoGTree.EdgeCount-1].AsString[vGInfoEdge]:='\\P L='+floattostr(RoundTo(infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat64[vGLength],-1))+'m';
1865                               //ZCMsgCallBackInterface.TextMessage('edgedddddlength : ' + floattostr(infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat32[vGLength]) + ' - - - ' + floattostr(tempFloat),TMWOHistoryOut);
1866 
1867 
1868                               //infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat32[vGLength]:=RoundTo(getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index),-1);
1869                               //infoGTree.Edges[infoGTree.EdgeCount-1].AsString[vGInfoEdge]:='\\P L='+floattostr(infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat32[vGLength])+'m';
1870                               //ZCMsgCallBackInterface.TextMessage('edgelength : ' + floattostr(getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index)) + ' - - - ' + floattostr(RoundTo(getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index),-1)),TMWOHistoryOut);
1871                               //ZCMsgCallBackInterface.TextMessage('edgelength : ' + floattostr(infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat32[vGLength]) + ' - округ - ' + infoGTree.Edges[infoGTree.EdgeCount-1].AsString[vGInfoEdge],TMWOHistoryOut);
1872 
1873                               tIndexLocal:=infoGTree.VertexCount-1;
1874                               tIndexGlobal:=TVertex(VertexPath[m]).Index;
1875                              end;
1876 
1877                          end
1878                       else begin
1879                         if tIndexLocal >= 0 then
1880                            begin
1881                             tIndex:=getLocalIndex(infoGTree,TVertex(VertexPath[m]).index);
1882                             //ZCMsgCallBackInterface.TextMessage('edgeGlobal : ' + inttostr(tIndexGlobal)+' - ' + inttostr(TVertex(VertexPath[m]).index),TMWOHistoryOut);
1883                             //ZCMsgCallBackInterface.TextMessage('edgelocal : ' + inttostr(tIndexLocal)+' - ' + inttostr(tIndex),TMWOHistoryOut);
1884                             infoGTree.AddEdge(infoGTree.Vertices[tIndexLocal],infoGTree.Vertices[tIndex]);
1885 
1886                             //НОВОЕ!!!! Добавил ссылку на устройство
1887                             infoGTree.Edges[infoGTree.EdgeCount-1].AsPointer[vGPGDBObjSuperLine]:=getvGPGDBObjSuperLine(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index);
1888 
1889 
1890                               //ZCMsgCallBackInterface.TextMessage('edgelength : ' + floattostr(getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index)),TMWOHistoryOut);
1891                               infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat64[vGLength]:=getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index);
1892                               infoGTree.Edges[infoGTree.EdgeCount-1].AsString[vGInfoEdge]:='\\P L='+floattostr(RoundTo(infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat64[vGLength],-1))+'m';
1893 
1894                               //ZCMsgCallBackInterface.TextMessage('edgelength : ' + floattostr(getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index)) + ' - - - ' + floattostr(RoundTo(getlength(listVertexEdge,tIndexGlobal,TVertex(VertexPath[m]).Index),-1)),TMWOHistoryOut);
1895                               //ZCMsgCallBackInterface.TextMessage('edgelength : ' + floattostr(infoGTree.Edges[infoGTree.EdgeCount-1].AsFloat32[vGLength]) + ' - округ - ' + infoGTree.Edges[infoGTree.EdgeCount-1].AsString[vGInfoEdge],TMWOHistoryOut);
1896 
1897                             tIndexLocal:=-1;
1898                             tIndexGlobal:=-1;
1899                         end;
1900                       end;
1901                     end;
1902 
1903                   EdgePath.Destroy;
1904                   VertexPath.Destroy;
1905                 end;
1906 
1907               //ZCMsgCallBackInterface.TextMessage('Количство ребер - ' + inttostr(infoGTree.EdgeCount),TMWOHistoryOut);
1908               //ZCMsgCallBackInterface.TextMessage('Количство вершин - ' + inttostr(infoGTree.VertexCount),TMWOHistoryOut);
1909 
1910               // Такая проверку нужна, тогда когда бывает что головное устройство на разных планах установлено
1911               // и может возникнуть ситуация когда на плане разные группы, что вызовит пустой граф
1912               //что бы не было проблем выполнена данная проверка
1913               if infoGTree.VertexCount > 0 then begin
1914               infoGTree.CorrectTree; //Делает дерево корректным, добавляет родителей детей
1915               listMasterDevice.mutable[i]^.LGroup.mutable[j]^.LTreeDev.PushBack(infoGTree);
1916               end;
1917 
1918               infoGTree:=nil;
1919               tempLVertex.Destroy;
1920             end;
1921          end;
1922       end;
1923   end;
1924 
buildListAllConnectDeviceNewnull1925 function buildListAllConnectDeviceNew(listVertexEdge:TGraphBuilder;Epsilon:double; var listError:TListError):TVectorOfMasterDevice;
1926 var
1927 
1928     globalGraph: TGraph;
1929     listMasterDevice:TVectorOfMasterDevice;
1930 
1931     i,j,k: Integer;
1932 
1933     gg:GDBVertex;
1934 
1935 
1936     //** Поиск существует ли устройства с нужным именем
isHaveDevicenull1937     function isHaveDevice(listVertex:TListDeviceLine;name:string):boolean;
1938     var
1939        i: Integer;
1940        pvd:pvardesk; //для работы со свойствами устройств
1941     begin
1942          result:=true;
1943          for i:=0 to listVertex.Size-1 do
1944                if listVertex[i].deviceEnt<>nil then
1945                begin
1946                    pvd:=FindVariableInEnt(listVertex[i].deviceEnt,'NMO_Name');
1947                    if pvd <> nil then
1948                    if pgdbstring(pvd^.data.Instance)^ = name then
1949                       result:= false;
1950                end;
1951     end;
1952 
1953   begin
1954 
1955     //Создаем граф на основе класса TGraphBuilder полученого при обработке устройств и суперлиний
1956     globalGraph:=TGraph.Create;
1957     globalGraph.Features:=[Weighted];
1958     globalGraph.AddVertices(listVertexEdge.listVertex.Size);
1959     for i:=0 to listVertexEdge.listEdge.Size-1 do
1960     begin
1961       globalGraph.AddEdges([listVertexEdge.listEdge[i].VIndex1, listVertexEdge.listEdge[i].VIndex2]);
1962       globalGraph.Edges[i].Weight:=listVertexEdge.listEdge[i].edgeLength;
1963     end;
1964 
1965 
1966     //**получаем список подключенных устройств к головным устройствам
1967     listMasterDevice:=getListMasterDevNew(listVertexEdge,globalGraph);
1968 
1969     for i:=0 to listMasterDevice.Size-1 do
1970       begin
1971          ZCMsgCallBackInterface.TextMessage('мастер = '+ listMasterDevice[i].name,TMWOHistoryOut);
1972          ZCMsgCallBackInterface.TextMessage('мастер кол-во = '+ inttostr(listMasterDevice[i].LIndex.Size),TMWOHistoryOut);
1973          for j:=0 to listMasterDevice[i].LGroup.Size -1 do
1974             begin
1975               ZCMsgCallBackInterface.TextMessage('колво приборы = '+ inttostr(listMasterDevice[i].LGroup[j].LNumSubDevice.size),TMWOHistoryOut);
1976               for k:=0 to listMasterDevice[i].LGroup[j].LNumSubDevice.Size -1 do
1977                 ZCMsgCallBackInterface.TextMessage('приборы = '+ inttostr(listMasterDevice[i].LGroup[j].LNumSubDevice[k].indexSub),TMWOHistoryOut);
1978             end;
1979       end;
1980 
1981      //**Переробатываем список устройств подключенный к группам и на основе него создание сложное дерево усройств
1982      addNewTreeDevice(listVertexEdge,globalGraph,listMasterDevice);
1983 
1984 
1985 //
1986 //    //**Переробатываем список устройств подключенный к группам и на основе него создание деревьев усройств
1987 //
1988 //
1989 //    //**Переробатываем большой граф в упрощенный,для удобной визуализации
1990 //    //addEasyTreeDevice(globalGraph,listMasterDevice);
1991 //
1992 //    //**Добавляем к вершинам длины кабелей с конца, для правильной сортировки дерева по длине
1993 //    addItemLengthFromEnd(listMasterDevice);
1994 //
1995 //    ZCMsgCallBackInterface.TextMessage('*** Суперлиния - ' + listVertexEdge.nameSuperLine + ' - обработка выполнена! ***',TMWOHistoryOut);
1996 //
1997 //    //visualGraph(listMasterDevice[0].LGroup[0].LTreeDev[0],gg,1) ;
1998 //    //gg:=uzegeometry.CreateVertex(0,0,0);
1999 //
2000 //    //visualAllTreesLMD(listMasterDevice,gg,1);
2001 //
2002 //    for i:=0 to listMasterDevice.Size-1 do
2003 //      begin
2004 //         for j:=0 to listMasterDevice[i].LGroup.Size -1 do
2005 //            begin
2006 //              for k:=0 to listMasterDevice[i].LGroup[j].LTreeDev.Size -1 do begin
2007 //                //visualGraph(listMasterDevice[i].LGroup[j].LTreeDev[k],gg,1);
2008 //
2009 //                listMasterDevice.mutable[i]^.LGroup.mutable[j]^.LTreeDev.mutable[k]^.SortTree(listMasterDevice[i].LGroup[j].LTreeDev[k].Root,@SortTreeLengthComparer.Compare);
2010 //
2011 //                //visualGraph(listMasterDevice[i].LGroup[j].LTreeDev[k],gg,1);
2012 //               end;
2013 //            end;
2014 //
2015 //      end;
2016 //
2017       result:=listMasterDevice;
2018 
2019   end;
2020 
2021 
2022 //Процедура создания списка ошибок
2023 procedure errorSearchList(ourGraph:TGraphBuilder;Epsilon:double;var listError:TListError;listSLname:TGDBlistSLname);
2024 type
2025     TListString=specialize TVector<string>;
2026 var
2027     EdgePath, VertexPath: TClassList;
2028     G: TGraph;
2029     headNum : integer;
2030 
2031     counter,counter2,counter3,counterColor:integer; //счетчики
2032     i,j,k: Integer;
2033     T: Float;
2034 
2035     headName,GroupNum,typeSLine,nameSL:string;
2036 
2037     listStr1,listStr2,listStr3:TListString;
2038 
2039     ///Получить список  параметров устройства для подключения
getListParamDevnull2040     function getListParamDev(nowDev:PGDBObjDevice;nameType:string):TListString;
2041     var
2042        pvd:pvardesk; //для работы со свойствами устройств
2043        tempName,nameParam:gdbstring;
2044     begin
2045         result:=TListString.Create;
2046         pvd:=FindVariableInEnt(nowDev,nameType);
2047          if pvd<>nil then
2048             BEGIN
2049              tempName:=pgdbstring(pvd^.data.Instance)^;
2050              repeat
2051                    GetPartOfPath(nameParam,tempName,';');
2052                    result.PushBack(nameParam);
2053              until tempName='';
2054             end;
2055 
2056     end;
2057     procedure addErrorinList(nowDev:PGDBObjDevice;var listError:TListError;textError:string);
2058     var
2059        pvd:pvardesk; //для работы со свойствами устройств
2060        //tempName,nameParam:gdbstring;
2061        errorInfo:TErrorInfo;
2062        //tempstring:string;
2063        isNotDev:boolean;
2064        i:integer;
2065     begin
2066        isNotDev:=true;
2067        for i:=0 to listError.Size-1 do
2068          begin
2069            if listError[i].device = nowDev then
2070              begin
2071               //tempstring := concat(errorInfo.text,textError);
2072                listError.Mutable[i]^.text := listError[i].text + textError;
2073                isNotDev:=false;
2074              end
2075          end;
2076        if isNotDev then
2077          begin
2078            //pvd:=FindVariableInEnt(nowDev,nameType);
2079            errorInfo.device := nowDev;
2080            errorInfo.name:=nowDev^.Name;
2081            errorInfo.text:=textError;
2082            listError.PushBack(errorInfo);
2083          end;
2084     end;
2085 
2086     //** Поиск существует ли устройства с нужным именем
isHaveDevicenull2087     function isHaveDevice(listVertex:TListDeviceLine;name:string):boolean;
2088     var
2089        i: Integer;
2090        pvd:pvardesk; //для работы со свойствами устройств
2091     begin
2092          result:=true;
2093          for i:=0 to listVertex.Size-1 do
2094             begin
2095                if listVertex[i].deviceEnt<>nil then
2096                begin
2097                    pvd:=FindVariableInEnt(listVertex[i].deviceEnt,'NMO_Name');
2098                    if pvd <> nil then
2099                    if pgdbstring(pvd^.data.Instance)^ = name then begin
2100                       result:= false;
2101                    end;
2102                end;
2103 
2104             end;
2105     end;
2106 
2107   begin
2108 
2109             // Подключение созданного граффа к библиотеке Аграф
2110     G:=TGraph.Create;
2111     G.Features:=[Weighted];
2112     G.AddVertices(ourGraph.listVertex.Size);
2113     for k:=0 to ourGraph.listEdge.Size-1 do
2114     begin
2115       G.AddEdges([ourGraph.listEdge[k].VIndex1, ourGraph.listEdge[k].VIndex2]);
2116       G.Edges[k].Weight:=ourGraph.listEdge[k].edgeLength;
2117     end;
2118 
2119     //смотрим все вершины
2120     for i:=0 to ourGraph.listVertex.Size-1 do
2121       begin
2122          //если это устройство и не разрыв
2123          if (ourGraph.listVertex[i].deviceEnt<>nil) and (ourGraph.listVertex[i].break<>true) then
2124          begin
2125               listStr1:=getListParamDev(ourGraph.listVertex[i].deviceEnt,'SLCABAGEN_HeadDeviceName');
2126               listStr2:=getListParamDev(ourGraph.listVertex[i].deviceEnt,'SLCABAGEN_NGHeadDevice');
2127               listStr3:=getListParamDev(ourGraph.listVertex[i].deviceEnt,'SLCABAGEN_SLTypeagen');
2128               if (listStr1.size = listStr2.size) and (listStr1.size = listStr3.size) and (listStr2.size = listStr3.size) then
2129               begin
2130                   counter:=0;
2131                   for j:=0 to listStr1.size-1 do
2132                    begin
2133                      headName:=listStr1[j];      //имя хозяина
2134                      GroupNum:=listStr2[j];      //№ шлейфа
2135                      typeSLine:=listStr3[j];     //название трассы
2136                      for nameSL in listSLname do
2137                          if typeSLine = nameSL then
2138                            inc(counter);
2139                    end;
2140                   if listStr1.size<>counter then
2141                     addErrorinList(ourGraph.listVertex[i].deviceEnt,listError,'Не правильное имя типа трассы *суперлинии* ');
2142 
2143                   counter:=0;
2144                   for j:=0 to listStr1.size-1 do
2145                    begin
2146                      headName:=listStr1[j];      //имя хозяина
2147                      GroupNum:=listStr2[j];      //№ шлейфа
2148                      typeSLine:=listStr3[j];     //название трассы
2149                      //isHaveDevice
2150                      if isHaveDevice(ourGraph.listVertex,headName) then
2151                        addErrorinList(ourGraph.listVertex[i].deviceEnt,listError,'Одно из имен головного устройства не правильное');
2152                    end;
2153 
2154                   for j:=0 to listStr1.size-1 do
2155                   begin
2156                    headName:=listStr1[j];      //имя хозяина
2157                    GroupNum:=listStr2[j];      //№ шлейфа
2158                    typeSLine:=listStr3[j];     //название трассы
2159                    //for nameSL in listSLname do
2160                    //  begin
2161                      if typeSLine = ourGraph.nameSuperLine then
2162                      begin
2163                       headNum:=getNumHeadDevice(ourGraph.listVertex,headName,G,i);
2164                       if headNum >= 0 then begin
2165 
2166                         //работа с библиотекой Аграф
2167                         EdgePath:=TClassList.Create;     //Создаем реберный путь
2168                         VertexPath:=TClassList.Create;   //Создаем вершиный путь
2169 
2170                         // Получение ребер минимального пути в графи из одной точки в другую
2171                         T:=G.FindMinWeightPath(G[headNum], G[i], EdgePath);
2172                         // Получение вершин минимального пути в графи на основе минимального пути в ребер, указывается из какой точки старт
2173                         G.EdgePathToVertexPath(G[headNum], EdgePath, VertexPath);
2174 
2175                          if VertexPath.Count <= 1 then
2176                           addErrorinList(ourGraph.listVertex[i].deviceEnt,listError,'Нет пути до головного устройства');
2177 
2178                         EdgePath.Free;
2179                         VertexPath.Free;
2180                        end
2181                        else
2182                        begin
2183                             addErrorinList(ourGraph.listVertex[i].deviceEnt,listError,'Головное устройство с таким именем отсутствует');
2184                            //else
2185                            //   addErrorinList(ourGraph.listVertex[i].deviceEnt,listError,'Нет пути до головного устройства');
2186                        end;
2187                      end;
2188                  end;
2189 
2190               end
2191               else
2192                 addErrorinList(ourGraph.listVertex[i].deviceEnt,listError,'Не одинаковое количество параметров в настройках');
2193 
2194         end;
2195       end;
2196   end;
2197 
2198 //Процедура создания списка ошибок
2199 procedure errorList(allGraph:TListAllGraph;Epsilon:double;var listError:TListError;listSLname,listAllSLname:TGDBlistSLname);
2200 type
2201     TListString=specialize TVector<string>;
2202 var
2203     EdgePath, VertexPath: TClassList;
2204     G: TGraph;
2205     headNum : integer;
2206 
2207     counter,counter2,counter3,counterColor:integer; //счетчики
2208     i,j,k: Integer;
2209     T: Float;
2210 
2211     headName,GroupNum,typeSLine,nameSL:string;
2212 
2213     listStr1,listStr2,listStr3:TListString;
2214 
2215     ourGraph:TGraphBuilder;
2216     graphBuilderInfo:TListGraphBuilder;
2217     ///Получить список  параметров устройства для подключения
getListParamDevnull2218     function getListParamDev(nowDev:PGDBObjDevice;nameType:string):TListString;
2219     var
2220        pvd:pvardesk; //для работы со свойствами устройств
2221        tempName,nameParam:gdbstring;
2222     begin
2223         result:=TListString.Create;
2224         pvd:=FindVariableInEnt(nowDev,nameType);
2225          if pvd<>nil then
2226             BEGIN
2227              tempName:=pgdbstring(pvd^.data.Instance)^;
2228              repeat
2229                    GetPartOfPath(nameParam,tempName,';');
2230                    result.PushBack(nameParam);
2231              until tempName='';
2232             end;
2233 
2234     end;
2235     procedure addErrorinList(nowDev:PGDBObjDevice;var listError:TListError;textError:string);
2236     var
2237        pvd:pvardesk; //для работы со свойствами устройств
2238        //tempName,nameParam:gdbstring;
2239        errorInfo:TErrorInfo;
2240        //tempstring:string;
2241        isNotDev:boolean;
2242        i:integer;
2243     begin
2244        isNotDev:=true;
2245        for i:=0 to listError.Size-1 do
2246          begin
2247            if listError[i].device = nowDev then
2248              begin
2249               //tempstring := concat(errorInfo.text,textError);
2250                listError.Mutable[i]^.text := listError[i].text + textError;
2251                isNotDev:=false;
2252              end
2253          end;
2254        if isNotDev then
2255          begin
2256            //pvd:=FindVariableInEnt(nowDev,nameType);
2257            errorInfo.device := nowDev;
2258            errorInfo.name:=nowDev^.Name;
2259            errorInfo.text:=textError;
2260            listError.PushBack(errorInfo);
2261          end;
2262     end;
2263 
2264     //** Поиск существует ли устройства с нужным именем
isHaveDevicenull2265     function isHaveDevice(listVertex:TListDeviceLine;name:string):boolean;
2266     var
2267        i: Integer;
2268        pvd:pvardesk; //для работы со свойствами устройств
2269     begin
2270          result:=true;
2271          for i:=0 to listVertex.Size-1 do
2272             begin
2273                if listVertex[i].deviceEnt<>nil then
2274                begin
2275                    pvd:=FindVariableInEnt(listVertex[i].deviceEnt,'NMO_Name');
2276                    if pvd <> nil then
2277                    if pgdbstring(pvd^.data.Instance)^ = name then begin
2278                       result:= false;
2279                    end;
2280                end;
2281 
2282             end;
2283     end;
getNumHeadDevnull2284     function getNumHeadDev(listVertex:TListDeviceLine;name:string;G:TGraph;numDev:integer):integer;
2285        var
2286        i: Integer;
2287        pvd:pvardesk; //для работы со свойствами устройств
2288        T: Float;
2289        EdgePath, VertexPath: TClassList;
2290     begin
2291          result:=-2;
2292          for i:=0 to listVertex.Size-1 do
2293             begin
2294                if listVertex[i].deviceEnt<>nil then
2295                begin
2296                    pvd:=FindVariableInEnt(listVertex[i].deviceEnt,'NMO_Name');
2297                    if pvd <> nil then
2298                    if pgdbstring(pvd^.data.Instance)^ = name then begin
2299                       //result:=-1;
2300 
2301                       //работа с библиотекой Аграф
2302                       EdgePath:=TClassList.Create;     //Создаем реберный путь
2303                       VertexPath:=TClassList.Create;   //Создаем вершиный путь
2304 
2305                       // Получение ребер минимального пути в графи из одной точки в другую
2306                       T:=G.FindMinWeightPath(G[i], G[numDev], EdgePath);
2307                       // Получение вершин минимального пути в графи на основе минимального пути в ребер, указывается из какой точки старт
2308                       G.EdgePathToVertexPath(G[i], EdgePath, VertexPath);
2309 
2310                       if VertexPath.Count > 1 then
2311                         result:= i;
2312 
2313                       EdgePath.Free;
2314                       VertexPath.Free;
2315                    end;
2316                end;
2317 
2318             end;
2319     end;
2320 
2321   begin
2322      //Проверяем параметры заполненость параметров во Всех устройствах//
2323 
2324      ourGraph:=allGraph[0].graph;
2325      for i:=0 to ourGraph.listVertex.Size-1 do
2326       begin
2327          //если это устройство и не разрыв
2328          if (ourGraph.listVertex[i].deviceEnt<>nil) and (ourGraph.listVertex[i].break<>true) then
2329          begin
2330               listStr1:=getListParamDev(ourGraph.listVertex[i].deviceEnt,'SLCABAGEN_HeadDeviceName');
2331               listStr2:=getListParamDev(ourGraph.listVertex[i].deviceEnt,'SLCABAGEN_NGHeadDevice');
2332               listStr3:=getListParamDev(ourGraph.listVertex[i].deviceEnt,'SLCABAGEN_SLTypeagen');
2333               if (listStr1.size = listStr2.size) and (listStr1.size = listStr3.size) and (listStr2.size = listStr3.size) then
2334               begin
2335                   counter:=0;
2336                   for j:=0 to listStr1.size-1 do
2337                    begin
2338                      headName:=listStr1[j];      //имя хозяина
2339                      GroupNum:=listStr2[j];      //№ шлейфа
2340                      typeSLine:=listStr3[j];     //название трассы
2341                      for nameSL in listAllSLname do
2342                          if typeSLine = nameSL then
2343                            inc(counter);
2344                    end;
2345                   if listStr1.size<>counter then
2346                     addErrorinList(ourGraph.listVertex[i].deviceEnt,listError,'Не правильное имя типа трассы *суперлинии* ');
2347 
2348                  end
2349               else
2350                 addErrorinList(ourGraph.listVertex[i].deviceEnt,listError,'Не одинаковое количество параметров в настройках');
2351         end;
2352       end;
2353 
2354     //** Проверяем подключены устройства к головному устройствам, возможность проложить трассу
2355     for graphBuilderInfo in allGraph do
2356      begin
2357         ourGraph:=graphBuilderInfo.graph;
2358         // Подключение созданного граффа к библиотеке Аграф
2359     G:=TGraph.Create;
2360     G.Features:=[Weighted];
2361     G.AddVertices(ourGraph.listVertex.Size);
2362     for k:=0 to ourGraph.listEdge.Size-1 do
2363     begin
2364       G.AddEdges([ourGraph.listEdge[k].VIndex1, ourGraph.listEdge[k].VIndex2]);
2365       G.Edges[k].Weight:=ourGraph.listEdge[k].edgeLength;
2366     end;
2367 
2368     //смотрим все вершины
2369     for i:=0 to ourGraph.listVertex.Size-1 do
2370       begin
2371          //если это устройство и не разрыв
2372          if (ourGraph.listVertex[i].deviceEnt<>nil) and (ourGraph.listVertex[i].break<>true) then
2373          begin
2374               listStr1:=getListParamDev(ourGraph.listVertex[i].deviceEnt,'SLCABAGEN_HeadDeviceName');
2375               listStr2:=getListParamDev(ourGraph.listVertex[i].deviceEnt,'SLCABAGEN_NGHeadDevice');
2376               listStr3:=getListParamDev(ourGraph.listVertex[i].deviceEnt,'SLCABAGEN_SLTypeagen');
2377               if (listStr1.size = listStr2.size) and (listStr1.size = listStr3.size) and (listStr2.size = listStr3.size) then
2378               begin
2379                   for j:=0 to listStr1.size-1 do
2380                   begin
2381                    headName:=listStr1[j];      //имя хозяина
2382                    GroupNum:=listStr2[j];      //№ шлейфа
2383                    typeSLine:=listStr3[j];     //название трассы
2384                    //for nameSL in listSLname do
2385                    //  begin
2386 
2387                      if isHaveDevice(ourGraph.listVertex,headName) then begin
2388                        addErrorinList(ourGraph.listVertex[i].deviceEnt,listError,'Одно из имен головного устройства не правильное');
2389                        continue;
2390                      end;
2391 
2392 
2393                      if typeSLine = ourGraph.nameSuperLine then
2394                      begin
2395 
2396                       headNum:=getNumHeadDev(ourGraph.listVertex,headName,G,i);
2397                       //ZCMsgCallBackInterface.TextMessage('*** УРРРРА ***' + inttostr(headNum),TMWOHistoryOut);
2398                       //ZCMsgCallBackInterface.TextMessage('*** УРРРРА ***' + inttostr(headNum),TMWOHistoryOut);
2399 
2400                       if headNum < 0 then begin
2401                          addErrorinList(ourGraph.listVertex[i].deviceEnt,listError,'Нет пути до головного устройства');
2402                        // //работа с библиотекой Аграф
2403                        // EdgePath:=TClassList.Create;     //Создаем реберный путь
2404                        // VertexPath:=TClassList.Create;   //Создаем вершиный путь
2405                        //
2406                        // // Получение ребер минимального пути в графи из одной точки в другую
2407                        // T:=G.FindMinWeightPath(G[headNum], G[i], EdgePath);
2408                        // // Получение вершин минимального пути в графи на основе минимального пути в ребер, указывается из какой точки старт
2409                        // G.EdgePathToVertexPath(G[headNum], EdgePath, VertexPath);
2410                        //
2411                        //  if VertexPath.Count <= 1 then
2412                        //   addErrorinList(ourGraph.listVertex[i].deviceEnt,listError,'Нет пути до головного устройства');
2413                        //
2414                        // EdgePath.Free;
2415                        // VertexPath.Free;
2416                        end;
2417                        ////else
2418                        ////begin
2419                        ////     addErrorinList(ourGraph.listVertex[i].deviceEnt,listError,'Головное устройство с таким именем отсутствует');
2420                        ////    //else
2421                        ////    //   addErrorinList(ourGraph.listVertex[i].deviceEnt,listError,'Нет пути до головного устройства');
2422                        ////end;
2423                      end;
2424                  end;
2425 
2426               end
2427               else
2428                 addErrorinList(ourGraph.listVertex[i].deviceEnt,listError,'Не одинаковое количество параметров в настройках');
2429 
2430         end;
2431       end;
2432      end;
2433   end;
2434 
2435 
TestgraphUses_comnull2436   function TestgraphUses_com(operands:TCommandOperands):TCommandResult;
2437   var
2438     G: TGraph;
2439     EdgePath, VertexPath: TClassList;
2440     I: Integer;
2441     T: Float;
2442   begin
2443     ZCMsgCallBackInterface.TextMessage('*** Min Weight Path ***',TMWOHistoryOut);
2444   //  writeln('*** Min Weight Path ***');
2445     G:=TGraph.Create;
2446     G.Features:=[Weighted];
2447     EdgePath:=TClassList.Create;
2448     VertexPath:=TClassList.Create;
2449     try
2450       G.AddVertices(7);
2451       G.AddEdges([0, 2,  0, 3,  0, 4,  0, 5,  1, 2,  1, 3,  1, 5,  2, 4,  3, 4,
2452         5, 6]);
2453       G.Edges[0].Weight:=11;
2454       G.Edges[1].Weight:=7;
2455       G.Edges[2].Weight:=2;
2456       G.Edges[3].Weight:=12;
2457       G.Edges[4].Weight:=2;
2458       G.Edges[5].Weight:=3;
2459       G.Edges[6].Weight:=2;
2460       G.Edges[7].Weight:=1;
2461       G.Edges[8].Weight:=2;
2462       G.Edges[9].Weight:=4;
2463 
2464       ZCMsgCallBackInterface.TextMessage(IntToStr(G.VertexCount) + '-вершин до удаления ',TMWOHistoryOut);
2465             ZCMsgCallBackInterface.TextMessage(IntToStr(G.EdgeCount) + '-ребер до удаления ',TMWOHistoryOut);
2466 
2467       G.Vertices[4].Destroy;
2468 
2469 
2470             ZCMsgCallBackInterface.TextMessage(IntToStr(G.VertexCount) + '-вершин после удаления ',TMWOHistoryOut);
2471             ZCMsgCallBackInterface.TextMessage(IntToStr(G.EdgeCount) + '-ребер после удаления ',TMWOHistoryOut);
2472 
2473       for I:=0 to G.VertexCount - 1 do
2474         ZCMsgCallBackInterface.TextMessage(IntToStr(I) + '-вершина ',TMWOHistoryOut);
2475 
2476       ZCMsgCallBackInterface.TextMessage(' ***Ребра между вершинами*** ',TMWOHistoryOut);
2477       for I:=0 to G.EdgeCount - 1 do begin
2478         ZCMsgCallBackInterface.TextMessage(IntToStr(I) + '- соединение ' + IntToStr(G.Edges[I].V1.Index) + ' - ' + IntToStr(G.Edges[I].V2.Index) + ' = ' + floattostr(G.Edges[I].Weight),TMWOHistoryOut);
2479       end;
2480 
2481 
2482 
2483       T:=G.FindMinWeightPath(G.Vertices[0], G.Vertices[2], EdgePath);
2484 
2485       if T <> 11 then begin
2486            ZCMsgCallBackInterface.TextMessage('*** Error! ***',TMWOHistoryOut);
2487        // write('Error!');
2488        // readln;
2489         Exit;
2490       end;
2491       ZCMsgCallBackInterface.TextMessage('Minimal Length: ',TMWOHistoryOut);
2492       //writeln('Minimal Length: ', T :4:2);
2493       G.EdgePathToVertexPath(G[0], EdgePath, VertexPath);
2494       ZCMsgCallBackInterface.TextMessage('Vertices: ',TMWOHistoryOut);
2495       //write('Vertices: ');
2496       for I:=0 to VertexPath.Count - 1 do
2497         ZCMsgCallBackInterface.TextMessage(IntToStr(TVertex(VertexPath[I]).Index) + ' ',TMWOHistoryOut);
2498       //writeln;
2499     finally
2500       G.Free;
2501       EdgePath.Free;
2502       VertexPath.Free;
2503     end;
2504     result:=cmd_ok;
2505   end;
TestTREEUses_comnull2506   function TestTREEUses_com(operands:TCommandOperands):TCommandResult;
2507   var
2508     G: TGraph;
2509     EdgePath, VertexPath: TClassList;
2510     //I: Integer;
2511     //T: Float;
2512     procedure ShowPath(const CorrectPath: array of Integer);
2513       var
2514         I: Integer;
2515       begin
2516         for I:=0 to VertexPath.Count - 1 do
2517           if TVertex(VertexPath[I]).Index <> CorrectPath[I] then begin
2518             ZCMsgCallBackInterface.TextMessage('Error!' + inttostr(TVertex(VertexPath[I]).Index),TMWOHistoryOut);
2519             //write('Error!');
2520             //readln;
2521             //Exit;
2522           end;
2523         for I:=0 to VertexPath.Count - 1 do
2524          ZCMsgCallBackInterface.TextMessage(inttostr(TVertex(VertexPath[I]).Index) + ' ',TMWOHistoryOut);
2525           //write(TVertex(VertexPath[I]).Index, ' ');
2526         //writeln;
2527       end;
2528   begin
2529 
2530       ZCMsgCallBackInterface.TextMessage('*** tree Path ***',TMWOHistoryOut);
2531       G:=TGraph.Create;
2532       VertexPath:=TClassList.Create;
2533       try
2534         G.Features:=[Tree];
2535         G.CreateVertexAttr('t', AttrBool);
2536         G.Root:=G.AddVertex;
2537         With G.Root do begin
2538           With AddChild do begin
2539             With AddChild do begin
2540               AddChild.AsBool['t']:=True;
2541               AddChild;
2542             end;
2543             AddChild;
2544             AddChild.AddChild;
2545           end;
2546           AddChild;
2547         end;
2548               if G.IsTree then
2549          ZCMsgCallBackInterface.TextMessage('граф дерево',TMWOHistoryOut)
2550       else
2551          ZCMsgCallBackInterface.TextMessage('граф не дерево',TMWOHistoryOut);
2552         G.CorrectTree;
2553 
2554                     if G.IsTree then
2555          ZCMsgCallBackInterface.TextMessage('граф дерево',TMWOHistoryOut)
2556       else
2557          ZCMsgCallBackInterface.TextMessage('граф не дерево',TMWOHistoryOut) ;
2558 
2559         G.TreeTraversal(G.Root, VertexPath);
2560         ShowPath([0, 1, 3, 2, 4, 5, 6, 7, 8]);
2561         //G.ArrangeTree(G.Root, TAttrSet.CompareUser, TAttrSet.CompareUser);
2562         //G.SortTree(G.Root,@DummyComparer.Compare);
2563         G.TreeTraversal(G.Root, VertexPath);
2564         ShowPath([0, 8, 1, 5, 6, 7, 2, 4, 3]);
2565 
2566 
2567   ////  writeln('*** Min Weight Path ***');
2568   //  G:=TGraph.Create;
2569   //  G.Features:=[Tree];
2570   //  EdgePath:=TClassList.Create;
2571   //  VertexPath:=TClassList.Create;
2572   //  try
2573   //    G.AddVertices(10);
2574   //    G.AddEdges([0, 2,  0, 3,  0, 1, 1, 4,  2, 5,  2, 6,  5, 7,  5, 8,
2575   //      6, 9]);
2576   //    //G.Edges[0].Weight:=5;
2577   //    //G.Edges[1].Weight:=7;
2578   //    //G.Edges[2].Weight:=2;
2579   //    //G.Edges[3].Weight:=12;
2580   //    //G.Edges[4].Weight:=2;
2581   //    //G.Edges[5].Weight:=3;
2582   //    //G.Edges[6].Weight:=2;
2583   //    //G.Edges[7].Weight:=1;
2584   //    //G.Edges[8].Weight:=2;
2585   //    //G.Edges[9].Weight:=4;
2586   //    //T:=G.FindMinWeightPath(G[0], G[6], EdgePath);
2587   //
2588   //    //if T <> 11 then begin
2589   //    //     ZCMsgCallBackInterface.TextMessage('*** Error! ***',TMWOHistoryOut);
2590   //    // // write('Error!');
2591   //    // // readln;
2592   //    //  Exit;
2593   //    //end;
2594   //    //ZCMsgCallBackInterface.TextMessage('Minimal Length: 'G.,TMWOHistoryOut);
2595   //    //writeln('Minimal Length: ', T :4:2);
2596   //    //G.EdgePathToVertexPath(G[0], EdgePath, VertexPath);
2597   //    ZCMsgCallBackInterface.TextMessage('Vertices: ',TMWOHistoryOut);
2598   //    //write('Vertices: ');
2599   //    for I:=0 to VertexPath.Count - 1 do
2600   //      ZCMsgCallBackInterface.TextMessage(IntToStr(TVertex(VertexPath[I]).Index) + ' ',TMWOHistoryOut);
2601   //    //writeln;
2602     finally
2603       G.Free;
2604       //EdgePath.Free;
2605       VertexPath.Free;
2606     end;
2607     result:=cmd_ok;
2608   end;
2609 
2610 
2611 
TDummyComparer.Comparenull2612 function TDummyComparer.Compare (Edge1, Edge2: Pointer): Integer;
2613 var
2614   e1,e2:TAttrSet;
2615 begin
2616    result:=0;
2617    e1:=TAttrSet(Edge1);
2618    e2:=TAttrSet(Edge2);
2619 
2620    ZCMsgCallBackInterface.TextMessage('sssssssssssssss'+e1.ClassName,TMWOHistoryOut);
2621    //ZCMsgCallBackInterface.TextMessage('xxxxxxssssss'+e1.AsString[vGInfoEdge],TMWOHistoryOut);
2622        //Edge1
2623    //ZCMsgCallBackInterface.TextMessage(floattostr(e1.AsFloat32['tt']) + ' сравниваем ' + floattostr(e2.AsFloat32['tt']),TMWOHistoryOut);
2624    //   ZCMsgCallBackInterface.TextMessage(floattostr(e2.AsFloat32[vGLength]) + '   ',TMWOHistoryOut);
2625 
2626    //e1.GetAsFloat32
2627 
2628    //if e1.ClassName; AsFloat32['lengthfrombegin'] <> nil then
2629    //  if e1.AsFloat32['lengthfrombegin'] > e2.AsFloat32['lengthfrombegin'] then
2630    //       result:=1
2631    //    else
2632    //       result:=-1;
2633 
2634    {if e1.AsFloat32['tt'] <> e2.AsFloat32['tt'] then
2635        if e1.AsFloat32['tt'] > e2.AsFloat32['tt'] then
2636           result:=1
2637        else
2638           result:=-1;}
2639 
2640    //тут e1 и e2 надо както сравнить по какомуто критерию и вернуть -1 0 1
2641    //в зависимости что чего меньше-больше
2642 end;
CompareEdgesnull2643 function TDummyComparer.CompareEdges (Edge1, Edge2: Pointer): Integer;
2644 var
2645   e1,e2:TAttrSet;
2646 begin
2647    ////result:=1;
2648    //e1:=TAttrSet(Edge1);
2649    //e2:=TAttrSet(Edge2);
2650    //
2651    ZCMsgCallBackInterface.TextMessage('hhhhhhhhhhhhhhhhhhhhhhhttttttttttttttttttttt,,,,hj',TMWOHistoryOut);
2652    //ZCMsgCallBackInterface.TextMessage('xxxxxxssssss'+e1.AsString[vGInfoEdge],TMWOHistoryOut);
2653        //Edge1
2654    //ZCMsgCallBackInterface.TextMessage(floattostr(e1.AsFloat32['tt']) + ' сравниваем ' + floattostr(e2.AsFloat32['tt']),TMWOHistoryOut);
2655    //   ZCMsgCallBackInterface.TextMessage(floattostr(e2.AsFloat32[vGLength]) + '   ',TMWOHistoryOut);
2656 
2657    //e1.GetAsFloat32
2658 
2659    //if e1.ClassName; AsFloat32['lengthfrombegin'] <> nil then
2660    //  if e1.AsFloat32['lengthfrombegin'] > e2.AsFloat32['lengthfrombegin'] then
2661    //       result:=1
2662    //    else
2663    //       result:=-1;
2664 
2665    {if e1.AsFloat32['tt'] <> e2.AsFloat32['tt'] then
2666        if e1.AsFloat32['tt'] > e2.AsFloat32['tt'] then
2667           result:=1
2668        else
2669           result:=-1;}
2670 
2671    //тут e1 и e2 надо както сравнить по какомуто критерию и вернуть -1 0 1
2672    //в зависимости что чего меньше-больше
2673 end;
2674 
2675 
2676 initialization
2677   //CreateCommandFastObjectPlugin(@NumPsIzvAndDlina_com,'test111',CADWG,0);
2678   CreateCommandFastObjectPlugin(@TestgraphUses_com,'test454',CADWG,0);
2679   //CreateCommandFastObjectPlugin(@TestTREEUses_com2,'test333',CADWG,0);
2680   DummyComparer:=TDummyComparer.Create;
2681 finalization
2682   DummyComparer.free;
2683 end.
2684 
2685