private List<int> PlaceHorizontally(Sheet sheet, Graphic graphic, E3Text text, Point placePosition, E3Font smallFont, E3Font bigFont)
 {
     List<int> groupIds = new List<int>(6);
     int sheetId = sheet.Id;
     double x = sheet.MoveLeft(placePosition.X, Size.Width / 2);
     double y = sheet.MoveDown(placePosition.Y, bigOffset + smallFontHeight);
     groupIds.Add(text.CreateText(sheetId, cableInfo.Type, x, y, smallFont));
     double x2 = sheet.MoveRight(x, typeTextWidth + smallOffset);
     groupIds.Add(graphic.CreateLine(sheetId, x, placePosition.Y, x2, placePosition.Y, lineHeight,connectionColorIndex));
     double radius = diameter / 2;
     double halfNameTextWidth = nameTextWidth / 2;
     x = sheet.MoveRight(x2, radius - halfNameTextWidth + ovalLength / 2);
     y = sheet.MoveDown(placePosition.Y, bigFontHeight / 2);
     groupIds.Add(text.CreateText(sheetId, cableInfo.Name, x, y, bigFont));
     x = sheet.MoveRight(x2, radius);
     if (isCircle)
     {
         groupIds.Add(graphic.CreateCircle(sheetId, x, placePosition.Y, radius));
         x = sheet.MoveRight(x, radius);
     }
     else
     {
         groupIds.Add(graphic.CreateArc(sheetId, x, placePosition.Y, radius, 90, 270));
         double y1 = sheet.MoveUp(placePosition.Y, radius);
         double y2 = sheet.MoveDown(placePosition.Y, radius);
         x2 = sheet.MoveRight(x, ovalLength);
         groupIds.Add(graphic.CreateLine(sheetId, x, y1, x2, y1));
         groupIds.Add(graphic.CreateLine(sheetId, x, y2, x2, y2));
         groupIds.Add(graphic.CreateArc(sheetId, x2, placePosition.Y, radius, 270, 90));
         x = sheet.MoveRight(x2, radius);
     }
     x2 = sheet.MoveRight(x, smallOffset + lengthTextWidth);
     groupIds.Add(graphic.CreateLine(sheetId, x, placePosition.Y, x2, placePosition.Y, lineHeight,connectionColorIndex));
     x = sheet.MoveRight(x, smallOffset);
     y = sheet.MoveUp(placePosition.Y, bigOffset);
     groupIds.Add(text.CreateText(sheetId, cableInfo.Length, x, y, smallFont));
     PlacedPosition = placePosition;
     return groupIds;
 }
 private List<int> PlaceVertically(Sheet sheet, Graphic graphic, E3Text text, Point placePosition, E3Font smallFont, E3Font bigFont)
 {
     List<int> groupIds = new List<int>(5);
     int sheetId = sheet.Id;
     double radius = diameter / 2;
     double x, y2;
     double y = sheet.MoveUp(placePosition.Y, Size.Height / 2 - radius);
     if (isCircle)
     {
         groupIds.Add(graphic.CreateCircle(sheetId, placePosition.X, y, radius));
     }
     else
     {
         x = sheet.MoveLeft(placePosition.X, ovalLength / 2);
         groupIds.Add(graphic.CreateArc(sheetId, x, y, radius, 90, 270));
         double x2 = sheet.MoveRight(x, ovalLength);
         groupIds.Add(graphic.CreateArc(sheetId, x2, y, radius, 270, 90));
         y = sheet.MoveDown(y, radius);
         y2 = sheet.MoveUp(y, 2 * radius);
         groupIds.Add(graphic.CreateLine(sheetId, x, y, x2, y));
         groupIds.Add(graphic.CreateLine(sheetId, x, y2, x2, y2));
         y = sheet.MoveUp(y, radius);
     }
     x = sheet.MoveLeft(placePosition.X, nameTextWidth / 2);
     y = sheet.MoveDown(y, bigFontHeight / 2);
     groupIds.Add(text.CreateText(sheetId, cableInfo.Name, x,y, bigFont));
     y = sheet.MoveDown(y, radius - bigFontHeight/2);
     y2 = sheet.MoveDown(y, smallOffset + Math.Max(typeTextWidth, lengthTextWidth));
     groupIds.Add(graphic.CreateLine(sheetId, placePosition.X, y, placePosition.X, y2, lineHeight,connectionColorIndex));
     y = sheet.MoveDown(y, smallOffset+typeTextWidth);
     x = sheet.MoveLeft(placePosition.X, bigOffset);
     groupIds.Add(text.CreateVerticalText(sheetId, cableInfo.Type, x, y, smallFont));
     x = sheet.MoveRight(placePosition. X, bigOffset + smallFontHeight);
     y = sheet.MoveUp(y, typeTextWidth - lengthTextWidth);
     groupIds.Add(text.CreateVerticalText(sheetId, cableInfo.Length, x, y, smallFont));
     PlacedPosition = placePosition;
     return groupIds;
 }
 private void PlaceConnectionLines(Sheet sheet, Graphic graphic, double topGroupOrdinate, double bottomGroupOrdinate)
 {
     double lineHeight = 0.2;
     int sheetId = sheet.Id;
     foreach (ISchemeSymbol symbol in symbolById.Values)
     {
         List<CableLayout> bottomLayouts = symbol.CableLayoutById.Values.Where(cl => cl.Level == Level.Bottom).ToList();
         int bottomLayoutsCount = bottomLayouts.Count();
         if (bottomLayoutsCount > 0)
         {
             double lastCableLayoutY = (symbol.Level == Level.Bottom) ? sheet.MoveDown(bottomGroupOrdinate, bottomGroupBottomMargin) : sheet.MoveDown(topGroupOrdinate, topGroupBottomMargin);
             List<CableSymbol> bottomSymbols = bottomLayouts.Select(bl => cableSymbolById[bl.Id]).ToList();
             bottomSymbols.Sort((bs1, bs2) => bs1.PlacedPosition.X.CompareTo(bs2.PlacedPosition.X));
             List<List<double>> connectionAbscisses = new List<List<double>>(bottomLayoutsCount);
             foreach (CableSymbol cableSymbol in bottomSymbols)
                 connectionAbscisses.Add(GetAbscisses(cableSymbol.PlacedPosition.X, symbol.CableLayoutById[cableSymbol.CableId]));
             List<int> maxPositions = new List<int>(bottomLayoutsCount);
             connectionAbscisses.ForEach(l => maxPositions.Add(l.Count));
             Dictionary<int, double> abscissesByCableId = GetAbscissesByCableId(maxPositions, connectionAbscisses, bottomSymbols, bottomLayouts, symbol);
             foreach (int cableId in abscissesByCableId.Keys)
             {
                 double absciss = abscissesByCableId[cableId];
                 CableLayout cableLayout = symbol.CableLayoutById[cableId];
                 double cableLayoutY = cableLayout.PlacedPoints.First().Y;
                 if (cableLayout.StartOffsets.Count > 1)
                     graphic.CreateArc(sheetId, absciss, cableLayoutY, radius, 180, 0, lineHeight, connectionColorIndex);
             }
             IEnumerable<CableSymbol> bottomHorizontalSymbols = bottomSymbols.Where(bs => bs.Orientation == Orientation.Horizontal);
             int horizontalCount = bottomHorizontalSymbols.Count();
             if (horizontalCount == 1)
             {
                 CableSymbol cableSymbol = bottomHorizontalSymbols.First();
                 int cableId = cableSymbol.CableId;
                 CableLayout cableLayout = symbol.CableLayoutById[cableId];
                 double firstLayoutPlacedY = cableLayout.PlacedPoints.First().Y;
                 if (cableLayout.StartOffsets.Count > 1)
                     firstLayoutPlacedY = sheet.MoveDown(firstLayoutPlacedY, radius);
                 CreateStraightConnectingLine(sheet, graphic, lineHeight, sheetId, abscissesByCableId, firstLayoutPlacedY, cableSymbol);
             }
             if (horizontalCount == 2)
             {
                 CableSymbol firstCableSymbol = bottomHorizontalSymbols.First();
                 int firstCableId = firstCableSymbol.CableId;
                 double firstAbsciss = abscissesByCableId[firstCableId];
                 CableLayout firstCableLayout = symbol.CableLayoutById[firstCableId];
                 double firstLayoutPlacedY = firstCableLayout.PlacedPoints.First().Y;
                 if (firstCableLayout.StartOffsets.Count > 1)
                     firstLayoutPlacedY = sheet.MoveDown(firstLayoutPlacedY, radius);
                 CableSymbol secondCableSymbol = bottomHorizontalSymbols.Last();
                 int secondCableId = secondCableSymbol.CableId;
                 double secondAbsciss = abscissesByCableId[secondCableId];
                 CableLayout secondCableLayout = symbol.CableLayoutById[secondCableId];
                 double secondLayoutPlacedY = secondCableLayout.PlacedPoints.First().Y;
                 if (secondCableLayout.StartOffsets.Count > 1)
                     secondLayoutPlacedY = sheet.MoveDown(secondLayoutPlacedY, radius);
                 if ((firstCableSymbol.PlacedPosition.X > secondCableSymbol.PlacedPosition.X && firstAbsciss > secondAbsciss) || (firstCableSymbol.PlacedPosition.X < secondCableSymbol.PlacedPosition.X && firstAbsciss < secondAbsciss))
                 {
                     CreateStraightConnectingLine(sheet, graphic, lineHeight, sheetId, abscissesByCableId, firstLayoutPlacedY, firstCableSymbol);
                     CreateStraightConnectingLine(sheet, graphic, lineHeight, sheetId, abscissesByCableId, secondLayoutPlacedY, secondCableSymbol);
                 }
                 else
                 {
                     CableSymbol straightSymbol, turningSymbol;
                     double straightLayouPlacedY, turningLayoutPlacedY;
                     if (firstCableSymbol.PlacedPosition.X < secondCableSymbol.PlacedPosition.X)
                     {
                         straightSymbol = firstCableSymbol;
                         turningSymbol = secondCableSymbol;
                         straightLayouPlacedY = firstLayoutPlacedY;
                         turningLayoutPlacedY = secondLayoutPlacedY;
                     }
                     else
                     {
                         straightSymbol = secondCableSymbol;
                         turningSymbol = firstCableSymbol;
                         straightLayouPlacedY = secondLayoutPlacedY;
                         turningLayoutPlacedY = firstLayoutPlacedY;
                     }
                     CreateStraightConnectingLine(sheet, graphic, lineHeight, sheetId, abscissesByCableId, straightLayouPlacedY, straightSymbol);
                     CreateTurningConnectingLine(sheet, graphic, lineHeight, sheetId, abscissesByCableId, turningLayoutPlacedY, turningSymbol, symbol);
                 }
             }
             IEnumerable<CableSymbol> bottomVerticalSymbols = bottomSymbols.Where(bs => bs.Orientation == Orientation.Vertical);
             if (bottomVerticalSymbols.Count() > 0)
             {
                 double centerX = (bottomVerticalSymbols.Min(bs => bs.PlacedPosition.X) + bottomVerticalSymbols.Max(bs => bs.PlacedPosition.X)) / 2;
                 List<CableSymbol> leftSymbols = bottomVerticalSymbols.Where(ls => ls.PlacedPosition.X < abscissesByCableId[ls.CableId]).ToList();
                 List<CableSymbol> rightSymbols = bottomVerticalSymbols.Where(rs => rs.PlacedPosition.X > abscissesByCableId[rs.CableId]).ToList();
                 CableSymbol cableSymbol = bottomVerticalSymbols.First();
                 double symbolY = sheet.MoveUp(cableSymbol.PlacedPosition.Y, cableSymbol.Size.Height / 2);
                 double centerY = (lastCableLayoutY + symbolY) / 2;
                 double leftTurnY = sheet.MoveDown(centerY, (leftSymbols.Count - 1) * gridStep / 2);
                 double rightTurnY = sheet.MoveDown(centerY, (rightSymbols.Count - 1) * gridStep / 2);
                 PlaceSideSymbolsConnectionLine(symbol, sheet, graphic, lineHeight, sheetId, abscissesByCableId, centerX, leftSymbols, leftTurnY, Level.Top);
                 PlaceSideSymbolsConnectionLine(symbol, sheet, graphic, lineHeight, sheetId, abscissesByCableId, centerX, rightSymbols, rightTurnY, Level.Top);
             }
         }
         List<CableLayout> topLayouts = symbol.CableLayoutById.Values.Where(cl => cl.Level == Level.Top).ToList();
         int topLayoutsCount = topLayouts.Count();
         if (topLayoutsCount > 0)
         {
             double lastCableLayoutY = topLayouts.Where(tl=>tl.verticalOffset == topLayouts.Max(t => t.verticalOffset)).First().PlacedPoints.First().Y;
             List<CableSymbol> topSymbols = topLayouts.Select(tl => cableSymbolById[tl.Id]).ToList();
             topSymbols.Sort((ts1, ts2) => ts1.PlacedPosition.X.CompareTo(ts2.PlacedPosition.X));
             List<List<double>> connectionAbscisses = new List<List<double>>(bottomLayoutsCount);
             foreach (CableSymbol cableSymbol in topSymbols)
                 connectionAbscisses.Add(GetAbscisses(cableSymbol.PlacedPosition.X, symbol.CableLayoutById[cableSymbol.CableId]));
             List<int> maxPositions = new List<int>(topLayoutsCount);
             connectionAbscisses.ForEach(l => maxPositions.Add(l.Count));
             Dictionary<int, double> abscissesByCableId = GetAbscissesByCableId(maxPositions, connectionAbscisses, topSymbols, topLayouts, symbol);
             foreach (int cableId in abscissesByCableId.Keys)
             {
                 double absciss = abscissesByCableId[cableId];
                 CableLayout cableLayout = symbol.CableLayoutById[cableId];
                 double cableLayoutY = cableLayout.PlacedPoints.First().Y;
                 if (cableLayout.StartOffsets.Count > 1)
                     graphic.CreateArc(sheetId, absciss, cableLayoutY, radius, 0, 180, lineHeight, connectionColorIndex);
             }
             double centerX = (topSymbols.Min(ts => ts.PlacedPosition.X) + topSymbols.Max(ts => ts.PlacedPosition.X)) / 2;
             List<CableSymbol> leftSymbols = topSymbols.Where(ts => ts.PlacedPosition.X <= abscissesByCableId[ts.CableId]).ToList();
             List<CableSymbol> rightSymbols = topSymbols.Where(ts => ts.PlacedPosition.X > abscissesByCableId[ts.CableId]).ToList();
             PlaceSideSymbolsConnectionLine(symbol, sheet, graphic, lineHeight, sheetId, abscissesByCableId, centerX, leftSymbols, lastCableLayoutY, Level.Bottom);
             PlaceSideSymbolsConnectionLine(symbol, sheet, graphic, lineHeight, sheetId, abscissesByCableId, centerX, rightSymbols, lastCableLayoutY, Level.Bottom);
         }
     }
 }