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/BGAFixedCourseZone.hpp"
34 #include "Task/ObservationZones/BGAEnhancedOptionZone.hpp"
35 #include "Task/ObservationZones/BGAStartSectorZone.hpp"
36 #include "Task/ObservationZones/AnnularSectorZone.hpp"
37 #include "Task/ObservationZones/MatCylinderZone.hpp"
38 #include "Task/Factory/AbstractTaskFactory.hpp"
39 #include "XML/DataNode.hpp"
40 #include "Engine/Waypoint/Waypoints.hpp"
46 Deserialiser::DeserialiseTaskpoint(OrderedTask
&data
)
48 const TCHAR
*type
= node
.GetAttribute(_T("type"));
52 std::unique_ptr
<DataNode
> wp_node(node
.GetChildNamed(_T("Waypoint")));
56 Deserialiser
wser(*wp_node
, waypoints
);
57 std::unique_ptr
<Waypoint
> wp(wser
.DeserialiseWaypoint());
61 std::unique_ptr
<DataNode
> oz_node(node
.GetChildNamed(_T("ObservationZone")));
63 AbstractTaskFactory
&fact
= data
.GetFactory();
65 ObservationZonePoint
* oz
= nullptr;
66 std::unique_ptr
<OrderedTaskPoint
> pt
;
69 bool is_turnpoint
= StringIsEqual(type
, _T("Turn")) ||
70 StringIsEqual(type
, _T("Area"));
72 Deserialiser
oser(*oz_node
, waypoints
);
73 oz
= oser
.DeserialiseOZ(*wp
, is_turnpoint
);
76 if (StringIsEqual(type
, _T("Start"))) {
77 pt
.reset(oz
!= nullptr
78 ? fact
.CreateStart(oz
, *wp
)
79 : fact
.CreateStart(*wp
));
81 } else if (StringIsEqual(type
, _T("OptionalStart"))) {
82 pt
.reset(oz
!= nullptr
83 ? fact
.CreateStart(oz
, *wp
)
84 : fact
.CreateStart(*wp
));
85 fact
.AppendOptionalStart(*pt
);
87 // don't let generic code below add it
90 } else if (StringIsEqual(type
, _T("Turn"))) {
91 pt
.reset(oz
!= nullptr
92 ? fact
.CreateASTPoint(oz
, *wp
)
93 : fact
.CreateIntermediate(*wp
));
95 } else if (StringIsEqual(type
, _T("Area"))) {
96 pt
.reset(oz
!= nullptr
97 ? fact
.CreateAATPoint(oz
, *wp
)
98 : fact
.CreateIntermediate(*wp
));
100 } else if (StringIsEqual(type
, _T("Finish"))) {
101 pt
.reset(oz
!= nullptr
102 ? fact
.CreateFinish(oz
, *wp
)
103 : fact
.CreateFinish(*wp
));
107 fact
.Append(*pt
, false);
110 ObservationZonePoint
*
111 Deserialiser::DeserialiseOZ(const Waypoint
&wp
, bool is_turnpoint
)
113 const TCHAR
*type
= node
.GetAttribute(_T("type"));
117 if (StringIsEqual(type
, _T("Line"))) {
118 LineSectorZone
*ls
= new LineSectorZone(wp
.location
);
121 if (node
.GetAttribute(_T("length"), length
) && positive(length
))
122 ls
->SetLength(length
);
125 } else if (StringIsEqual(type
, _T("Cylinder"))) {
126 CylinderZone
*ls
= new CylinderZone(wp
.location
);
129 if (node
.GetAttribute(_T("radius"), radius
) && positive(radius
))
130 ls
->SetRadius(radius
);
133 } else if (StringIsEqual(type
, _T("MatCylinder"))) {
134 MatCylinderZone
*ls
= new MatCylinderZone(wp
.location
);
137 } else if (StringIsEqual(type
, _T("Sector"))) {
139 fixed radius
, inner_radius
;
143 if (node
.GetAttribute(_T("inner_radius"), inner_radius
)) {
144 AnnularSectorZone
*als
= new AnnularSectorZone(wp
.location
);
145 als
->SetInnerRadius(inner_radius
);
148 ls
= new SectorZone(wp
.location
);
150 if (node
.GetAttribute(_T("radius"), radius
) && positive(radius
))
151 ls
->SetRadius(radius
);
152 if (node
.GetAttribute(_T("start_radial"), start
))
153 ls
->SetStartRadial(start
);
154 if (node
.GetAttribute(_T("end_radial"), end
))
155 ls
->SetEndRadial(end
);
158 } else if (StringIsEqual(type
, _T("FAISector")))
159 return new FAISectorZone(wp
.location
, is_turnpoint
);
160 else if (StringIsEqual(type
, _T("Keyhole")))
161 return new KeyholeZone(wp
.location
);
162 else if (StringIsEqual(type
, _T("BGAStartSector")))
163 return new BGAStartSectorZone(wp
.location
);
164 else if (StringIsEqual(type
, _T("BGAFixedCourse")))
165 return new BGAFixedCourseZone(wp
.location
);
166 else if (StringIsEqual(type
, _T("BGAEnhancedOption")))
167 return new BGAEnhancedOptionZone(wp
.location
);
174 Deserialiser::Deserialise(GeoPoint
&data
)
176 node
.GetAttribute(_T("longitude"), data
.longitude
);
177 node
.GetAttribute(_T("latitude"), data
.latitude
);
181 Deserialiser::DeserialiseWaypoint()
183 std::unique_ptr
<DataNode
> loc_node(node
.GetChildNamed(_T("Location")));
188 Deserialiser
lser(*loc_node
, waypoints
);
189 lser
.Deserialise(loc
);
191 const TCHAR
*name
= node
.GetAttribute(_T("name"));
193 // Turnpoints need names
196 if (waypoints
!= nullptr) {
197 // Try to find waypoint by name
198 const Waypoint
*from_database
= waypoints
->LookupName(name
);
200 // If waypoint by name found and closer than 10m to the original
201 if (from_database
!= nullptr &&
202 from_database
->location
.Distance(loc
) <= fixed(10))
203 // Use this waypoint for the task
204 return new Waypoint(*from_database
);
206 // Try finding the closest waypoint to the original one
207 from_database
= waypoints
->GetNearest(loc
, fixed(10));
209 // If closest waypoint found and closer than 10m to the original
210 if (from_database
!= nullptr &&
211 from_database
->location
.Distance(loc
) <= fixed(10))
212 // Use this waypoint for the task
213 return new Waypoint(*from_database
);
216 // Create a new waypoint from the original one
217 Waypoint
*wp
= new Waypoint(loc
);
220 node
.GetAttribute(_T("id"), wp
->id
);
222 const TCHAR
*comment
= node
.GetAttribute(_T("comment"));
223 if (comment
!= nullptr)
224 wp
->comment
.assign(comment
);
226 node
.GetAttribute(_T("altitude"), wp
->elevation
);
232 Deserialiser::Deserialise(OrderedTaskBehaviour
&data
)
234 node
.GetAttribute(_T("aat_min_time"), data
.aat_min_time
);
235 node
.GetAttribute(_T("start_max_speed"), data
.start_constraints
.max_speed
);
236 node
.GetAttribute(_T("start_max_height"), data
.start_constraints
.max_height
);
237 data
.start_constraints
.max_height_ref
=
238 GetHeightRef(_T("start_max_height_ref"));
239 data
.start_constraints
.open_time_span
=
240 node
.GetAttributeRoughTimeSpan(_T("start_open_time"),
241 _T("start_close_time"));
242 node
.GetAttribute(_T("finish_min_height"),
243 data
.finish_constraints
.min_height
);
244 data
.finish_constraints
.min_height_ref
=
245 GetHeightRef(_T("finish_min_height_ref"));
246 node
.GetAttribute(_T("fai_finish"), data
.finish_constraints
.fai_finish
);
247 data
.start_constraints
.fai_finish
= data
.finish_constraints
.fai_finish
;
251 Deserialiser::Deserialise(OrderedTask
&task
)
254 task
.SetFactory(GetTaskFactoryType());
257 OrderedTaskBehaviour beh
= task
.GetOrderedTaskBehaviour();
259 task
.SetOrderedTaskBehaviour(beh
);
261 const DataNode::List children
= node
.ListChildrenNamed(_T("Point"));
262 for (const auto &i
: children
) {
263 std::unique_ptr
<DataNode
> point_node(i
);
264 Deserialiser
pser(*point_node
, waypoints
);
265 pser
.DeserialiseTaskpoint(task
);
270 Deserialiser::GetHeightRef(const TCHAR
*nodename
) const
272 const TCHAR
*type
= node
.GetAttribute(nodename
);
273 if (type
!= nullptr && StringIsEqual(type
, _T("MSL")))
274 return AltitudeReference::MSL
;
276 return AltitudeReference::AGL
;
280 Deserialiser::GetTaskFactoryType() const
282 const TCHAR
*type
= node
.GetAttribute(_T("type"));
284 return TaskFactoryType::FAI_GENERAL
;
286 if (StringIsEqual(type
, _T("FAIGeneral")))
287 return TaskFactoryType::FAI_GENERAL
;
288 else if (StringIsEqual(type
, _T("FAITriangle")))
289 return TaskFactoryType::FAI_TRIANGLE
;
290 else if (StringIsEqual(type
, _T("FAIOR")))
291 return TaskFactoryType::FAI_OR
;
292 else if (StringIsEqual(type
, _T("FAIGoal")))
293 return TaskFactoryType::FAI_GOAL
;
294 else if (StringIsEqual(type
, _T("RT")))
295 return TaskFactoryType::RACING
;
296 else if (StringIsEqual(type
, _T("AAT")))
297 return TaskFactoryType::AAT
;
298 else if (StringIsEqual(type
, _T("MAT")))
299 return TaskFactoryType::MAT
;
300 else if (StringIsEqual(type
, _T("Mixed")))
301 return TaskFactoryType::MIXED
;
302 else if (StringIsEqual(type
, _T("Touring")))
303 return TaskFactoryType::TOURING
;
306 return TaskFactoryType::FAI_GENERAL
;