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"
42 Deserialiser::DeserialiseTaskpoint(OrderedTask
&data
)
44 const TCHAR
*type
= node
.GetAttribute(_T("type"));
48 std::unique_ptr
<DataNode
> wp_node(node
.GetChildNamed(_T("Waypoint")));
52 Deserialiser
wser(*wp_node
, waypoints
);
53 std::unique_ptr
<Waypoint
> wp(wser
.DeserialiseWaypoint());
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
;
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
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
));
103 fact
.Append(*pt
, false);
106 ObservationZonePoint
*
107 Deserialiser::DeserialiseOZ(const Waypoint
&wp
, bool is_turnpoint
)
109 const TCHAR
*type
= node
.GetAttribute(_T("type"));
113 if (StringIsEqual(type
, _T("Line"))) {
114 LineSectorZone
*ls
= new LineSectorZone(wp
.location
);
117 if (node
.GetAttribute(_T("length"), length
) && positive(length
))
118 ls
->SetLength(length
);
121 } else if (StringIsEqual(type
, _T("Cylinder"))) {
122 CylinderZone
*ls
= new CylinderZone(wp
.location
);
125 if (node
.GetAttribute(_T("radius"), radius
) && positive(radius
))
126 ls
->SetRadius(radius
);
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
;
137 if (node
.GetAttribute(_T("inner_radius"), inner_radius
)) {
138 AnnularSectorZone
*als
= new AnnularSectorZone(wp
.location
);
139 als
->SetInnerRadius(inner_radius
);
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
);
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
);
181 Deserialiser::Deserialise(GeoPoint
&data
)
183 node
.GetAttribute(_T("longitude"), data
.longitude
);
184 node
.GetAttribute(_T("latitude"), data
.latitude
);
188 Deserialiser::DeserialiseWaypoint()
190 std::unique_ptr
<DataNode
> loc_node(node
.GetChildNamed(_T("Location")));
195 Deserialiser
lser(*loc_node
, waypoints
);
196 lser
.Deserialise(loc
);
198 const TCHAR
*name
= node
.GetAttribute(_T("name"));
200 // Turnpoints need names
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
);
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
);
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
;
258 Deserialiser::Deserialise(OrderedTask
&task
)
261 task
.SetFactory(GetTaskFactoryType());
264 OrderedTaskBehaviour beh
= task
.GetOrderedTaskBehaviour();
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
);
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
;
287 Deserialiser::GetTaskFactoryType() const
289 const TCHAR
*type
= node
.GetAttribute(_T("type"));
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
;
313 return TaskFactoryType::FAI_GENERAL
;