Compare commits
No commits in common. "f12945e689acad4c5c8a8d370f446598e730b1e4" and "11326bf58591d2391fbe1fd97bd808207b571b69" have entirely different histories.
f12945e689
...
11326bf585
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,195 +1,126 @@
|
|||||||
{% load static %}
|
{% load static %}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>LDS City</title>
|
<title>LDS City</title>
|
||||||
<!-- A-Frame 1.7.0 & environment component -->
|
<script src="https://aframe.io/releases/1.4.0/aframe.min.js"></script>
|
||||||
<script src="https://aframe.io/releases/1.7.0/aframe.min.js"></script>
|
<script src="https://raw.githack.com/donmccurdy/aframe-extras/v6.0.0/dist/aframe-extras.min.js"></script>
|
||||||
<script src="https://unpkg.com/aframe-environment-component/dist/aframe-environment-component.min.js"></script>
|
</head>
|
||||||
|
<body>
|
||||||
|
<a-scene>
|
||||||
|
<!-- Preload Assets -->
|
||||||
|
<a-assets>
|
||||||
|
<img id="skyTexture" src="{% static 'textures/sky.jpg' %}" />
|
||||||
|
<img id="floorTexture" src="https://cdn.aframe.io/a-painter/images/floor.jpg" />
|
||||||
|
</a-assets>
|
||||||
|
|
||||||
<!-- 1) Simple “look-at” component to face the camera -->
|
<!-- Lighting -->
|
||||||
<script>
|
<a-entity light="type: ambient; color: #BBB"></a-entity>
|
||||||
AFRAME.registerComponent('billboard', {
|
<a-entity light="type: directional; color: #FFF; intensity: 0.6" position="0 1 0"></a-entity>
|
||||||
schema: {type: 'selector'},
|
|
||||||
tick: function () {
|
|
||||||
if (!this.data) return;
|
|
||||||
// Make this entity face the camera each frame
|
|
||||||
this.el.object3D.lookAt(this.data.object3D.position);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<a-scene shadow="type: pcfsoft"
|
|
||||||
environment="preset: forest; dressing: trees; groundColor: #777; skyType: gradient; dressingAmount: 20;">
|
|
||||||
|
|
||||||
<!-- Camera & Controls (give it an id for look-at) -->
|
<!-- Camera and Controls -->
|
||||||
<a-entity id="mainCamera" camera look-controls wasd-controls position="0 2 0"></a-entity>
|
<a-entity camera look-controls wasd-controls position="0 2 0"></a-entity>
|
||||||
|
|
||||||
<!-- Optional: Transparent ground plane (comment out if you want only environment ground) -->
|
<!-- Sky -->
|
||||||
<a-plane position="0 -0.1 0" rotation="-90 0 0"
|
<a-sky id="sky" src="#skyTexture" radius="150"></a-sky>
|
||||||
width="200" height="200"
|
|
||||||
color="#444" opacity="0.3">
|
|
||||||
</a-plane>
|
|
||||||
|
|
||||||
<!-- Buildings -->
|
<!-- Ground Plane -->
|
||||||
{% for building in city_data.buildings %}
|
<a-plane position="0 -0.1 0" rotation="-90 0 0" width="200" height="200"
|
||||||
<a-entity id="{{ building.id }}" status="{{ building.status }}">
|
material="src: #floorTexture; repeat: 100 100;"></a-plane>
|
||||||
<!-- Building geometry -->
|
|
||||||
<a-box position="{{ building.position_x }} 1 {{ building.position_z }}"
|
|
||||||
width="{{ building.width }}" height="{{ building.height }}" depth="{{ building.depth }}"
|
|
||||||
color="{{ building.color }}">
|
|
||||||
</a-box>
|
|
||||||
|
|
||||||
<!-- Label entity: plane + text, billboarded to face camera -->
|
<!-- Buildings Group -->
|
||||||
<a-entity position="{{ building.position_x }} 3 {{ building.position_z }}"
|
<a-entity id="buildings-group">
|
||||||
billboard="#mainCamera">
|
{% for building in city_data.buildings %}
|
||||||
<!-- Semi-transparent background plane -->
|
<a-entity id="building{{ building.id }}" status="{{ building.status }}"
|
||||||
<a-plane width="4" height="1.2" color="#000" opacity="0.5"></a-plane>
|
position="{{ building.position_x }} 1 {{ building.position_z }}"
|
||||||
<!-- Text in front of plane -->
|
event-set__mouseenter="_event: mouseenter; scale: 1.1 1.1 1.1"
|
||||||
<a-text value="Status: {{ building.status }}"
|
event-set__mouseleave="_event: mouseleave; scale: 1 1 1">
|
||||||
width="4"
|
<a-box width="{{ building.width }}" height="{{ building.height }}" depth="{{ building.depth }}"
|
||||||
align="center"
|
color="{{ building.color }}"></a-box>
|
||||||
color="#FFF"
|
<a-text value="Status: {{ building.status }}"
|
||||||
position="0 0 0.01">
|
position="0 {{ building.height|add:'1' }} 0"
|
||||||
</a-text>
|
scale="1.5 1.5 1.5"></a-text>
|
||||||
</a-entity>
|
</a-entity>
|
||||||
</a-entity>
|
{% endfor %}
|
||||||
{% endfor %}
|
</a-entity>
|
||||||
|
|
||||||
<!-- Lamps -->
|
<!-- Lamps Group -->
|
||||||
{% for lamp in city_data.lamps %}
|
<a-entity id="lamps-group">
|
||||||
<a-entity id="{{ lamp.id }}" status="{{ lamp.status }}" position="{{ lamp.position_x }} 1 {{ lamp.position_z }}">
|
{% for lamp in city_data.lamps %}
|
||||||
<!-- Lamp geometry -->
|
<a-entity id="lamp{{ lamp.id }}" status="{{ lamp.status }}"
|
||||||
<a-cone radius-bottom="0.1" radius-top="0.5"
|
position="{{ lamp.position_x }} 1 {{ lamp.position_z }}"
|
||||||
height="{{ lamp.height }}" color="{{ lamp.color }}">
|
event-set__mouseenter="_event: mouseenter; scale: 1.1 1.1 1.1"
|
||||||
</a-cone>
|
event-set__mouseleave="_event: mouseleave; scale: 1 1 1">
|
||||||
<a-sphere radius="0.2" color="#FFFFFF"
|
<a-cone radius-bottom="0.1" radius-top="0.5" height="{{ lamp.height }}"
|
||||||
position="0 {{ lamp.height }} 0">
|
color="{{ lamp.color }}"></a-cone>
|
||||||
</a-sphere>
|
<a-sphere radius="0.2" color="#FFFFFF" position="0 {{ lamp.height }} 0"></a-sphere>
|
||||||
|
<a-text value="Status: {{ lamp.status }}"
|
||||||
<!-- Label: billboard to camera -->
|
position="0 {{ lamp.height|add:'1' }} 0"
|
||||||
<a-entity position="0 3 0" billboard="#mainCamera">
|
scale="1.5 1.5 1.5"></a-text>
|
||||||
<a-plane width="4" height="1.2" color="#000" opacity="0.5"></a-plane>
|
|
||||||
<a-text value="Status: {{ lamp.status }}"
|
|
||||||
width="4"
|
|
||||||
align="center"
|
|
||||||
color="#FFF"
|
|
||||||
position="0 0 0.01">
|
|
||||||
</a-text>
|
|
||||||
</a-entity>
|
</a-entity>
|
||||||
</a-entity>
|
{% endfor %}
|
||||||
{% endfor %}
|
</a-entity>
|
||||||
|
|
||||||
<!-- Trees -->
|
<!-- Trees Group -->
|
||||||
{% for tree in city_data.trees %}
|
<a-entity id="trees-group">
|
||||||
<a-entity id="{{ tree.id }}" status="{{ tree.status }}" position="{{ tree.position_x }} 1 {{ tree.position_z }}">
|
{% for tree in city_data.trees %}
|
||||||
<!-- Tree trunk & leaves -->
|
<a-entity id="tree{{ tree.id }}" status="{{ tree.status }}"
|
||||||
<a-cone radius-bottom="{{ tree.radius_bottom }}"
|
position="{{ tree.position_x }} 1 {{ tree.position_z }}"
|
||||||
radius-top="{{ tree.radius_top }}"
|
event-set__mouseenter="_event: mouseenter; scale: 1.1 1.1 1.1"
|
||||||
height="{{ tree.height }}"
|
event-set__mouseleave="_event: mouseleave; scale: 1 1 1">
|
||||||
color="{{ tree.color_trunk }}">
|
<a-cone radius-bottom="{{ tree.radius_bottom }}" radius-top="{{ tree.radius_top }}"
|
||||||
</a-cone>
|
height="{{ tree.height }}" color="{{ tree.color_trunk }}"></a-cone>
|
||||||
<a-sphere radius="{{ tree.radius_top }}"
|
<a-sphere radius="{{ tree.radius_top }}" color="{{ tree.color_leaves }}"
|
||||||
color="{{ tree.color_leaves }}"
|
position="0 {{ tree.height }} 0"></a-sphere>
|
||||||
position="0 {{ tree.height }} 0">
|
<a-text value="Status: {{ tree.status }}"
|
||||||
</a-sphere>
|
position="0 {{ tree.height|add:'1' }} 0"
|
||||||
|
scale="1.5 1.5 1.5"></a-text>
|
||||||
<!-- Label: billboard to camera -->
|
|
||||||
<a-entity position="0 3 0" billboard="#mainCamera">
|
|
||||||
<a-plane width="4" height="1.2" color="#000" opacity="0.5"></a-plane>
|
|
||||||
<a-text value="Status: {{ tree.status }}"
|
|
||||||
width="4"
|
|
||||||
align="center"
|
|
||||||
color="#FFF"
|
|
||||||
position="0 0 0.01">
|
|
||||||
</a-text>
|
|
||||||
</a-entity>
|
</a-entity>
|
||||||
</a-entity>
|
{% endfor %}
|
||||||
{% endfor %}
|
</a-entity>
|
||||||
|
|
||||||
<!-- Cell Towers -->
|
<!-- Cell Towers Group -->
|
||||||
{% for tower in city_data.towers %}
|
<a-entity id="towers-group">
|
||||||
<a-entity id="tower{{ tower.id }}"
|
{% for tower in city_data.towers %}
|
||||||
position="{{ tower.position_x }} {{ tower.position_y }} {{ tower.position_z }}">
|
<a-entity id="tower{{ tower.id }}" position="{{ tower.position_x }} 0 {{ tower.position_z }}"
|
||||||
<!-- Base tower cylinder -->
|
event-set__mouseenter="_event: mouseenter; scale: 1.1 1.1 1.1"
|
||||||
<a-cylinder height="{{ tower.height }}" radius="1" color="{{ tower.color }}"></a-cylinder>
|
event-set__mouseleave="_event: mouseleave; scale: 1 1 1">
|
||||||
|
<a-cylinder height="{{ tower.height }}" radius="2" color="{{ tower.color }}"></a-cylinder>
|
||||||
<!-- Animated signal ring near top -->
|
<a-text value="📡 Tower {{ tower.id }} - {{ tower.status }}"
|
||||||
<a-ring color="#FF0000"
|
position="0 {{ tower.height|add:'1' }} 0" scale="1.5 1.5 1.5"></a-text>
|
||||||
radius-inner="2"
|
|
||||||
radius-outer="2.5"
|
|
||||||
position="0 {{ tower.height|add:'1' }} 0"
|
|
||||||
rotation="-90 0 0"
|
|
||||||
animation="property: scale; to: 1.5 1.5 1.5; dir: alternate; dur: 1000; loop: true">
|
|
||||||
</a-ring>
|
|
||||||
|
|
||||||
<!-- Tower label: billboard to camera -->
|
|
||||||
<a-entity position="0 -5 0" billboard="#mainCamera">
|
|
||||||
<a-plane width="4" height="1.2" color="#000" opacity="0.5"></a-plane>
|
|
||||||
<a-text value="📡 Tower {{ tower.id }} - {{ tower.status }}"
|
|
||||||
width="4"
|
|
||||||
align="center"
|
|
||||||
color="#FFF"
|
|
||||||
position="0 0 0.01">
|
|
||||||
</a-text>
|
|
||||||
</a-entity>
|
</a-entity>
|
||||||
</a-entity>
|
{% endfor %}
|
||||||
{% endfor %}
|
</a-entity>
|
||||||
|
|
||||||
<!-- Fiber Paths (Cylinders) -->
|
<!-- Fiber Paths Group -->
|
||||||
{% for fiber in city_data.fiber_paths %}
|
<a-entity id="fiber-paths-group">
|
||||||
<a-entity>
|
{% for fiber in city_data.fiber_paths %}
|
||||||
<a-cylinder position="{{ fiber.mid_x }} {{ fiber.mid_y }} {{ fiber.mid_z }}"
|
<a-entity id="fiber{{ fiber.id }}">
|
||||||
height="{{ fiber.length }}"
|
<a-line start="{{ fiber.start_x }} 0 {{ fiber.start_z }}"
|
||||||
radius="0.1"
|
end="{{ fiber.end_x }} 0 {{ fiber.end_z }}"
|
||||||
rotation="90 {{ fiber.angle }} 0"
|
color="{{ fiber.color }}"></a-line>
|
||||||
color="{{ fiber.color }}">
|
<a-text value="🔗 Fiber Path {{ fiber.id }} - {{ fiber.status }}"
|
||||||
</a-cylinder>
|
position="{{ fiber.start_x }} 1 {{ fiber.start_z }}"
|
||||||
|
scale="1.2 1.2 1.2"></a-text>
|
||||||
<!-- Fiber label: billboard to camera -->
|
|
||||||
<a-entity position="{{ fiber.start_x }} 3 {{ fiber.start_z }}" billboard="#mainCamera">
|
|
||||||
<a-plane width="4" height="1.2" color="#000" opacity="0.5"></a-plane>
|
|
||||||
<a-text value="🔗 Fiber Path {{ fiber.id }} - {{ fiber.status }}"
|
|
||||||
width="4"
|
|
||||||
align="center"
|
|
||||||
color="{{ fiber.color }}"
|
|
||||||
position="0 0 0.01">
|
|
||||||
</a-text>
|
|
||||||
</a-entity>
|
</a-entity>
|
||||||
</a-entity>
|
{% endfor %}
|
||||||
{% endfor %}
|
</a-entity>
|
||||||
|
|
||||||
<!-- Wi-Fi Hotspots -->
|
<!-- Wi-Fi Hotspots Group -->
|
||||||
{% for wifi in city_data.wifi_hotspots %}
|
<a-entity id="wifi-group">
|
||||||
<a-entity id="wifi{{ wifi.id }}"
|
{% for wifi in city_data.wifi_hotspots %}
|
||||||
position="{{ wifi.position_x }} {{ wifi.position_y }} {{ wifi.position_z }}">
|
<a-entity id="wifi{{ wifi.id }}" position="{{ wifi.position_x }} 0 {{ wifi.position_z }}"
|
||||||
<!-- Hotspot sphere (animated) -->
|
event-set__mouseenter="_event: mouseenter; scale: 1.1 1.1 1.1"
|
||||||
<a-sphere radius="{{ wifi.radius }}" color="{{ wifi.color }}"
|
event-set__mouseleave="_event: mouseleave; scale: 1 1 1">
|
||||||
animation="property: scale; to: 1.5 1.5 1.5; dir: alternate; dur: 1500; loop: true">
|
<a-sphere radius="2" color="{{ wifi.color }}"></a-sphere>
|
||||||
</a-sphere>
|
<a-text value="📶 WiFi {{ wifi.id }} - {{ wifi.status }}"
|
||||||
|
position="0 3 0" scale="1.2 1.2 1.2"></a-text>
|
||||||
<!-- Coverage area (fixed or dynamic) -->
|
|
||||||
<a-sphere radius="5"
|
|
||||||
color="#00FFFF"
|
|
||||||
opacity="0.2"
|
|
||||||
position="0 {{ wifi.radius }} 0">
|
|
||||||
</a-sphere>
|
|
||||||
|
|
||||||
<!-- Wi-Fi label: billboard to camera -->
|
|
||||||
<a-entity position="0 3 0" billboard="#mainCamera">
|
|
||||||
<a-plane width="4" height="1.2" color="#000" opacity="0.5"></a-plane>
|
|
||||||
<a-text value="📶 WiFi {{ wifi.id }} - {{ wifi.status }}"
|
|
||||||
width="4"
|
|
||||||
align="center"
|
|
||||||
color="#FFF"
|
|
||||||
position="0 0 0.01">
|
|
||||||
</a-text>
|
|
||||||
</a-entity>
|
</a-entity>
|
||||||
</a-entity>
|
{% endfor %}
|
||||||
{% endfor %}
|
</a-entity>
|
||||||
|
|
||||||
</a-scene>
|
</a-scene>
|
||||||
</body>
|
<script src="{% static 'js/lds_city_vr.js' %}"></script>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
153
views.py
153
views.py
@ -3,35 +3,19 @@ from django.http import Http404
|
|||||||
import random
|
import random
|
||||||
import math
|
import math
|
||||||
|
|
||||||
def get_environment_preset(lat, long):
|
|
||||||
"""
|
|
||||||
Determines the A-Frame environment preset based on latitude and longitude.
|
|
||||||
You can adjust the logic to suit your needs.
|
|
||||||
"""
|
|
||||||
# Example logic: adjust these thresholds as needed
|
|
||||||
if lat >= 60 or lat <= -60:
|
|
||||||
return 'snow' # Polar regions: snow environment
|
|
||||||
elif lat >= 30 or lat <= -30:
|
|
||||||
return 'forest' # Mid-latitudes: forest environment
|
|
||||||
elif long >= 100:
|
|
||||||
return 'goldmine' # Arbitrary example: for far east longitudes, a 'goldmine' preset
|
|
||||||
else:
|
|
||||||
return 'desert' # Default to desert for lower latitudes and moderate longitudes
|
|
||||||
|
|
||||||
def city_digital_twin(request, city_id, innovation_pct=None, technology_pct=None, science_pct=None):
|
def city_digital_twin(request, city_id, innovation_pct=None, technology_pct=None, science_pct=None):
|
||||||
try:
|
try:
|
||||||
lat = float(request.GET.get('lat', 0))
|
if city_id == "random_city":
|
||||||
long = float(request.GET.get('long', 0))
|
|
||||||
|
|
||||||
if city_id == "com_con":
|
|
||||||
city_data = generate_com_con_city_data(lat, long)
|
|
||||||
elif city_id == "random_city":
|
|
||||||
city_data = generate_random_city_data()
|
city_data = generate_random_city_data()
|
||||||
|
elif city_id == "com_con":
|
||||||
|
city_data = generate_com_con_city_data()
|
||||||
elif city_id == "dream":
|
elif city_id == "dream":
|
||||||
|
# Retrieve percentages from GET parameters if not in URL
|
||||||
innovation_pct = innovation_pct or request.GET.get('innovation', 0)
|
innovation_pct = innovation_pct or request.GET.get('innovation', 0)
|
||||||
technology_pct = technology_pct or request.GET.get('technology', 0)
|
technology_pct = technology_pct or request.GET.get('technology', 0)
|
||||||
science_pct = science_pct or request.GET.get('science', 0)
|
science_pct = science_pct or request.GET.get('science', 0)
|
||||||
|
|
||||||
|
# Convert to integers
|
||||||
innovation_pct = int(innovation_pct)
|
innovation_pct = int(innovation_pct)
|
||||||
technology_pct = int(technology_pct)
|
technology_pct = int(technology_pct)
|
||||||
science_pct = int(science_pct)
|
science_pct = int(science_pct)
|
||||||
@ -39,22 +23,22 @@ def city_digital_twin(request, city_id, innovation_pct=None, technology_pct=None
|
|||||||
city_data = generate_random_city_data(innovation_pct, technology_pct, science_pct)
|
city_data = generate_random_city_data(innovation_pct, technology_pct, science_pct)
|
||||||
else:
|
else:
|
||||||
city_data = get_city_data(city_id)
|
city_data = get_city_data(city_id)
|
||||||
|
except ValueError:
|
||||||
|
raise Http404("City data not found.")
|
||||||
|
|
||||||
if not city_data:
|
if not city_data:
|
||||||
city_data = get_example_data()
|
city_data = get_example_data()
|
||||||
|
|
||||||
preset = get_environment_preset(lat, long)
|
context = {'city_data': city_data}
|
||||||
|
return render(request, 'pxy_city_digital_twins/city_digital_twin.html', context)
|
||||||
|
|
||||||
context = {
|
|
||||||
'city_data': city_data,
|
|
||||||
'environment_preset': preset,
|
|
||||||
'lat': lat,
|
|
||||||
'long': long,
|
|
||||||
}
|
|
||||||
return render(request, 'pxy_city_digital_twins/city_digital_twin.html', context)
|
|
||||||
except (ValueError, TypeError):
|
|
||||||
raise Http404("Invalid data provided.")
|
|
||||||
|
|
||||||
|
if not city_data:
|
||||||
|
# Fallback to example data if no city data is found
|
||||||
|
city_data = get_example_data()
|
||||||
|
|
||||||
|
context = {'city_data': city_data}
|
||||||
|
return render(request, 'pxy_city_digital_twins/city_digital_twin.html', context)
|
||||||
|
|
||||||
def get_city_data(city_id):
|
def get_city_data(city_id):
|
||||||
# Implement fetching logic here
|
# Implement fetching logic here
|
||||||
@ -260,75 +244,52 @@ def generate_random_city_data(innovation_pct=100, technology_pct=100, science_pc
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_environment_by_lat(lat):
|
def generate_com_con_city_data():
|
||||||
if lat > 60 or lat < -60:
|
"""
|
||||||
return 'yeti'
|
Generates a telecom-focused digital twin for the hackathon.
|
||||||
elif 30 < lat < 60 or -30 > lat > -60:
|
It includes cell towers, fiber paths, and optimized coverage zones.
|
||||||
return 'forest'
|
"""
|
||||||
else:
|
num_towers = random.randint(3, 10)
|
||||||
return 'desert'
|
num_fiber_paths = random.randint(5, 15)
|
||||||
|
num_wifi_hotspots = random.randint(5, 20)
|
||||||
|
|
||||||
|
towers = [
|
||||||
import random
|
{
|
||||||
|
|
||||||
def generate_com_con_city_data(lat, long):
|
|
||||||
random.seed(f"{lat},{long}")
|
|
||||||
|
|
||||||
center_x = lat % 100
|
|
||||||
center_z = long % 100
|
|
||||||
|
|
||||||
grid_size = 5
|
|
||||||
spacing = 15 # Distance between objects
|
|
||||||
|
|
||||||
# Towers in a grid
|
|
||||||
towers = []
|
|
||||||
for i in range(grid_size):
|
|
||||||
for j in range(grid_size):
|
|
||||||
x = center_x + (i - grid_size // 2) * spacing
|
|
||||||
z = center_z + (j - grid_size // 2) * spacing
|
|
||||||
towers.append({
|
|
||||||
'id': len(towers) + 1,
|
|
||||||
'status': 'Active' if random.random() > 0.2 else 'Inactive',
|
|
||||||
'position_x': x,
|
|
||||||
'position_y': 0,
|
|
||||||
'position_z': z,
|
|
||||||
'height': random.randint(40, 60),
|
|
||||||
'range': random.randint(500, 1000),
|
|
||||||
'color': '#ff4500'
|
|
||||||
})
|
|
||||||
|
|
||||||
# Fiber paths connect neighboring towers
|
|
||||||
fiber_paths = []
|
|
||||||
for i in range(len(towers) - 1):
|
|
||||||
fiber_paths.append({
|
|
||||||
'id': i + 1,
|
'id': i + 1,
|
||||||
'start_x': towers[i]['position_x'],
|
'status': 'Active' if random.random() > 0.2 else 'Inactive',
|
||||||
'start_z': towers[i]['position_z'],
|
'position_x': random.uniform(-50, 50),
|
||||||
'end_x': towers[i + 1]['position_x'],
|
'position_z': random.uniform(-50, 50),
|
||||||
'end_z': towers[i + 1]['position_z'],
|
'height': random.randint(20, 50),
|
||||||
'mid_x': (towers[i]['position_x'] + towers[i + 1]['position_x']) / 2,
|
'range': random.randint(500, 1500), # Coverage range in meters
|
||||||
'mid_y': 0.1,
|
'color': '#ff4500' # Orange for telecom towers
|
||||||
'mid_z': (towers[i]['position_z'] + towers[i + 1]['position_z']) / 2,
|
}
|
||||||
'length': ((towers[i + 1]['position_x'] - towers[i]['position_x'])**2 + (towers[i + 1]['position_z'] - towers[i]['position_z'])**2)**0.5,
|
for i in range(num_towers)
|
||||||
'angle': random.uniform(0, 360),
|
]
|
||||||
|
|
||||||
|
fiber_paths = [
|
||||||
|
{
|
||||||
|
'id': i + 1,
|
||||||
|
'start_x': random.uniform(-50, 50),
|
||||||
|
'start_z': random.uniform(-50, 50),
|
||||||
|
'end_x': random.uniform(-50, 50),
|
||||||
|
'end_z': random.uniform(-50, 50),
|
||||||
'status': 'Connected' if random.random() > 0.1 else 'Broken',
|
'status': 'Connected' if random.random() > 0.1 else 'Broken',
|
||||||
'color': '#4682b4'
|
'color': '#4682b4' # Steel blue for fiber cables
|
||||||
})
|
}
|
||||||
|
for i in range(num_fiber_paths)
|
||||||
|
]
|
||||||
|
|
||||||
# Wi-Fi Hotspots scattered nearby but within grid bounds
|
wifi_hotspots = [
|
||||||
wifi_hotspots = []
|
{
|
||||||
for i in range(10):
|
|
||||||
x = center_x + random.uniform(-spacing * grid_size / 2, spacing * grid_size / 2)
|
|
||||||
z = center_z + random.uniform(-spacing * grid_size / 2, spacing * grid_size / 2)
|
|
||||||
wifi_hotspots.append({
|
|
||||||
'id': i + 1,
|
'id': i + 1,
|
||||||
'position_x': x,
|
'position_x': random.uniform(-50, 50),
|
||||||
'position_y': 1.5,
|
'position_z': random.uniform(-50, 50),
|
||||||
'position_z': z,
|
|
||||||
'status': 'Online' if random.random() > 0.2 else 'Offline',
|
'status': 'Online' if random.random() > 0.2 else 'Offline',
|
||||||
'radius': random.randint(1, 3),
|
'range': random.randint(100, 300),
|
||||||
'color': '#32cd32'
|
'color': '#32cd32' # Lime green for Wi-Fi coverage
|
||||||
})
|
}
|
||||||
|
for i in range(num_wifi_hotspots)
|
||||||
|
]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'towers': towers,
|
'towers': towers,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user