Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ | |
2 /* | |
3 * Copyright (c) 2008 INESC Porto | |
4 * | |
5 * This program is free software; you can redistribute it and/or modify | |
6 * it under the terms of the GNU General Public License version 2 as | |
7 * published by the Free Software Foundation; | |
8 * | |
9 * This program is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 * GNU General Public License for more details. | |
13 * | |
14 * You should have received a copy of the GNU General Public License | |
15 * along with this program; if not, write to the Free Software | |
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
17 * | |
18 * Author: Gustavo Carneiro <gjc@inescporto.pt> | |
19 */ | |
20 | |
21 #include <stdlib.h> | |
22 #include "pyviz.h" | |
23 #include "ns3/simulator.h" | |
24 #include "ns3/config.h" | |
25 #include "ns3/node-list.h" | |
26 #include "ns3/wifi-net-device.h" | |
27 #include "ns3/ppp-header.h" | |
28 #include "ns3/wifi-mac-header.h" | |
29 #include "ns3/ethernet-header.h" | |
30 #include "ns3/log.h" | |
31 #include "ns3/abort.h" | |
32 | |
33 #include <sstream> | |
34 | |
35 NS_LOG_COMPONENT_DEFINE ("PyViz"); | |
36 #define NUM_LAST_PACKETS 10 | |
37 | |
38 static | |
39 std::vector<std::string> | |
40 PathSplit (std::string str) | |
41 { | |
42 std::vector<std::string> results; | |
43 size_t cutAt; | |
44 while ((cutAt = str.find_first_of('/')) != str.npos) | |
45 { | |
46 if(cutAt > 0) | |
47 { | |
48 results.push_back(str.substr(0,cutAt)); | |
49 } | |
50 str = str.substr(cutAt+1); | |
51 } | |
52 if (str.length() > 0) | |
53 { | |
54 results.push_back(str); | |
55 } | |
56 return results; | |
57 } | |
58 | |
59 | |
60 namespace ns3 { | |
61 | |
62 static PyViz* g_visualizer = NULL; | |
63 | |
64 | |
65 | |
66 struct PyVizPacketTag : public Tag | |
67 { | |
68 static TypeId GetTypeId (void); | |
69 virtual TypeId GetInstanceTypeId (void) const; | |
70 virtual uint32_t GetSerializedSize (void) const; | |
71 virtual void Serialize (TagBuffer buf) const; | |
72 virtual void Deserialize (TagBuffer buf); | |
73 virtual void Print (std::ostream &os) const; | |
74 PyVizPacketTag (); | |
75 | |
76 uint32_t m_packetId; | |
77 }; | |
78 | |
79 | |
80 TypeId· | |
81 PyVizPacketTag::GetTypeId (void) | |
82 { | |
83 static TypeId tid = TypeId ("ns3::PyVizPacketTag") | |
84 .SetParent<Tag> () | |
85 .AddConstructor<PyVizPacketTag> () | |
86 ; | |
87 return tid; | |
88 } | |
89 TypeId· | |
90 PyVizPacketTag::GetInstanceTypeId (void) const | |
91 { | |
92 return GetTypeId (); | |
93 } | |
94 uint32_t· | |
95 PyVizPacketTag::GetSerializedSize (void) const | |
96 { | |
97 return 4; | |
98 } | |
99 void· | |
100 PyVizPacketTag::Serialize (TagBuffer buf) const | |
101 { | |
102 buf.WriteU32 (m_packetId); | |
103 } | |
104 void· | |
105 PyVizPacketTag::Deserialize (TagBuffer buf) | |
106 { | |
107 m_packetId = buf.ReadU32 (); | |
108 } | |
109 void· | |
110 PyVizPacketTag::Print (std::ostream &os) const | |
111 { | |
112 os << "PacketId=" << m_packetId; | |
113 } | |
114 PyVizPacketTag::PyVizPacketTag () | |
115 : Tag ()· | |
116 {} | |
117 | |
118 | |
119 | |
120 PyViz::PyViz () | |
121 { | |
122 NS_ASSERT (g_visualizer == NULL); | |
123 g_visualizer = this; | |
124 | |
125 Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/MacTx", | |
126 MakeCallback (&PyViz::TraceNetDevTxWifi, this)); | |
127 | |
128 Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/MacRx", | |
129 MakeCallback (&PyViz::TraceNetDevRxWifi, this)); | |
130 | |
131 Config::Connect ("/NodeList/*/DeviceList/*/$ns3::CsmaNetDevice/MacTx", | |
132 MakeCallback (&PyViz::TraceNetDevTxCsma, this)); | |
133 | |
134 Config::Connect ("/NodeList/*/DeviceList/*/$ns3::CsmaNetDevice/MacRx", | |
135 MakeCallback (&PyViz::TraceNetDevRxCsma, this)); | |
136 | |
137 Config::Connect ("/NodeList/*/DeviceList/*/$ns3::CsmaNetDevice/MacPromiscRx", | |
138 MakeCallback (&PyViz::TraceNetDevPromiscRxCsma, this)); | |
139 | |
140 Config::Connect ("/NodeList/*/DeviceList/*/TxQueue/Drop", | |
141 MakeCallback (&PyViz::TraceDevQueueDrop, this)); | |
142 | |
143 Config::Connect ("/NodeList/*/$ns3::Ipv4L3Protocol/Drop", | |
144 MakeCallback (&PyViz::TraceIpv4Drop, this)); | |
145 | |
146 Config::Connect ("/NodeList/*/DeviceList/*/$ns3::PointToPointNetDevice/MacTx", | |
147 MakeCallback (&PyViz::TraceNetDevTxPointToPoint, this)); | |
148 | |
149 Config::Connect ("/NodeList/*/DeviceList/*/$ns3::PointToPointNetDevice/MacRx", | |
150 MakeCallback (&PyViz::TraceNetDevRxPointToPoint, this)); | |
151 | |
152 Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WimaxNetDevice/Tx", | |
153 MakeCallback (&PyViz::TraceNetDevTxWimax, this)); | |
154 | |
155 Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WimaxNetDevice/Rx", | |
156 MakeCallback (&PyViz::TraceNetDevRxWimax, this)); | |
157 | |
158 } | |
159 | |
160 void | |
161 PyViz::RegisterCsmaLikeDevice (std::string const &deviceTypeName) | |
162 { | |
163 TypeId::LookupByName (deviceTypeName); // this will assert if the type name is invalid | |
164 | |
165 std::ostringstream sstream; | |
166 sstream << "/NodeList/*/DeviceList/*/$" << deviceTypeName << "/MacTx"; | |
167 Config::Connect (sstream.str (), MakeCallback (&PyViz::TraceNetDevTxCsma, this )); | |
168 | |
169 sstream.str (""); | |
170 sstream << "/NodeList/*/DeviceList/*/$" << deviceTypeName << "/Rx"; | |
171 Config::Connect (sstream.str (), MakeCallback (&PyViz::TraceNetDevRxCsma, this )); | |
172 | |
173 sstream.str (""); | |
174 sstream << "/NodeList/*/DeviceList/*/$" << deviceTypeName << "/PromiscRx"; | |
175 Config::Connect (sstream.str (), MakeCallback (&PyViz::TraceNetDevPromiscRxCsm a, this)); | |
176 } | |
177 | |
178 void | |
179 PyViz::RegisterWifiLikeDevice (std::string const &deviceTypeName) | |
180 { | |
181 TypeId::LookupByName (deviceTypeName); // this will assert if the type name is invalid | |
182 | |
183 std::ostringstream sstream; | |
184 sstream << "/NodeList/*/DeviceList/*/$" << deviceTypeName << "/Tx"; | |
185 Config::Connect (sstream.str (), MakeCallback (&PyViz::TraceNetDevTxWifi, this )); | |
186 | |
187 sstream.str (""); | |
188 sstream <<"/NodeList/*/DeviceList/*/$" << deviceTypeName << "/Rx"; | |
189 Config::Connect (sstream.str (), MakeCallback (&PyViz::TraceNetDevRxWifi, this )); | |
190 } | |
191 | |
192 void | |
193 PyViz::RegisterPointToPointLikeDevice (std::string const &deviceTypeName) | |
194 { | |
195 TypeId::LookupByName (deviceTypeName); // this will assert if the type name is invalid | |
196 | |
197 std::ostringstream sstream; | |
198 sstream << "/NodeList/*/DeviceList/*/$" << deviceTypeName << "/TxQueue/Dequeue "; | |
199 Config::Connect (sstream.str (), MakeCallback (&PyViz::TraceNetDevTxPointToPoi nt, this)); | |
200 | |
201 sstream.str (""); | |
202 sstream << "/NodeList/*/DeviceList/*/$" << deviceTypeName << "/Rx"; | |
203 Config::Connect (sstream.str (), MakeCallback (&PyViz::TraceNetDevRxPointToPoi nt, this)); | |
204 } | |
205 | |
206 void | |
207 PyViz::SetPacketCaptureOptions (uint32_t nodeId, PacketCaptureOptions options) | |
208 { | |
209 NS_LOG_DEBUG (" SetPacketCaptureOptions " << nodeId | |
210 << " PacketCaptureOptions (headers size = " << options.headers.s ize () | |
211 << " mode = " << options.mode << " numLastPackets = " << options .numLastPackets | |
212 << ")"); | |
213 m_packetCaptureOptions[nodeId] = options; | |
214 } | |
215 | |
216 void | |
217 PyViz::RegisterDropTracePath (std::string const &tracePath) | |
218 { | |
219 Config::Connect (tracePath, MakeCallback (&PyViz::TraceDevQueueDrop, this)); | |
220 } | |
221 | |
222 PyViz::~PyViz () | |
223 { | |
224 NS_ASSERT (g_visualizer == this); | |
225 g_visualizer = NULL; | |
226 } | |
227 | |
228 void PyViz::DoPause (std::string const &message) | |
229 { | |
230 m_pauseMessages.push_back (message); | |
231 m_stop = true; | |
232 NS_LOG_LOGIC (Simulator::Now ().GetSeconds () << ": Have " | |
233 << g_visualizer->m_pauseMessages.size () << " pause messages"); | |
234 } | |
235 | |
236 void PyViz::Pause (std::string const &message) | |
237 { | |
238 NS_ASSERT (g_visualizer); | |
239 g_visualizer->DoPause (message); | |
240 } | |
241 | |
242 std::vector<std::string> | |
243 PyViz::GetPauseMessages () const | |
244 { | |
245 NS_LOG_LOGIC (Simulator::Now ().GetSeconds () << ": GetPauseMessages: have " | |
246 << g_visualizer->m_pauseMessages.size () << " pause messages"); | |
247 return m_pauseMessages; | |
248 } | |
249 ···· | |
250 | |
251 void | |
252 PyViz::CallbackStopSimulation () | |
253 { | |
254 NS_LOG_FUNCTION_NOARGS (); | |
255 m_stop = true; | |
Mathieu Lacage
2010/11/18 08:23:13
call Simulator::Stop here.
| |
256 } | |
257 | |
258 void | |
259 PyViz::SimulatorRunUntil (Time time) | |
260 { | |
261 NS_LOG_LOGIC ("SimulatorRunUntil " << time << " (now is " << Simulator::Now () << ")"); | |
262 | |
263 m_pauseMessages.clear (); | |
264 m_transmissionSamples.clear (); | |
265 m_packetDrops.clear (); | |
266 | |
267 Time expirationTime = Simulator::Now () - Seconds (10); | |
268 | |
269 // Clear very old transmission records | |
270 for (std::map<TxRecordKey, TxRecordValue>::iterator iter = m_txRecords.begin ( ); | |
271 iter != m_txRecords.end ();) | |
272 { | |
273 if (iter->second.time < expirationTime) | |
274 { | |
275 m_txRecords.erase (iter++); | |
276 } | |
277 else | |
278 { | |
279 iter++; | |
280 } | |
281 } | |
282 | |
283 // Clear very old packets of interest | |
284 for (std::map<uint32_t, Time>::iterator iter = m_packetsOfInterest.begin (); | |
285 iter != m_packetsOfInterest.end ();) | |
286 { | |
287 if (iter->second < expirationTime) | |
288 { | |
289 m_packetsOfInterest.erase (iter++); | |
290 } | |
291 else | |
292 { | |
293 iter++; | |
294 } | |
295 } | |
296 | |
297 if (Simulator::IsFinished () || Simulator::Now () >= time) | |
298 { | |
299 return; | |
300 } | |
301 // Schedule a dummy callback function for the target time, to make | |
302 // sure we stop at the right time. Otherwise, simulations with few | |
303 // events just appear to "jump" big chunks of time. | |
304 NS_LOG_LOGIC ("Schedule dummy callback to be called in " << (time - Simulator: :Now ())); | |
305 m_stop = false; | |
306 Simulator::Cancel (m_stopCallbackEvent); | |
307 m_stopCallbackEvent = Simulator::Schedule (time - Simulator::Now (), &PyViz::C allbackStopSimulation, this); | |
308 | |
309 while (!Simulator::IsFinished ()) | |
310 { | |
311 if (m_stop) | |
312 { | |
313 break; | |
314 } | |
315 Simulator::RunOneEvent (); | |
Mathieu Lacage
2010/11/18 08:23:13
I really don't understand why you can't call Simul
| |
316 } | |
317 } | |
318 | |
319 bool PyViz::TransmissionSampleKey::operator < (PyViz::TransmissionSampleKey cons t &other) const | |
320 { | |
321 if (this->transmitter < other.transmitter) | |
322 { | |
323 return true; | |
324 } | |
325 if (this->transmitter != other.transmitter) | |
326 { | |
327 return false; | |
328 } | |
329 if (this->receiver < other.receiver) | |
330 { | |
331 return true;} | |
332 if (this->receiver != other.receiver) | |
333 { | |
334 return false; | |
335 } | |
336 if (this->channel < other.channel) | |
337 { | |
338 return true; | |
339 } | |
340 else | |
341 { | |
342 return false; | |
343 } | |
344 } | |
345 | |
346 bool PyViz::TransmissionSampleKey::operator == (PyViz::TransmissionSampleKey con st &other) const | |
347 { | |
348 bool retval = (transmitter == other.transmitter) && | |
349 (receiver == other.receiver) && | |
350 (channel == other.channel); | |
351 return retval; | |
352 } | |
353 | |
354 | |
355 PyViz::NetDeviceStatistics & | |
356 PyViz::FindNetDeviceStatistics (int node, int interface) | |
357 { | |
358 std::map<uint32_t, std::vector<NetDeviceStatistics> >::iterator nodeStatsIter = m_nodesStatistics.find (node); | |
359 std::vector<NetDeviceStatistics> *stats; | |
360 if (nodeStatsIter == m_nodesStatistics.end ()) | |
361 { | |
362 stats = &m_nodesStatistics[node]; | |
363 stats->resize (NodeList::GetNode (node)->GetNDevices ()); | |
364 } | |
365 else | |
366 { | |
367 stats = &(nodeStatsIter->second); | |
368 } | |
369 NetDeviceStatistics &devStats = (*stats)[interface]; | |
370 return devStats; | |
371 } | |
372 | |
373 bool PyViz::GetPacketCaptureOptions (uint32_t nodeId, const PacketCaptureOptions **outOptions) const | |
374 { | |
375 std::map<uint32_t, PacketCaptureOptions>::const_iterator iter = m_packetCaptur eOptions.find (nodeId); | |
376 if (iter == m_packetCaptureOptions.end ()) | |
377 { | |
378 return false; | |
379 } | |
380 else | |
381 { | |
382 *outOptions = &iter->second; | |
383 return true; | |
384 } | |
385 } | |
386 | |
387 bool PyViz::FilterPacket (Ptr<const Packet> packet, const PacketCaptureOptions & options) | |
388 { | |
389 switch (options.mode) | |
390 { | |
391 case PACKET_CAPTURE_DISABLED: | |
392 return false; | |
393 | |
394 case PACKET_CAPTURE_FILTER_HEADERS_OR: | |
395 { | |
396 PacketMetadata::ItemIterator metadataIterator = packet->BeginItem (); | |
397 while (metadataIterator.HasNext ()) | |
398 { | |
399 PacketMetadata::Item item = metadataIterator.Next (); | |
400 if (options.headers.find (item.tid) != options.headers.end ()) | |
401 { | |
402 return true; | |
403 } | |
404 } | |
405 return false; | |
406 } | |
407 | |
408 case PACKET_CAPTURE_FILTER_HEADERS_AND: | |
409 { | |
410 std::set<TypeId> missingHeaders (options.headers); | |
411 PacketMetadata::ItemIterator metadataIterator = packet->BeginItem (); | |
412 while (metadataIterator.HasNext ()) | |
413 { | |
414 PacketMetadata::Item item = metadataIterator.Next (); | |
415 std::set<TypeId>::iterator missingIter = missingHeaders.find (item.t id); | |
416 if (missingIter != missingHeaders.end ()) | |
417 { | |
418 missingHeaders.erase (missingIter); | |
419 } | |
420 } | |
421 if (missingHeaders.size () == 0) | |
422 { | |
423 return true; | |
424 } | |
425 else | |
426 { | |
427 return false; | |
428 } | |
429 } | |
430 | |
431 default: | |
432 NS_FATAL_ERROR ("should not be reached"); | |
433 return false; | |
434 } | |
435 } | |
436 | |
437 void | |
438 PyViz::TraceDevQueueDrop (std::string context, Ptr<const Packet> packet) | |
439 { | |
440 NS_LOG_FUNCTION (context << packet->GetUid ()); | |
441 std::vector<std::string> splitPath = PathSplit (context); | |
442 int nodeIndex = atoi (splitPath[1].c_str ()); | |
443 Ptr<Node> node = NodeList::GetNode (nodeIndex); | |
444 | |
445 if (m_nodesOfInterest.find (nodeIndex) == m_nodesOfInterest.end ()) | |
446 { | |
447 // if the transmitting node is not "of interest", we still | |
448 // record the transmission if it is a packet of interest. | |
449 if (m_packetsOfInterest.find (packet->GetUid ()) == m_packetsOfInterest.en d ()) | |
450 { | |
451 NS_LOG_DEBUG ("Packet " << packet->GetUid () << " is not of interest") ; | |
452 return; | |
453 } | |
454 } | |
455 | |
456 // ---- "last packets" | |
457 const PacketCaptureOptions *captureOptions; | |
458 if (GetPacketCaptureOptions (nodeIndex, &captureOptions) && FilterPacket (pack et, *captureOptions)) | |
459 { | |
460 LastPacketsSample &last = m_lastPackets[nodeIndex]; | |
461 PacketSample lastPacket; | |
462 lastPacket.time = Simulator::Now (); | |
463 lastPacket.packet = packet->Copy (); | |
464 lastPacket.device = NULL; | |
465 last.lastDroppedPackets.push_back (lastPacket); | |
466 while (last.lastDroppedPackets.size () > captureOptions->numLastPackets) | |
467 { | |
468 last.lastDroppedPackets.erase (last.lastDroppedPackets.begin ()); | |
469 } | |
470 } | |
471 | |
472 std::map<Ptr<Node>, uint32_t>::iterator iter = m_packetDrops.find (node); | |
473 if (iter == m_packetDrops.end ()) | |
474 { | |
475 m_packetDrops[node] = packet->GetSize (); | |
476 } | |
477 else | |
478 { | |
479 iter->second += packet->GetSize (); | |
480 } | |
481 } | |
482 | |
483 void | |
484 PyViz::TraceIpv4Drop (std::string context, ns3::Ipv4Header const &hdr, Ptr<const Packet> packet, | |
485 ns3::Ipv4L3Protocol::DropReason reason, Ptr<Ipv4> dummy_ip v4, uint32_t interface) | |
486 { | |
487 Ptr<Packet> packetCopy = packet->Copy (); | |
488 packetCopy->AddHeader (hdr); | |
489 TraceDevQueueDrop (context, packetCopy); | |
490 } | |
491 | |
492 | |
493 // --------- TX device tracing -------------------·· | |
494 | |
495 void | |
496 PyViz::TraceNetDevTxCommon (std::string const &context, Ptr<const Packet> packet , | |
497 Mac48Address const &destinationAddress) | |
498 { | |
499 NS_LOG_FUNCTION (context << packet->GetUid () << *packet); | |
500 | |
501 std::vector<std::string> splitPath = PathSplit (context); | |
502 int nodeIndex = atoi (splitPath[1].c_str ()); | |
503 int devIndex = atoi (splitPath[3].c_str ()); | |
504 Ptr<Node> node = NodeList::GetNode (nodeIndex); | |
505 Ptr<NetDevice> device = node->GetDevice (devIndex); | |
506 | |
507 // ---- statistics | |
508 NetDeviceStatistics &stats = FindNetDeviceStatistics (nodeIndex, devIndex); | |
509 ++stats.transmittedPackets; | |
510 stats.transmittedBytes += packet->GetSize (); | |
511 | |
512 // ---- "last packets" | |
513 const PacketCaptureOptions *captureOptions; | |
514 if (GetPacketCaptureOptions (nodeIndex, &captureOptions) && FilterPacket (pack et, *captureOptions)) | |
515 { | |
516 LastPacketsSample &last = m_lastPackets[nodeIndex]; | |
517 TxPacketSample lastPacket; | |
518 lastPacket.time = Simulator::Now (); | |
519 lastPacket.packet = packet->Copy (); | |
520 lastPacket.device = device; | |
521 lastPacket.to = destinationAddress; | |
522 last.lastTransmittedPackets.push_back (lastPacket); | |
523 while (last.lastTransmittedPackets.size () > captureOptions->numLastPacket s) | |
524 { | |
525 last.lastTransmittedPackets.erase (last.lastTransmittedPackets.begin ( )); | |
526 } | |
527 } | |
528 | |
529 // ---- transmissions records | |
530 | |
531 if (m_nodesOfInterest.find (nodeIndex) == m_nodesOfInterest.end ()) | |
532 { | |
533 // if the transmitting node is not "of interest", we still | |
534 // record the transmission if it is a packet of interest. | |
535 if (m_packetsOfInterest.find (packet->GetUid ()) == m_packetsOfInterest.en d ()) | |
536 { | |
537 NS_LOG_DEBUG ("Packet " << packet->GetUid () << " is not of interest") ; | |
538 return; | |
539 } | |
540 } | |
541 else | |
542 { | |
543 // We will follow this packet throughout the network. | |
544 m_packetsOfInterest[packet->GetUid ()] = Simulator::Now (); | |
545 } | |
546 | |
547 TxRecordValue record = { Simulator::Now (), node, false }; | |
548 if (destinationAddress == device->GetBroadcast ()) | |
549 { | |
550 record.isBroadcast = true; | |
551 } | |
552 | |
553 m_txRecords[TxRecordKey (device->GetChannel (), packet->GetUid ())] = record; | |
554 | |
555 PyVizPacketTag tag; | |
556 //packet->RemovePacketTag (tag); | |
557 tag.m_packetId = packet->GetUid (); | |
558 packet->AddByteTag (tag); | |
559 } | |
560 | |
561 void | |
562 PyViz::TraceNetDevTxWifi (std::string context, Ptr<const Packet> packet) | |
563 { | |
564 NS_LOG_FUNCTION (context << packet->GetUid () << *packet); | |
565 | |
566 /* | |
567 * To DS From DS Address 1 Address 2 Address 3 Address 4· | |
568 *---------------------------------------------------------------------- | |
569 * 0 0 Destination Source BSSID N/A | |
570 * 0 1 Destination BSSID Source N/A | |
571 * 1 0 BSSID Source Destination N/A | |
572 * 1 1 Receiver Transmitter Destination Source | |
573 */·· | |
574 WifiMacHeader hdr; | |
575 NS_ABORT_IF (packet->PeekHeader (hdr) == 0); | |
576 Mac48Address destinationAddress; | |
577 if (hdr.IsToDs () && !hdr.IsFromDs ()) | |
578 { | |
579 destinationAddress = hdr.GetAddr3 (); | |
580 } | |
581 else if (!hdr.IsToDs () && hdr.IsFromDs ()) | |
582 { | |
583 destinationAddress = hdr.GetAddr1 (); | |
584 } | |
585 else if (!hdr.IsToDs () && !hdr.IsFromDs ()) | |
586 { | |
587 destinationAddress = hdr.GetAddr1 (); | |
588 } | |
589 else | |
590 { | |
591 destinationAddress = hdr.GetAddr3 (); | |
592 } | |
593 TraceNetDevTxCommon (context, packet, destinationAddress); | |
594 } | |
595 | |
596 | |
597 void | |
598 PyViz::TraceNetDevTxCsma (std::string context, Ptr<const Packet> packet) | |
599 { | |
600 EthernetHeader ethernetHeader; | |
601 NS_ABORT_IF (packet->PeekHeader (ethernetHeader) == 0); | |
602 TraceNetDevTxCommon (context, packet, ethernetHeader.GetDestination ()); | |
603 } | |
604 | |
605 void | |
606 PyViz::TraceNetDevTxPointToPoint (std::string context, Ptr<const Packet> packet) | |
607 { | |
608 TraceNetDevTxCommon (context, packet, Mac48Address ()); | |
609 } | |
610 | |
611 | |
612 | |
613 | |
614 // --------- RX device tracing -------------------·· | |
615 | |
616 void | |
617 PyViz::TraceNetDevRxCommon (std::string const &context, Ptr<const Packet> packet , Mac48Address const &from) | |
618 { | |
619 uint32_t uid; | |
620 PyVizPacketTag tag; | |
621 if (packet->FindFirstMatchingByteTag (tag)) | |
622 { | |
623 uid = tag.m_packetId; | |
624 } | |
625 else | |
626 { | |
627 //NS_ASSERT (0); | |
628 NS_LOG_WARN ("Packet has no byte tag; wimax link?"); | |
629 uid = packet->GetUid (); | |
630 } | |
631 | |
632 NS_LOG_FUNCTION (context << uid); | |
633 std::vector<std::string> splitPath = PathSplit (context); | |
634 int nodeIndex = atoi (splitPath[1].c_str ()); | |
635 int devIndex = atoi (splitPath[3].c_str ()); | |
636 | |
637 // ---- statistics | |
638 NetDeviceStatistics &stats = FindNetDeviceStatistics (nodeIndex, devIndex); | |
639 ++stats.receivedPackets; | |
640 stats.receivedBytes += packet->GetSize (); | |
641 | |
642 Ptr<Node> node = NodeList::GetNode (nodeIndex); | |
643 Ptr<NetDevice> device = node->GetDevice (devIndex); | |
644 | |
645 // ---- "last packets" | |
646 const PacketCaptureOptions *captureOptions; | |
647 if (GetPacketCaptureOptions (nodeIndex, &captureOptions) && FilterPacket (pack et, *captureOptions)) | |
648 { | |
649 LastPacketsSample &last = m_lastPackets[nodeIndex]; | |
650 RxPacketSample lastPacket; | |
651 lastPacket.time = Simulator::Now (); | |
652 lastPacket.packet = packet->Copy (); | |
653 lastPacket.device = device; | |
654 lastPacket.from = from; | |
655 last.lastReceivedPackets.push_back (lastPacket); | |
656 while (last.lastReceivedPackets.size () > captureOptions->numLastPackets) | |
657 { | |
658 last.lastReceivedPackets.erase (last.lastReceivedPackets.begin ()); | |
659 } | |
660 } | |
661 | |
662 // ---- transmissions | |
663 if (m_packetsOfInterest.find (uid) == m_packetsOfInterest.end ()) | |
664 { | |
665 NS_LOG_DEBUG ("RX Packet " << uid << " is not of interest"); | |
666 return; | |
667 } | |
668 | |
669 Ptr<Channel> channel = device->GetChannel (); | |
670 | |
671 std::map<TxRecordKey, TxRecordValue>::iterator recordIter =· | |
672 m_txRecords.find (TxRecordKey (channel, uid)); | |
673 | |
674 if (recordIter == m_txRecords.end ()) | |
675 { | |
676 NS_LOG_DEBUG ("RX Packet " << uid << " was not transmitted?!"); | |
677 return; | |
678 } | |
679 ·· | |
680 TxRecordValue &record = recordIter->second; | |
681 ·· | |
682 if (record.srcNode == node) | |
683 { | |
684 NS_LOG_WARN ("Node " << node->GetId () << " receiving back the same packet (UID=" << uid | |
685 << ") it had previously transmitted, on the same channel!"); | |
686 return; | |
687 } | |
688 | |
689 TransmissionSampleKey key = { record.srcNode, node, channel }; | |
690 | |
691 #ifdef NS3_LOG_ENABLE | |
692 NS_LOG_DEBUG("m_transmissionSamples begin:"); | |
693 if (g_log.IsEnabled (ns3::LOG_DEBUG)) | |
694 { | |
695 for (std::map<TransmissionSampleKey,TransmissionSampleValue>::const_iterat or iter | |
696 = m_transmissionSamples.begin (); iter != m_transmissionSamples.end (); iter++) | |
697 { | |
698 NS_LOG_DEBUG(iter->first.transmitter<<"/"<<iter->first.transmitter->Ge tId () << ", " | |
699 << iter->first.receiver<<"/"<<iter->first.receiver->GetId () | |
700 << ", " << iter->first.channel << " => " << iter->second. bytes << " (@ " << &iter->second << ")"); | |
701 } | |
702 } | |
703 NS_LOG_DEBUG("m_transmissionSamples end."); | |
704 #endif | |
705 | |
706 std::map<TransmissionSampleKey,TransmissionSampleValue>::iterator | |
707 iter = m_transmissionSamples.find (key); | |
708 | |
709 if (iter == m_transmissionSamples.end ()) | |
710 { | |
711 TransmissionSampleValue sample = { packet->GetSize () }; | |
712 NS_LOG_DEBUG ("RX: from " << key.transmitter<<"/"<<key.transmitter->GetId( ) << " to " | |
713 << key.receiver<<"/"<<key.receiver->GetId() | |
714 << " channel " << channel << ": " << packet->GetSize () | |
715 << " bytes more. => new sample with " << packet->GetSize () << " bytes."); | |
716 m_transmissionSamples[key] = sample; | |
717 } | |
718 else | |
719 { | |
720 TransmissionSampleValue &sample = iter->second; | |
721 NS_LOG_DEBUG ("RX: from " << key.transmitter<<"/"<<key.transmitter->GetId( ) << " to " | |
722 << key.receiver<<"/"<<key.receiver->GetId() | |
723 << " channel " << channel << ": " << packet->GetSize () | |
724 << " bytes more. => sample " << &sample << " with bytes " << sample.bytes); | |
725 | |
726 sample.bytes += packet->GetSize (); | |
727 } | |
728 } | |
729 | |
730 void | |
731 PyViz::TraceNetDevRxWifi (std::string context, Ptr<const Packet> packet) | |
732 { | |
733 NS_LOG_FUNCTION (context << packet->GetUid ()); | |
734 | |
735 | |
736 /* | |
737 * To DS From DS Address 1 Address 2 Address 3 Address 4· | |
738 *---------------------------------------------------------------------- | |
739 * 0 0 Destination Source BSSID N/A | |
740 * 0 1 Destination BSSID Source N/A | |
741 * 1 0 BSSID Source Destination N/A | |
742 * 1 1 Receiver Transmitter Destination Source | |
743 */·· | |
744 WifiMacHeader hdr; | |
745 NS_ABORT_IF (packet->PeekHeader (hdr) == 0); | |
746 Mac48Address sourceAddress; | |
747 if (hdr.IsToDs () && !hdr.IsFromDs ()) | |
748 { | |
749 sourceAddress = hdr.GetAddr2 (); | |
750 } | |
751 else if (!hdr.IsToDs () && hdr.IsFromDs ()) | |
752 { | |
753 sourceAddress = hdr.GetAddr3 (); | |
754 } | |
755 else if (!hdr.IsToDs () && !hdr.IsFromDs ()) | |
756 { | |
757 sourceAddress = hdr.GetAddr2 (); | |
758 } | |
759 else | |
760 { | |
761 sourceAddress = hdr.GetAddr4 (); | |
762 } | |
763 | |
764 TraceNetDevRxCommon (context, packet, sourceAddress); | |
765 } | |
766 | |
767 | |
768 | |
769 void | |
770 PyViz::TraceNetDevRxCsma (std::string context, Ptr<const Packet> packet) | |
771 { | |
772 EthernetHeader ethernetHeader; | |
773 NS_ABORT_IF (packet->PeekHeader (ethernetHeader) == 0); | |
774 TraceNetDevRxCommon (context, packet, ethernetHeader.GetSource ()); | |
775 } | |
776 | |
777 void | |
778 PyViz::TraceNetDevRxPointToPoint (std::string context, Ptr<const Packet> packet) | |
779 { | |
780 TraceNetDevRxCommon (context, packet, Mac48Address ()); | |
781 } | |
782 | |
783 void | |
784 PyViz::TraceNetDevPromiscRxCsma (std::string context, Ptr<const Packet> packet) | |
785 { | |
786 EthernetHeader ethernetHeader; | |
787 NS_ABORT_IF (packet->PeekHeader (ethernetHeader) == 0); | |
788 | |
789 NetDevice::PacketType packetType = NetDevice::PACKET_OTHERHOST; // FIXME | |
790 ·· | |
791 // Other packet types are already being received by | |
792 // TraceNetDevRxCsma; we don't want to receive them twice. | |
793 if (packetType == NetDevice::PACKET_OTHERHOST) | |
794 { | |
795 TraceNetDevRxCommon (context, packet, ethernetHeader.GetDestination ()); | |
796 } | |
797 } | |
798 | |
799 void | |
800 PyViz::TraceNetDevTxWimax (std::string context, Ptr<const Packet> packet, Mac48A ddress const &destination) | |
801 { | |
802 NS_LOG_FUNCTION (context); | |
803 TraceNetDevTxCommon (context, packet, destination); | |
804 } | |
805 | |
806 void | |
807 PyViz::TraceNetDevRxWimax (std::string context, Ptr<const Packet> packet, Mac48A ddress const &source) | |
808 { | |
809 NS_LOG_FUNCTION (context); | |
810 TraceNetDevRxCommon (context, packet, source); | |
811 } | |
812 | |
813 | |
814 // --------------------- | |
815 | |
816 PyViz::TransmissionSampleList | |
817 PyViz::GetTransmissionSamples () const | |
818 { | |
819 NS_LOG_DEBUG ("GetTransmissionSamples BEGIN"); | |
820 TransmissionSampleList list; | |
821 for (std::map<TransmissionSampleKey, TransmissionSampleValue>::const_iterator | |
822 iter = m_transmissionSamples.begin (); | |
823 iter != m_transmissionSamples.end (); | |
824 iter++) | |
825 { | |
826 TransmissionSample sample; | |
827 sample.transmitter = iter->first.transmitter; | |
828 sample.receiver = iter->first.receiver; | |
829 sample.channel = iter->first.channel; | |
830 sample.bytes = iter->second.bytes; | |
831 NS_LOG_DEBUG ("from " << sample.transmitter->GetId() << " to " << sample.r eceiver->GetId() | |
832 << ": " << sample.bytes << " bytes."); | |
833 list.push_back (sample); | |
834 } | |
835 NS_LOG_DEBUG ("GetTransmissionSamples END"); | |
836 return list; | |
837 } | |
838 | |
839 PyViz::PacketDropSampleList | |
840 PyViz::GetPacketDropSamples () const | |
841 { | |
842 NS_LOG_DEBUG ("GetPacketDropSamples BEGIN"); | |
843 PacketDropSampleList list; | |
844 for (std::map<Ptr<Node>, uint32_t>::const_iterator | |
845 iter = m_packetDrops.begin (); | |
846 iter != m_packetDrops.end (); | |
847 iter++) | |
848 { | |
849 PacketDropSample sample; | |
850 sample.transmitter = iter->first; | |
851 sample.bytes = iter->second; | |
852 NS_LOG_DEBUG ("in " << sample.transmitter->GetId()· | |
853 << ": " << sample.bytes << " bytes dropped."); | |
854 list.push_back (sample); | |
855 } | |
856 NS_LOG_DEBUG ("GetPacketDropSamples END"); | |
857 return list; | |
858 } | |
859 | |
860 void | |
861 PyViz::SetNodesOfInterest (std::set<uint32_t> nodes) | |
862 { | |
863 m_nodesOfInterest = nodes; | |
864 } | |
865 | |
866 std::vector<PyViz::NodeStatistics> | |
867 PyViz::GetNodesStatistics () const | |
868 { | |
869 std::vector<PyViz::NodeStatistics> retval; | |
870 for (std::map<uint32_t, std::vector<NetDeviceStatistics> >::const_iterator ite r = m_nodesStatistics.begin (); | |
871 iter != m_nodesStatistics.end (); iter++) | |
872 { | |
873 NodeStatistics stats = { iter->first, iter->second }; | |
874 retval.push_back (stats); | |
875 } | |
876 return retval; | |
877 } | |
878 | |
879 | |
880 PyViz::LastPacketsSample | |
881 PyViz::GetLastPackets (uint32_t nodeId) const | |
882 { | |
883 NS_LOG_DEBUG ("GetLastPackets: " << nodeId); | |
884 ·· | |
885 std::map<uint32_t, LastPacketsSample>::const_iterator | |
886 iter = m_lastPackets.find(nodeId); | |
887 if (iter != m_lastPackets.end ()) | |
888 { | |
889 return iter->second; | |
890 } | |
891 else | |
892 { | |
893 return LastPacketsSample (); | |
894 } | |
895 } | |
896 | |
897 | |
898 | |
899 | |
900 | |
901 | |
902 namespace | |
903 { | |
904 // Adapted from http://en.wikipedia.org/w/index.php?title=Line_clipping&oldid= 248609574 | |
905 class FastClipping | |
906 { | |
907 public: | |
908 struct Vector2· | |
909 { | |
910 double x; | |
911 double y; | |
912 }; | |
913 ······ | |
914 Vector2 m_clipMin, m_clipMax; | |
915 | |
916 struct Line | |
917 { | |
918 Vector2 start, end; | |
919 double dx, dy; | |
920 }; | |
921 | |
922 private: | |
923 | |
924 void ClipStartTop (Line &line) | |
925 { | |
926 line.start.x += line.dx * (m_clipMin.y - line.start.y) / line.dy; | |
927 line.start.y = m_clipMin.y; | |
928 } | |
929 · | |
930 void ClipStartBottom (Line &line) | |
931 { | |
932 line.start.x += line.dx * (m_clipMax.y - line.start.y) / line.dy; | |
933 line.start.y = m_clipMax.y; | |
934 } | |
935 · | |
936 void ClipStartRight (Line &line) | |
937 { | |
938 line.start.y += line.dy * (m_clipMax.x - line.start.x) / line.dx; | |
939 line.start.x = m_clipMax.x; | |
940 } | |
941 · | |
942 void ClipStartLeft (Line &line) | |
943 { | |
944 line.start.y += line.dy * (m_clipMin.x - line.start.x) / line.dx; | |
945 line.start.x = m_clipMin.x; | |
946 } | |
947 · | |
948 void ClipEndTop (Line &line) | |
949 { | |
950 line.end.x += line.dx * (m_clipMin.y - line.end.y) / line.dy; | |
951 line.end.y = m_clipMin.y; | |
952 } | |
953 ···· | |
954 void ClipEndBottom (Line &line) { | |
955 line.end.x += line.dx * (m_clipMax.y - line.end.y) / line.dy; | |
956 line.end.y = m_clipMax.y; | |
957 } | |
958 · | |
959 void ClipEndRight (Line &line) | |
960 { | |
961 line.end.y += line.dy * (m_clipMax.x - line.end.x) / line.dx; | |
962 line.end.x = m_clipMax.x; | |
963 } | |
964 · | |
965 void ClipEndLeft (Line &line) | |
966 { | |
967 line.end.y += line.dy * (m_clipMin.x - line.end.x) / line.dx; | |
968 line.end.x = m_clipMin.x; | |
969 } | |
970 | |
971 public: | |
972 FastClipping (Vector2 clipMin, Vector2 clipMax) | |
973 : m_clipMin (clipMin), m_clipMax (clipMax) | |
974 { | |
975 } | |
976 ···· | |
977 · | |
978 bool ClipLine (Line &line) | |
979 { | |
980 uint8_t lineCode = 0; | |
981 · | |
982 if (line.end.y < m_clipMin.y) | |
983 lineCode |= 8; | |
984 else if (line.end.y > m_clipMax.y) | |
985 lineCode |= 4; | |
986 · | |
987 if (line.end.x > m_clipMax.x) | |
988 lineCode |= 2; | |
989 else if (line.end.x < m_clipMin.x) | |
990 lineCode |= 1; | |
991 · | |
992 if (line.start.y < m_clipMin.y) | |
993 lineCode |= 128; | |
994 else if (line.start.y > m_clipMax.y) | |
995 lineCode |= 64; | |
996 · | |
997 if (line.start.x > m_clipMax.x) | |
998 lineCode |= 32; | |
999 else if (line.start.x < m_clipMin.x) | |
1000 lineCode |= 16; | |
1001 · | |
1002 // 9 - 8 - A | |
1003 // | | | | |
1004 // 1 - 0 - 2 | |
1005 // | | | | |
1006 // 5 - 4 - 6 | |
1007 switch (lineCode) | |
1008 { | |
1009 // center | |
1010 case 0x00: | |
1011 return true; | |
1012 · | |
1013 case 0x01: | |
1014 ClipEndLeft (line); | |
1015 return true; | |
1016 · | |
1017 case 0x02: | |
1018 ClipEndRight (line); | |
1019 return true; | |
1020 · | |
1021 case 0x04: | |
1022 ClipEndBottom (line); | |
1023 return true; | |
1024 · | |
1025 case 0x05: | |
1026 ClipEndLeft (line); | |
1027 if (line.end.y > m_clipMax.y) | |
1028 ClipEndBottom (line); | |
1029 return true; | |
1030 · | |
1031 case 0x06: | |
1032 ClipEndRight (line); | |
1033 if (line.end.y > m_clipMax.y) | |
1034 ClipEndBottom (line); | |
1035 return true; | |
1036 · | |
1037 case 0x08: | |
1038 ClipEndTop (line); | |
1039 return true; | |
1040 · | |
1041 case 0x09: | |
1042 ClipEndLeft (line); | |
1043 if (line.end.y < m_clipMin.y) | |
1044 ClipEndTop (line); | |
1045 return true; | |
1046 · | |
1047 case 0x0A: | |
1048 ClipEndRight (line); | |
1049 if (line.end.y < m_clipMin.y) | |
1050 ClipEndTop (line); | |
1051 return true; | |
1052 · | |
1053 // left | |
1054 case 0x10: | |
1055 ClipStartLeft (line); | |
1056 return true; | |
1057 · | |
1058 case 0x12: | |
1059 ClipStartLeft (line); | |
1060 ClipEndRight (line); | |
1061 return true; | |
1062 · | |
1063 case 0x14: | |
1064 ClipStartLeft (line); | |
1065 if (line.start.y > m_clipMax.y) | |
1066 return false; | |
1067 ClipEndBottom (line); | |
1068 return true; | |
1069 · | |
1070 case 0x16: | |
1071 ClipStartLeft (line); | |
1072 if (line.start.y > m_clipMax.y) | |
1073 return false; | |
1074 ClipEndBottom (line); | |
1075 if (line.end.x > m_clipMax.x) | |
1076 ClipEndRight (line); | |
1077 return true; | |
1078 · | |
1079 case 0x18: | |
1080 ClipStartLeft (line); | |
1081 if (line.start.y < m_clipMin.y) | |
1082 return false; | |
1083 ClipEndTop (line); | |
1084 return true; | |
1085 · | |
1086 case 0x1A: | |
1087 ClipStartLeft (line); | |
1088 if (line.start.y < m_clipMin.y) | |
1089 return false; | |
1090 ClipEndTop (line); | |
1091 if (line.end.x > m_clipMax.x) | |
1092 ClipEndRight (line); | |
1093 return true; | |
1094 · | |
1095 // right | |
1096 case 0x20: | |
1097 ClipStartRight (line); | |
1098 return true; | |
1099 · | |
1100 case 0x21: | |
1101 ClipStartRight (line); | |
1102 ClipEndLeft (line); | |
1103 return true; | |
1104 · | |
1105 case 0x24: | |
1106 ClipStartRight (line); | |
1107 if (line.start.y > m_clipMax.y) | |
1108 return false; | |
1109 ClipEndBottom (line); | |
1110 return true; | |
1111 · | |
1112 case 0x25: | |
1113 ClipStartRight (line); | |
1114 if (line.start.y > m_clipMax.y) | |
1115 return false; | |
1116 ClipEndBottom (line); | |
1117 if (line.end.x < m_clipMin.x) | |
1118 ClipEndLeft (line); | |
1119 return true; | |
1120 · | |
1121 case 0x28: | |
1122 ClipStartRight (line); | |
1123 if (line.start.y < m_clipMin.y) | |
1124 return false; | |
1125 ClipEndTop (line); | |
1126 return true; | |
1127 · | |
1128 case 0x29: | |
1129 ClipStartRight (line); | |
1130 if (line.start.y < m_clipMin.y) | |
1131 return false; | |
1132 ClipEndTop (line); | |
1133 if (line.end.x < m_clipMin.x) | |
1134 ClipEndLeft (line); | |
1135 return true; | |
1136 · | |
1137 // bottom | |
1138 case 0x40: | |
1139 ClipStartBottom (line); | |
1140 return true; | |
1141 · | |
1142 case 0x41: | |
1143 ClipStartBottom (line); | |
1144 if (line.start.x < m_clipMin.x) | |
1145 return false; | |
1146 ClipEndLeft (line); | |
1147 if (line.end.y > m_clipMax.y) | |
1148 ClipEndBottom (line); | |
1149 return true; | |
1150 · | |
1151 case 0x42: | |
1152 ClipStartBottom (line); | |
1153 if (line.start.x > m_clipMax.x) | |
1154 return false; | |
1155 ClipEndRight (line); | |
1156 return true; | |
1157 · | |
1158 case 0x48: | |
1159 ClipStartBottom (line); | |
1160 ClipEndTop (line); | |
1161 return true; | |
1162 · | |
1163 case 0x49: | |
1164 ClipStartBottom (line); | |
1165 if (line.start.x < m_clipMin.x) | |
1166 return false; | |
1167 ClipEndLeft (line); | |
1168 if (line.end.y < m_clipMin.y) | |
1169 ClipEndTop (line); | |
1170 return true; | |
1171 · | |
1172 case 0x4A: | |
1173 ClipStartBottom (line); | |
1174 if (line.start.x > m_clipMax.x) | |
1175 return false; | |
1176 ClipEndRight (line); | |
1177 if (line.end.y < m_clipMin.y) | |
1178 ClipEndTop (line); | |
1179 return true; | |
1180 · | |
1181 // bottom-left | |
1182 case 0x50: | |
1183 ClipStartLeft (line); | |
1184 if (line.start.y > m_clipMax.y) | |
1185 ClipStartBottom (line); | |
1186 return true; | |
1187 · | |
1188 case 0x52: | |
1189 ClipEndRight (line); | |
1190 if (line.end.y > m_clipMax.y) | |
1191 return false; | |
1192 ClipStartBottom (line); | |
1193 if (line.start.x < m_clipMin.x) | |
1194 ClipStartLeft (line); | |
1195 return true; | |
1196 · | |
1197 case 0x58: | |
1198 ClipEndTop (line); | |
1199 if (line.end.x < m_clipMin.x) | |
1200 return false; | |
1201 ClipStartBottom (line); | |
1202 if (line.start.x < m_clipMin.x) | |
1203 ClipStartLeft (line); | |
1204 return true; | |
1205 · | |
1206 case 0x5A: | |
1207 ClipStartLeft (line); | |
1208 if (line.start.y < m_clipMin.y) | |
1209 return false; | |
1210 ClipEndRight (line); | |
1211 if (line.end.y > m_clipMax.y) | |
1212 return false; | |
1213 if (line.start.y > m_clipMax.y) | |
1214 ClipStartBottom (line); | |
1215 if (line.end.y < m_clipMin.y) | |
1216 ClipEndTop (line); | |
1217 return true; | |
1218 · | |
1219 // bottom-right | |
1220 case 0x60: | |
1221 ClipStartRight (line); | |
1222 if (line.start.y > m_clipMax.y) | |
1223 ClipStartBottom (line); | |
1224 return true; | |
1225 · | |
1226 case 0x61: | |
1227 ClipEndLeft (line); | |
1228 if (line.end.y > m_clipMax.y) | |
1229 return false; | |
1230 ClipStartBottom (line); | |
1231 if (line.start.x > m_clipMax.x) | |
1232 ClipStartRight (line); | |
1233 return true; | |
1234 · | |
1235 case 0x68: | |
1236 ClipEndTop (line); | |
1237 if (line.end.x > m_clipMax.x) | |
1238 return false; | |
1239 ClipStartRight (line); | |
1240 if (line.start.y > m_clipMax.y) | |
1241 ClipStartBottom (line); | |
1242 return true; | |
1243 · | |
1244 case 0x69: | |
1245 ClipEndLeft (line); | |
1246 if (line.end.y > m_clipMax.y) | |
1247 return false; | |
1248 ClipStartRight (line); | |
1249 if (line.start.y < m_clipMin.y) | |
1250 return false; | |
1251 if (line.end.y < m_clipMin.y) | |
1252 ClipEndTop (line); | |
1253 if (line.start.y > m_clipMax.y) | |
1254 ClipStartBottom (line); | |
1255 return true; | |
1256 · | |
1257 // top | |
1258 case 0x80: | |
1259 ClipStartTop (line); | |
1260 return true; | |
1261 · | |
1262 case 0x81: | |
1263 ClipStartTop (line); | |
1264 if (line.start.x < m_clipMin.x) | |
1265 return false; | |
1266 ClipEndLeft (line); | |
1267 return true; | |
1268 · | |
1269 case 0x82: | |
1270 ClipStartTop (line); | |
1271 if (line.start.x > m_clipMax.x) | |
1272 return false; | |
1273 ClipEndRight (line); | |
1274 return true; | |
1275 · | |
1276 case 0x84: | |
1277 ClipStartTop (line); | |
1278 ClipEndBottom (line); | |
1279 return true; | |
1280 · | |
1281 case 0x85: | |
1282 ClipStartTop (line); | |
1283 if (line.start.x < m_clipMin.x) | |
1284 return false; | |
1285 ClipEndLeft (line); | |
1286 if (line.end.y > m_clipMax.y) | |
1287 ClipEndBottom (line); | |
1288 return true; | |
1289 · | |
1290 case 0x86: | |
1291 ClipStartTop (line); | |
1292 if (line.start.x > m_clipMax.x) | |
1293 return false; | |
1294 ClipEndRight (line); | |
1295 if (line.end.y > m_clipMax.y) | |
1296 ClipEndBottom (line); | |
1297 return true; | |
1298 · | |
1299 // top-left | |
1300 case 0x90: | |
1301 ClipStartLeft (line); | |
1302 if (line.start.y < m_clipMin.y) | |
1303 ClipStartTop (line); | |
1304 return true; | |
1305 · | |
1306 case 0x92: | |
1307 ClipEndRight (line); | |
1308 if (line.end.y < m_clipMin.y) | |
1309 return false; | |
1310 ClipStartTop (line); | |
1311 if (line.start.x < m_clipMin.x) | |
1312 ClipStartLeft (line); | |
1313 return true; | |
1314 · | |
1315 case 0x94: | |
1316 ClipEndBottom (line); | |
1317 if (line.end.x < m_clipMin.x) | |
1318 return false; | |
1319 ClipStartLeft (line); | |
1320 if (line.start.y < m_clipMin.y) | |
1321 ClipStartTop (line); | |
1322 return true; | |
1323 · | |
1324 case 0x96: | |
1325 ClipStartLeft (line); | |
1326 if (line.start.y > m_clipMax.y) | |
1327 return false; | |
1328 ClipEndRight (line); | |
1329 if (line.end.y < m_clipMin.y) | |
1330 return false; | |
1331 if (line.start.y < m_clipMin.y) | |
1332 ClipStartTop (line); | |
1333 if (line.end.y > m_clipMax.y) | |
1334 ClipEndBottom (line); | |
1335 return true; | |
1336 · | |
1337 // top-right | |
1338 case 0xA0: | |
1339 ClipStartRight (line); | |
1340 if (line.start.y < m_clipMin.y) | |
1341 ClipStartTop (line); | |
1342 return true; | |
1343 · | |
1344 case 0xA1: | |
1345 ClipEndLeft (line); | |
1346 if (line.end.y < m_clipMin.y) | |
1347 return false; | |
1348 ClipStartTop (line); | |
1349 if (line.start.x > m_clipMax.x) | |
1350 ClipStartRight (line); | |
1351 return true; | |
1352 · | |
1353 case 0xA4: | |
1354 ClipEndBottom (line); | |
1355 if (line.end.x > m_clipMax.x) | |
1356 return false; | |
1357 ClipStartRight (line); | |
1358 if (line.start.y < m_clipMin.y) | |
1359 ClipStartTop (line); | |
1360 return true; | |
1361 · | |
1362 case 0xA5: | |
1363 ClipEndLeft (line); | |
1364 if (line.end.y < m_clipMin.y) | |
1365 return false; | |
1366 ClipStartRight (line); | |
1367 if (line.start.y > m_clipMax.y) | |
1368 return false; | |
1369 if (line.end.y > m_clipMax.y) | |
1370 ClipEndBottom (line); | |
1371 if (line.start.y < m_clipMin.y) | |
1372 ClipStartTop (line); | |
1373 return true; | |
1374 } | |
1375 · | |
1376 return false; | |
1377 } | |
1378 }; | |
1379 } | |
1380 | |
1381 void | |
1382 PyViz::LineClipping (double boundsX1, double boundsY1, double boundsX2, double b oundsY2, | |
1383 double &lineX1, double &lineY1, double &lineX2, double &lin eY2) | |
1384 { | |
1385 FastClipping::Vector2 clipMin = {boundsX1, boundsY1}, clipMax = {boundsX2, bou ndsY2}; | |
1386 FastClipping::Line line = { { lineX1, lineY1 }, { lineX2, lineY2 }, (lineX2-li neX1), (lineY2-lineY1) }; | |
1387 | |
1388 FastClipping clipper (clipMin, clipMax); | |
1389 clipper.ClipLine (line); | |
1390 lineX1 = line.start.x; | |
1391 lineX2 = line.end.x; | |
1392 lineY1 = line.start.y; | |
1393 lineY2 = line.end.y; | |
1394 } | |
1395 | |
1396 | |
1397 } | |
1398 | |
OLD | NEW |