SectorZone: add attribute arc_boundary
[xcsoar.git] / src / Task / Deserialiser.cpp
blob55246c08c2a23499f69d79099bb3fb41aff76d59
1 /* Copyright_License {
3 XCSoar Glide Computer - http://www.xcsoar.org/
4 Copyright (C) 2000-2013 The XCSoar Project
5 A detailed list of copyright holders can be found in the file "AUTHORS".
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "Deserialiser.hpp"
24 #include "Task/Ordered/OrderedTaskBehaviour.hpp"
25 #include "Task/Ordered/OrderedTask.hpp"
26 #include "Task/Ordered/Points/StartPoint.hpp"
27 #include "Task/Ordered/Points/FinishPoint.hpp"
28 #include "Task/Ordered/Points/AATPoint.hpp"
29 #include "Task/Ordered/Points/ASTPoint.hpp"
30 #include "Task/ObservationZones/LineSectorZone.hpp"
31 #include "Task/ObservationZones/FAISectorZone.hpp"
32 #include "Task/ObservationZones/KeyholeZone.hpp"
33 #include "Task/ObservationZones/AnnularSectorZone.hpp"
34 #include "Task/Factory/AbstractTaskFactory.hpp"
35 #include "XML/DataNode.hpp"
36 #include "Engine/Waypoint/Waypoints.hpp"
38 #include <assert.h>
39 #include <memory>
41 void
42 Deserialiser::DeserialiseTaskpoint(OrderedTask &data)
44 const TCHAR *type = node.GetAttribute(_T("type"));
45 if (type == nullptr)
46 return;
48 std::unique_ptr<DataNode> wp_node(node.GetChildNamed(_T("Waypoint")));
49 if (!wp_node)
50 return;
52 Deserialiser wser(*wp_node, waypoints);
53 std::unique_ptr<Waypoint> wp(wser.DeserialiseWaypoint());
54 if (!wp)
55 return;
57 std::unique_ptr<DataNode> oz_node(node.GetChildNamed(_T("ObservationZone")));
59 AbstractTaskFactory &fact = data.GetFactory();
61 ObservationZonePoint* oz = nullptr;
62 std::unique_ptr<OrderedTaskPoint> pt;
64 if (oz_node) {
65 bool is_turnpoint = StringIsEqual(type, _T("Turn")) ||
66 StringIsEqual(type, _T("Area"));
68 Deserialiser oser(*oz_node, waypoints);
69 oz = oser.DeserialiseOZ(*wp, is_turnpoint);
72 if (StringIsEqual(type, _T("Start"))) {
73 pt.reset(oz != nullptr
74 ? fact.CreateStart(oz, *wp)
75 : fact.CreateStart(*wp));
77 } else if (StringIsEqual(type, _T("OptionalStart"))) {
78 pt.reset(oz != nullptr
79 ? fact.CreateStart(oz, *wp)
80 : fact.CreateStart(*wp));
81 fact.AppendOptionalStart(*pt);
83 // don't let generic code below add it
84 pt.reset();
86 } else if (StringIsEqual(type, _T("Turn"))) {
87 pt.reset(oz != nullptr
88 ? fact.CreateASTPoint(oz, *wp)
89 : fact.CreateIntermediate(*wp));
91 } else if (StringIsEqual(type, _T("Area"))) {
92 pt.reset(oz != nullptr
93 ? fact.CreateAATPoint(oz, *wp)
94 : fact.CreateIntermediate(*wp));
96 } else if (StringIsEqual(type, _T("Finish"))) {
97 pt.reset(oz != nullptr
98 ? fact.CreateFinish(oz, *wp)
99 : fact.CreateFinish(*wp));
102 if (pt)
103 fact.Append(*pt, false);
106 ObservationZonePoint*
107 Deserialiser::DeserialiseOZ(const Waypoint &wp, bool is_turnpoint)
109 const TCHAR *type = node.GetAttribute(_T("type"));
110 if (type == nullptr)
111 return nullptr;
113 if (StringIsEqual(type, _T("Line"))) {
114 LineSectorZone *ls = new LineSectorZone(wp.location);
116 fixed length;
117 if (node.GetAttribute(_T("length"), length) && positive(length))
118 ls->SetLength(length);
120 return ls;
121 } else if (StringIsEqual(type, _T("Cylinder"))) {
122 CylinderZone *ls = new CylinderZone(wp.location);
124 fixed radius;
125 if (node.GetAttribute(_T("radius"), radius) && positive(radius))
126 ls->SetRadius(radius);
128 return ls;
129 } else if (StringIsEqual(type, _T("MatCylinder"))) {
130 return CylinderZone::CreateMatCylinderZone(wp.location);
131 } else if (StringIsEqual(type, _T("Sector"))) {
133 fixed radius, inner_radius;
134 Angle start, end;
135 SectorZone *ls;
137 if (node.GetAttribute(_T("inner_radius"), inner_radius)) {
138 AnnularSectorZone *als = new AnnularSectorZone(wp.location);
139 als->SetInnerRadius(inner_radius);
140 ls = als;
141 } else
142 ls = new SectorZone(wp.location);
144 if (node.GetAttribute(_T("radius"), radius) && positive(radius))
145 ls->SetRadius(radius);
146 if (node.GetAttribute(_T("start_radial"), start))
147 ls->SetStartRadial(start);
148 if (node.GetAttribute(_T("end_radial"), end))
149 ls->SetEndRadial(end);
151 return ls;
152 } else if (StringIsEqual(type, _T("FAISector")))
153 return new FAISectorZone(wp.location, is_turnpoint);
154 else if (StringIsEqual(type, _T("SymmetricQuadrant"))) {
155 fixed radius = fixed(10000);
156 node.GetAttribute(_T("radius"), radius);
158 return new SymmetricSectorZone(wp.location, radius);
159 } else if (StringIsEqual(type, _T("Keyhole")))
160 return KeyholeZone::CreateDAeCKeyholeZone(wp.location);
161 else if (StringIsEqual(type, _T("CustomKeyhole"))) {
162 fixed radius = fixed(10000);
163 Angle angle = Angle::QuarterCircle();
165 node.GetAttribute(_T("radius"), radius);
166 node.GetAttribute(_T("angle"), angle);
168 return KeyholeZone::CreateCustomKeyholeZone(wp.location, radius, angle);
169 } else if (StringIsEqual(type, _T("BGAStartSector")))
170 return KeyholeZone::CreateBGAStartSectorZone(wp.location);
171 else if (StringIsEqual(type, _T("BGAFixedCourse")))
172 return KeyholeZone::CreateBGAFixedCourseZone(wp.location);
173 else if (StringIsEqual(type, _T("BGAEnhancedOption")))
174 return KeyholeZone::CreateBGAEnhancedOptionZone(wp.location);
176 assert(1);
177 return nullptr;
180 void
181 Deserialiser::Deserialise(GeoPoint &data)
183 node.GetAttribute(_T("longitude"), data.longitude);
184 node.GetAttribute(_T("latitude"), data.latitude);
187 Waypoint*
188 Deserialiser::DeserialiseWaypoint()
190 std::unique_ptr<DataNode> loc_node(node.GetChildNamed(_T("Location")));
191 if (!loc_node)
192 return nullptr;
194 GeoPoint loc;
195 Deserialiser lser(*loc_node, waypoints);
196 lser.Deserialise(loc);
198 const TCHAR *name = node.GetAttribute(_T("name"));
199 if (name == nullptr)
200 // Turnpoints need names
201 return nullptr;
203 if (waypoints != nullptr) {
204 // Try to find waypoint by name
205 const Waypoint *from_database = waypoints->LookupName(name);
207 // If waypoint by name found and closer than 10m to the original
208 if (from_database != nullptr &&
209 from_database->location.Distance(loc) <= fixed(10))
210 // Use this waypoint for the task
211 return new Waypoint(*from_database);
213 // Try finding the closest waypoint to the original one
214 from_database = waypoints->GetNearest(loc, fixed(10));
216 // If closest waypoint found and closer than 10m to the original
217 if (from_database != nullptr &&
218 from_database->location.Distance(loc) <= fixed(10))
219 // Use this waypoint for the task
220 return new Waypoint(*from_database);
223 // Create a new waypoint from the original one
224 Waypoint *wp = new Waypoint(loc);
225 wp->name = name;
227 node.GetAttribute(_T("id"), wp->id);
229 const TCHAR *comment = node.GetAttribute(_T("comment"));
230 if (comment != nullptr)
231 wp->comment.assign(comment);
233 node.GetAttribute(_T("altitude"), wp->elevation);
235 return wp;
238 void
239 Deserialiser::Deserialise(OrderedTaskBehaviour &data)
241 node.GetAttribute(_T("aat_min_time"), data.aat_min_time);
242 node.GetAttribute(_T("start_max_speed"), data.start_constraints.max_speed);
243 node.GetAttribute(_T("start_max_height"), data.start_constraints.max_height);
244 data.start_constraints.max_height_ref =
245 GetHeightRef(_T("start_max_height_ref"));
246 data.start_constraints.open_time_span =
247 node.GetAttributeRoughTimeSpan(_T("start_open_time"),
248 _T("start_close_time"));
249 node.GetAttribute(_T("finish_min_height"),
250 data.finish_constraints.min_height);
251 data.finish_constraints.min_height_ref =
252 GetHeightRef(_T("finish_min_height_ref"));
253 node.GetAttribute(_T("fai_finish"), data.finish_constraints.fai_finish);
254 data.start_constraints.fai_finish = data.finish_constraints.fai_finish;
257 void
258 Deserialiser::Deserialise(OrderedTask &task)
260 task.Clear();
261 task.SetFactory(GetTaskFactoryType());
262 task.Reset();
264 OrderedTaskBehaviour beh = task.GetOrderedTaskBehaviour();
265 Deserialise(beh);
266 task.SetOrderedTaskBehaviour(beh);
268 const DataNode::List children = node.ListChildrenNamed(_T("Point"));
269 for (const auto &i : children) {
270 std::unique_ptr<DataNode> point_node(i);
271 Deserialiser pser(*point_node, waypoints);
272 pser.DeserialiseTaskpoint(task);
276 AltitudeReference
277 Deserialiser::GetHeightRef(const TCHAR *nodename) const
279 const TCHAR *type = node.GetAttribute(nodename);
280 if (type != nullptr && StringIsEqual(type, _T("MSL")))
281 return AltitudeReference::MSL;
283 return AltitudeReference::AGL;
286 TaskFactoryType
287 Deserialiser::GetTaskFactoryType() const
289 const TCHAR *type = node.GetAttribute(_T("type"));
290 if (type == nullptr)
291 return TaskFactoryType::FAI_GENERAL;
293 if (StringIsEqual(type, _T("FAIGeneral")))
294 return TaskFactoryType::FAI_GENERAL;
295 else if (StringIsEqual(type, _T("FAITriangle")))
296 return TaskFactoryType::FAI_TRIANGLE;
297 else if (StringIsEqual(type, _T("FAIOR")))
298 return TaskFactoryType::FAI_OR;
299 else if (StringIsEqual(type, _T("FAIGoal")))
300 return TaskFactoryType::FAI_GOAL;
301 else if (StringIsEqual(type, _T("RT")))
302 return TaskFactoryType::RACING;
303 else if (StringIsEqual(type, _T("AAT")))
304 return TaskFactoryType::AAT;
305 else if (StringIsEqual(type, _T("MAT")))
306 return TaskFactoryType::MAT;
307 else if (StringIsEqual(type, _T("Mixed")))
308 return TaskFactoryType::MIXED;
309 else if (StringIsEqual(type, _T("Touring")))
310 return TaskFactoryType::TOURING;
312 assert(1);
313 return TaskFactoryType::FAI_GENERAL;