1 # Copyright 2023 highstreet technologies GmbH
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
18 A Class representing a 3GPP new radio cell du (NrCellDu)
20 import xml.etree.ElementTree as ET
21 from typing import Any, cast
23 import network_generation.model.python.hexagon as Hexagon
24 from network_generation.model.python.geo_location import (
28 from network_generation.model.python.o_ran_node import IORanNode, ORanNode
29 from network_generation.model.python.o_ran_termination_point import (
32 from network_generation.model.python.point import Point
35 # Define the "INrCellDu" interface
36 class INrCellDu(IORanNode):
41 default_value: INrCellDu = cast(
45 **{"cellAngle": 120, "azimuth": 120},
50 # Define an abstract O-RAN Node class
51 class NrCellDu(ORanNode):
54 data: dict[str, Any] = cast(dict[str, Any], default_value),
55 **kwargs: dict[str, Any]
57 cell_data: INrCellDu = self._to_cell_data(data)
58 super().__init__(cast(dict[str, Any], cell_data), **kwargs)
59 self._cell_angle: int = int(str(cell_data["cellAngle"]))
60 self._azimuth: int = int(str(cell_data["azimuth"]))
62 def _to_cell_data(self, data: dict[str, Any]) -> INrCellDu:
63 result: INrCellDu = default_value
64 for key, key_type in INrCellDu.__annotations__.items():
66 result[key] = data[key] # type: ignore
69 def termination_points(self) -> list[ORanTerminationPoint]:
70 result: list[ORanTerminationPoint] = super().termination_points()
72 ORanTerminationPoint({"id": self.name, "name": self.name})
76 def to_topology_nodes(self) -> list[dict[str, Any]]:
77 # a cell is not a node it is a Termination Point
78 result: list[dict[str, Any]] = [] # super().to_topology_nodes()
81 def to_topology_links(self) -> list[dict[str, Any]]:
82 # as a cell is not a node, it does not have links
83 result: list[dict[str, Any]] = [] # super().to_topology_links()
86 def toKml(self) -> ET.Element:
87 placemark: ET.Element = ET.Element("Placemark")
88 name: ET.Element = ET.SubElement(placemark, "name")
90 style: ET.Element = ET.SubElement(placemark, "styleUrl")
91 style.text = "#" + self.__class__.__name__
92 multi_geometry: ET.Element = ET.SubElement(placemark, "MultiGeometry")
93 polygon: ET.Element = ET.SubElement(multi_geometry, "Polygon")
94 outer_boundary: ET.Element = ET.SubElement(polygon, "outerBoundaryIs")
95 linear_ring: ET.Element = ET.SubElement(outer_boundary, "LinearRing")
96 coordinates: ET.Element = ET.SubElement(linear_ring, "coordinates")
98 points: list[Point] = Hexagon.polygon_corners(
99 self.layout, self.position
102 self.parent.parent.parent.parent.parent.parent
103 .geo_location.point_to_geo_location
105 geo_locations: list[GeoLocation] = list(map(method, points))
108 index: int = 1 + int(self._azimuth / self._cell_angle)
109 network_center: GeoLocation = (
110 self.parent.parent.parent.parent.parent.parent.geo_location
113 intersect1: Point = Point(
114 (points[(2 * index + 1) % 6].x + points[(2 * index + 2) % 6].x)
116 (points[(2 * index + 1) % 6].y + points[(2 * index + 2) % 6].y)
119 intersect_geo_location1: GeoLocation = (
120 network_center.point_to_geo_location(intersect1)
123 intersect2: Point = Point(
124 (points[(2 * index + 3) % 6].x + points[(2 * index + 4) % 6].x)
126 (points[(2 * index + 3) % 6].y + points[(2 * index + 4) % 6].y)
129 intersect_geo_location2: GeoLocation = (
130 network_center.point_to_geo_location(intersect2)
133 tower: GeoLocation = GeoLocation(cast(IGeoLocation, self.geo_location))
134 # TODO: Why a cast is required
136 cell_polygon: list[GeoLocation] = []
137 cell_polygon.append(tower)
138 cell_polygon.append(intersect_geo_location1)
139 cell_polygon.append(geo_locations[(2 * index + 2) % 6])
140 cell_polygon.append(geo_locations[(2 * index + 3) % 6])
141 cell_polygon.append(intersect_geo_location2)
143 cell_polygon.append(tower)
145 for gl in cell_polygon:
148 str("%.6f" % float(gl.longitude)),
149 str("%.6f" % float(gl.latitude)),
150 str("%.6f" % float(gl.aboveMeanSeaLevel)),
152 text.append(",".join(strs))
153 coordinates.text = " ".join(text)
157 def toSvg(self) -> ET.Element:
158 return ET.Element("to-be-implemented")