<commit_before>/*
 * IP address for the multicast group 224.0.0.224
 * Port for multicast group 45454
 *
 *
 * broadcasts are of the format
 * [type][channel][nick][contents]
 * type is a 4 byte string, currently "edct" for normal edicts, "mdct" for medicts, "ntfy" for notifies.
 * channel is a 64 byte string which contains the destination channel for the message terminated with zero characters.
 * nick is the same size and idea as channel, except it contains the nick of the sender.
 * contents is a max 256 byte string of whatever the text being sent is.  If the contents are shorter, the broadcast is shorter to match.
 *
 * a periodic broadcast of type "here" is sent out every minute; it's format is
 * [type][nick]
 * type is the standard 4 byte string, and nick is a max 64 byte
 *
 * To Do:
 * make sure the nick/channel/message length being broadcast is short enough
 * toss a notify to the UI if ^ fails
 *
 * add the timed "still here" messages
 */

#include <thread>
#include <iostream>
#include <QByteArray>
#include <QString>
#include <QSettings>
#include <QtNetwork>
#include <unordered_set>
#include <ctime>

#include "lirch_constants.h"
#include "blocker_messages.h"
#include "edict_messages.h"
#include "received_messages.h"
#include "lirch_plugin.h"
#include "lirch_constants.h"
#include "grinder_messages.h"
#include "notify_messages.h"

using namespace std;

//this nonsense is needed in order to have our blocklist be searchable
namespace std
{
	template <>
	struct hash<QHostAddress>
	{
		size_t operator()(const QHostAddress& v) const
		{
			return std::hash<std::string>()(v.toString().toStdString());
		}
	};
}

message sendBlock(QString str, QString)
{
	if (str.startsWith("/block "))
		return block_message::create(block_message_subtype::ADD,QHostAddress(str.section(' ',1)));
	return empty_message::create();
}

message sendUnblock(QString str, QString)
{
	if (str.startsWith("/unblock "))
		return block_message::create(block_message_subtype::REMOVE,QHostAddress(str.section(' ',1)));
	return empty_message::create();
}

QByteArray formatMessage(QString type, QString channel, QString nick, QString contents);

void run(plugin_pipe p, string name)
{
	unordered_set<QHostAddress> blocklist;

	time_t lastSent=time(NULL);

	//register for the message types the antenna can handle
	p.write(registration_message::create(0, name, "block"));
	p.write(registration_message::create(0, name, "edict"));
	p.write(registration_message::create(0, name, "handler_ready"));

	p.write(register_handler::create("/block", sendBlock));
	p.write(register_handler::create("/unblock", sendUnblock));

	//connect to multicast group
	QUdpSocket udpSocket;
	QHostAddress groupAddress(LIRCH_DEFAULT_ADDR);
	quint16 port = LIRCH_DEFAULT_PORT;

	//TODO: Explicitly set QAbstractSocket::MulticastLoopbackOption to 1
	if (!udpSocket.bind(groupAddress,port,QUdpSocket::ShareAddress))
	{
		p.write(notify_message::create("default","Failed to bind."));
		return;
	}
	if(!udpSocket.joinMulticastGroup(groupAddress))
	{
		p.write(notify_message::create("default","Failed to join Multicast Group."));
		return;
	}

	//needed to send nick with your messages
	QSettings settings(QSettings::IniFormat, QSettings::UserScope, LIRCH_COMPANY_NAME, "Lirch");
	settings.beginGroup("UserData");

	while(true)
	{
		while (p.has_message())
		{
			message m = p.read();

			if (m.type=="shutdown")
			{
				udpSocket.leaveMulticastGroup(groupAddress);
				udpSocket.close();
				return;
			}
			else if (m.type=="registration_status")
			{
				auto s=dynamic_cast<registration_status *>(m.getdata());
				if (!s)
					continue;
				//Retry 2000 times until we succeed
				if (!s->status)
				{
					if (s->priority<2000)
						p.write(registration_message::create(s->priority+1, name, s->type));
				}
			}
			else if(m.type=="handler_ready")
			{
				p.write(register_handler::create("/block", sendBlock));
				p.write(register_handler::create("/unblock", sendUnblock));
				p.write(m.decrement_priority());
			}
			else if(m.type=="block")
			{
				auto castMessage=dynamic_cast<block_message *>(m.getdata());

				//if it's not actually a block message, ignore it and move on
				if (!castMessage)
					continue;

				//this contains the IP that /block or /unblock was called on
				auto toModify=castMessage->ip;

				if(castMessage->subtype==block_message_subtype::ADD)
				{
					blocklist.insert(toModify);
					p.write(notify_message::create("default",toModify.toString()+" is now blocked."));
				}
				if(castMessage->subtype==block_message_subtype::REMOVE)
				{
					blocklist.erase(toModify);
					p.write(notify_message::create("default",toModify.toString()+" is now unblocked."));
				}
			}
			else if(m.type=="edict")
			{
				auto castMessage=dynamic_cast<edict_message *>(m.getdata());

				//if it's not actually an edict message, ignore it and move on
				if (!castMessage)
					continue;

				QString nick=settings.value("nick","spartacus").value<QString>();
				QString channel=castMessage->channel;
				QString contents=castMessage->contents;
				QString type;
				if(castMessage->subtype==edict_message_subtype::NORMAL)
					type="edct";
				else if(castMessage->subtype==edict_message_subtype::ME)
					type="mdct";
				QByteArray message = formatMessage(type,channel,nick,contents);

				//change to use write() function when we have time
				if(message.length()>0)
				{
					udpSocket.writeDatagram(message,groupAddress,port);
					lastSent=time(NULL);
				}
			}
			else if(m.type=="sendable_notify")
			{
				auto castMessage=dynamic_cast<sendable_notify_message *>(m.getdata());

				//if it's not actually an edict message, ignore it and move on
				if (!castMessage)
					continue;

				QString nick=settings.value("nick","spartacus").value<QString>();
				QString channel=castMessage->channel;
				QString contents=castMessage->contents;
				QString type="ntfy";

				QByteArray message = formatMessage(type,channel,nick,contents);

				//change to use write() function when we have time
				if(message.length()>0)
				{
					udpSocket.writeDatagram(message,groupAddress,port);
					lastSent=time(NULL);
				}
			}
			//if somehow a message is recieved that is not of these types, send it back.
			else
			{
				p.write(m.decrement_priority());
			}
		}

		while (udpSocket.hasPendingDatagrams())
		{
			char broadcast[512];
			QHostAddress senderIP;
			quint16 senderPort;
			qint64 size = udpSocket.readDatagram(broadcast,512,&senderIP,&senderPort);
			broadcast[size]='\0';
			if(blocklist.end()!=blocklist.find(senderIP))
				continue;

			string type(broadcast,4);

			if (type=="here")
			{
				p.write(received_message::create(received_message_subtype::HERE,"",QString::fromUtf8(broadcast+4),"",senderIP));
				continue;
			}

			QString destinationChannel=QString::fromUtf8(broadcast+4);
			QString senderNick=QString::fromUtf8(broadcast+68);
			QString sentContents=QString::fromUtf8(broadcast+132);

			if (type=="edct")
			{
				p.write(received_message::create(received_message_subtype::NORMAL,destinationChannel,senderNick,sentContents,senderIP));
			}
			else if (type=="mdct")
			{
				p.write(received_message::create(received_message_subtype::ME,destinationChannel,senderNick,sentContents,senderIP));
			}
			else if (type=="ntfy")
			{
				p.write(received_message::create(received_message_subtype::NOTIFY,destinationChannel,senderNick,sentContents,senderIP));
			}
			else
			{
				continue;
			}

		}

		//sends out a "still here" message every minute
		if(time(NULL)-lastSent>60)
		{
			QString nick=settings.value("nick","spartacus").value<QString>();
			QString type="here";

			QByteArray message = type.toUtf8()+nick.toUtf8();
			message.truncate(68);

			udpSocket.writeDatagram(message,groupAddress,port);
			lastSent=time(NULL);
		}

		this_thread::sleep_for(chrono::milliseconds(50));

	}

};

//if components are too long, the cropped version might not have a \0 to terminate it.  might need fixing later.
QByteArray formatMessage(QString type, QString channel, QString nick, QString contents)
{
	QByteArray output;
	output += type.toUtf8();
	output += channel.toUtf8().leftJustified(64,'\0',true);
	output += nick.toUtf8().leftJustified(64,'\0',true);
	QByteArray holder =contents.toUtf8();
	if (holder.length()>256)
	{
		return QByteArray();
	}
	output += holder;
	output += '\0';
	return output;
};
<commit_msg>made broadcast fields not spill into one another<commit_after>/*
 * IP address for the multicast group 224.0.0.224
 * Port for multicast group 45454
 *
 *
 * broadcasts are of the format
 * [type][channel][nick][contents]
 * type is a 4 byte string, currently "edct" for normal edicts, "mdct" for medicts, "ntfy" for notifies.
 * channel is a 64 byte string which contains the destination channel for the message terminated with zero characters.
 * nick is the same size and idea as channel, except it contains the nick of the sender.
 * contents is a max 256 byte string of whatever the text being sent is.  If the contents are shorter, the broadcast is shorter to match.
 *
 * a periodic broadcast of type "here" is sent out every minute; it's format is
 * [type][nick]
 * type is the standard 4 byte string, and nick is a max 64 byte
 *
 * To Do:
 * make sure the nick/channel/message length being broadcast is short enough
 * toss a notify to the UI if ^ fails
 *
 * add the timed "still here" messages
 */

#include <thread>
#include <iostream>
#include <QByteArray>
#include <QString>
#include <QSettings>
#include <QtNetwork>
#include <unordered_set>
#include <ctime>

#include "lirch_constants.h"
#include "blocker_messages.h"
#include "edict_messages.h"
#include "received_messages.h"
#include "lirch_plugin.h"
#include "lirch_constants.h"
#include "grinder_messages.h"
#include "notify_messages.h"

using namespace std;

//this nonsense is needed in order to have our blocklist be searchable
namespace std
{
	template <>
	struct hash<QHostAddress>
	{
		size_t operator()(const QHostAddress& v) const
		{
			return std::hash<std::string>()(v.toString().toStdString());
		}
	};
}

message sendBlock(QString str, QString)
{
	if (str.startsWith("/block "))
		return block_message::create(block_message_subtype::ADD,QHostAddress(str.section(' ',1)));
	return empty_message::create();
}

message sendUnblock(QString str, QString)
{
	if (str.startsWith("/unblock "))
		return block_message::create(block_message_subtype::REMOVE,QHostAddress(str.section(' ',1)));
	return empty_message::create();
}

QByteArray formatMessage(QString type, QString channel, QString nick, QString contents);

void run(plugin_pipe p, string name)
{
	unordered_set<QHostAddress> blocklist;

	time_t lastSent=time(NULL);

	//register for the message types the antenna can handle
	p.write(registration_message::create(0, name, "block"));
	p.write(registration_message::create(0, name, "edict"));
	p.write(registration_message::create(0, name, "handler_ready"));

	p.write(register_handler::create("/block", sendBlock));
	p.write(register_handler::create("/unblock", sendUnblock));

	//connect to multicast group
	QUdpSocket udpSocket;
	QHostAddress groupAddress(LIRCH_DEFAULT_ADDR);
	quint16 port = LIRCH_DEFAULT_PORT;

	//TODO: Explicitly set QAbstractSocket::MulticastLoopbackOption to 1
	if (!udpSocket.bind(groupAddress,port,QUdpSocket::ShareAddress))
	{
		p.write(notify_message::create("default","Failed to bind."));
		return;
	}
	if(!udpSocket.joinMulticastGroup(groupAddress))
	{
		p.write(notify_message::create("default","Failed to join Multicast Group."));
		return;
	}

	//needed to send nick with your messages
	QSettings settings(QSettings::IniFormat, QSettings::UserScope, LIRCH_COMPANY_NAME, "Lirch");
	settings.beginGroup("UserData");

	while(true)
	{
		while (p.has_message())
		{
			message m = p.read();

			if (m.type=="shutdown")
			{
				udpSocket.leaveMulticastGroup(groupAddress);
				udpSocket.close();
				return;
			}
			else if (m.type=="registration_status")
			{
				auto s=dynamic_cast<registration_status *>(m.getdata());
				if (!s)
					continue;
				//Retry 2000 times until we succeed
				if (!s->status)
				{
					if (s->priority<2000)
						p.write(registration_message::create(s->priority+1, name, s->type));
				}
			}
			else if(m.type=="handler_ready")
			{
				p.write(register_handler::create("/block", sendBlock));
				p.write(register_handler::create("/unblock", sendUnblock));
				p.write(m.decrement_priority());
			}
			else if(m.type=="block")
			{
				auto castMessage=dynamic_cast<block_message *>(m.getdata());

				//if it's not actually a block message, ignore it and move on
				if (!castMessage)
					continue;

				//this contains the IP that /block or /unblock was called on
				auto toModify=castMessage->ip;

				if(castMessage->subtype==block_message_subtype::ADD)
				{
					blocklist.insert(toModify);
					p.write(notify_message::create("default",toModify.toString()+" is now blocked."));
				}
				if(castMessage->subtype==block_message_subtype::REMOVE)
				{
					blocklist.erase(toModify);
					p.write(notify_message::create("default",toModify.toString()+" is now unblocked."));
				}
			}
			else if(m.type=="edict")
			{
				auto castMessage=dynamic_cast<edict_message *>(m.getdata());

				//if it's not actually an edict message, ignore it and move on
				if (!castMessage)
					continue;

				QString nick=settings.value("nick","spartacus").value<QString>();
				QString channel=castMessage->channel;
				QString contents=castMessage->contents;
				QString type;
				if(castMessage->subtype==edict_message_subtype::NORMAL)
					type="edct";
				else if(castMessage->subtype==edict_message_subtype::ME)
					type="mdct";
				QByteArray message = formatMessage(type,channel,nick,contents);

				//change to use write() function when we have time
				if(message.length()>0)
				{
					udpSocket.writeDatagram(message,groupAddress,port);
					lastSent=time(NULL);
				}
			}
			else if(m.type=="sendable_notify")
			{
				auto castMessage=dynamic_cast<sendable_notify_message *>(m.getdata());

				//if it's not actually an edict message, ignore it and move on
				if (!castMessage)
					continue;

				QString nick=settings.value("nick","spartacus").value<QString>();
				QString channel=castMessage->channel;
				QString contents=castMessage->contents;
				QString type="ntfy";

				QByteArray message = formatMessage(type,channel,nick,contents);

				//change to use write() function when we have time
				if(message.length()>0)
				{
					udpSocket.writeDatagram(message,groupAddress,port);
					lastSent=time(NULL);
				}
			}
			//if somehow a message is recieved that is not of these types, send it back.
			else
			{
				p.write(m.decrement_priority());
			}
		}

		while (udpSocket.hasPendingDatagrams())
		{
			char broadcast[512];
			QHostAddress senderIP;
			quint16 senderPort;
			qint64 size = udpSocket.readDatagram(broadcast,512,&senderIP,&senderPort);
			broadcast[size]='\0';
			if(blocklist.end()!=blocklist.find(senderIP))
				continue;

			string type(broadcast,4);

			if (type=="here")
			{
				p.write(received_message::create(received_message_subtype::HERE,"",QString::fromUtf8(broadcast+4),"",senderIP));
				continue;
			}

			//takes the components out of the broadcast and crops them apropriately, just in case
			QString destinationChannel=QString::fromUtf8(broadcast+4);
			destinationChannel.truncate(64);
			QString senderNick=QString::fromUtf8(broadcast+68);
			senderNick.truncate(64);
			QString sentContents=QString::fromUtf8(broadcast+132);
			sentContents.truncate(256);

			if (type=="edct")
			{
				p.write(received_message::create(received_message_subtype::NORMAL,destinationChannel,senderNick,sentContents,senderIP));
			}
			else if (type=="mdct")
			{
				p.write(received_message::create(received_message_subtype::ME,destinationChannel,senderNick,sentContents,senderIP));
			}
			else if (type=="ntfy")
			{
				p.write(received_message::create(received_message_subtype::NOTIFY,destinationChannel,senderNick,sentContents,senderIP));
			}
			else
			{
				continue;
			}
		}

		//sends out a "still here" message every minute
		if(time(NULL)-lastSent>60)
		{
			QString nick=settings.value("nick","spartacus").value<QString>();
			QString type="here";

			QByteArray message = type.toUtf8()+nick.toUtf8();
			message.truncate(68);

			udpSocket.writeDatagram(message,groupAddress,port);
			lastSent=time(NULL);
		}
		this_thread::sleep_for(chrono::milliseconds(50));
	}
};

//stores type in he first 4 bytes, channel in the 64 after that, then 64 for nick, and up to 256 for the contents of the message
QByteArray formatMessage(QString type, QString channel, QString nick, QString contents)
{
	QByteArray output;
	output += type.toUtf8();
	output += channel.toUtf8().leftJustified(64,'\0',true);
	output += nick.toUtf8().leftJustified(64,'\0',true);
	QByteArray holder =contents.toUtf8();
	if (holder.length()>256)
	{
		return QByteArray();
	}
	output += holder;
	output += '\0';
	return output;
};
<|endoftext|>


<commit_before>
#include <silicon/server.hh>

iod_define_symbol(module, _Module);

namespace iod
{
  std::string javascript_call_procedure();

  template <typename S, typename... T>
  std::string generate_javascript_client(const S& s, T... _options)
  {
    auto desc = server_api_description(s);

    auto opts = D(_options...);

    std::ostringstream calls;

    auto handlers = s.get_handlers();
    for (int i = 0; i < desc.size(); i++)
    {
      //visit(h)
      calls << "  // ";
      print_procedure_desc(calls, desc[i]);
      calls << std::endl;
      calls << "  this." << desc[i].name << " = function(params) { return this.call_procedure(" << i << ", params); }" << std::endl;
      calls << std::endl;
    }

    std::string module = opts.get(_Module, "sl");

    std::ostringstream src;

    src << "function " << module << "() {" << std::endl;
    src << javascript_call_procedure();
    src << calls.str();
    src << "}" << std::endl;

    return src.str();
  }

  std::string javascript_call_procedure()
  {
    return R"javascript(
  var server_url = "/";
  this.set_server = function(url) { server_url = url; }
  this.call_procedure = function(id, params)
  {
    // Return a new promise.
    var _this = this;
    return new Promise(function(resolve, reject) {
      // Do the usual XHR stuff
      var req = new XMLHttpRequest();
      req.open('POST', _this.server_url);

      req.onload = function() {
        // This is called even on 404 etc
        // so check the status
        if (req.status == 200) {
          // Resolve the promise with the response text
          resolve(req.response);
        }
        else {
          // Otherwise reject with the status text
          // which will hopefully be a meaningful error
          reject(Error(req.statusText));
        }
      };

      // Handle network errors
      req.onerror = function() {
        reject(Error("Network Error"));
      };

      // Make the request
      body = JSON.stringify({ handler_id: id}) + JSON.stringify(params);
      req.send(body);
    });
  }

)javascript";

  }
}
<commit_msg>Handle return types of procedures in javascript client.<commit_after>
#include <silicon/server.hh>

namespace iod
{
  std::string javascript_api_base();

  template <typename S, typename... T>
  std::string generate_javascript_client(const S& s, T... _options)
  {
    auto opts = D(_options...);
    std::string module = opts.get(_Module, "sl");

    auto desc = server_api_description(s);

    std::ostringstream calls;

    auto handlers = s.get_handlers();
    for (int i = 0; i < desc.size(); i++)
    {
      std::string ret = desc[i].return_type;
      if (ret[0] == '{') ret = "json";

      calls << "  // ";
      print_procedure_desc(calls, desc[i]);
      calls << std::endl;
      calls << "  " << module << ".prototype." << desc[i].name << " = function(params) { return this.call_procedure(" << i << ", params, '" << ret << "'); }" << std::endl;
      calls << std::endl;
    }

    std::ostringstream src;

    src << javascript_api_base();
    src << "var " << module << " = new silicon_api_base();" << std::endl;
    src << calls.str();
    src << "}" << std::endl;

    return src.str();
  }

  std::string javascript_api_base()
  {
    return R"javascript(

function silicon_api_base()
{
  this.server_url = "/";
  this.set_server = function(url) { this.server_url = url; }
  this.call_procedure = function(id, params, return_type)
  {
    // Return a new promise.
    var _this = this;
    return new Promise(function(resolve, reject) {
      // Do the usual XHR stuff
      var req = new XMLHttpRequest();
      req.open('POST', _this.server_url);

      req.onload = function() {
        // This is called even on 404 etc
        // so check the status
        if (req.status == 200) {
          // Resolve the promise with the response text
          switch (return_type) {
          case "int":    resolve(parseInt(req.response)); break;
          case "float":  resolve(parseFloat(req.response)); break;
          case "json":   resolve(JSON.parse(req.response)); break;
          default: resolve(req.response); break;
        }
        else {
          // Otherwise reject with the request object.
          reject(req);
        }
      };

      // Handle network errors
      req.onerror = function() {
        reject(Error("Network Error"));
      };

      // Make the request
      body = JSON.stringify({ handler_id: id}) + JSON.stringify(params);
      req.send(body);
    });
  }

}

)javascript";

  }
}
<|endoftext|>


<commit_before>// __BEGIN_LICENSE__
// Copyright (C) 2006-2010 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__

#include <vw/BundleAdjustment/BundleAdjustReport.h>
namespace fs = boost::filesystem;

namespace vw {
namespace ba {

  void write_kml_styles( KMLFile& kml ) {
    // GCP Placemark Style
    kml.append_style( "gcp_circle", "", 1.2,
                      "http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png" );
    kml.append_style( "gcp_circle_highlight", "", 1.4,
                      "http://maps.google.com/mapfiles/kml/shapes/placemark_circle_highlight.png" );
    kml.append_stylemap( "gcp_placemark", "gcp_circle",
                         "gcp_circle_highlight" );

    // Est Circle Lvl 1 (Green) Placemark
    kml.append_style( "est_circle_1", "ff00ff00", 0.8,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_style( "est_circle_1_highlight", "ff00ff00", 0.9,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_stylemap( "est_placemark_1", "est_circle_1",
                         "est_circle_1_highlight" );

    // Est Circle Lvl 2 (Green-Yellow) Placemark
    kml.append_style( "est_circle_2", "ff00ff80", 0.8,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_style( "est_circle_2_highlight", "ff00ff80", 0.9,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_stylemap( "est_placemark_2", "est_circle_2",
                         "est_circle_2_highlight" );

    // Est Circle Lvl 3 (Yellow) Placemark
    kml.append_style( "est_circle_3", "ff00ffff", 0.8,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_style( "est_circle_3_highlight", "ff00ffff", 0.9,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_stylemap( "est_placemark_3", "est_circle_3",
                         "est_circle_3_highlight" );

    // Est Circle Lvl 4 (Red-Yellow) Placemark
    kml.append_style( "est_circle_4", "ff0080ff", 0.8,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_style( "est_circle_4_highlight", "ff0080ff", 0.9,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_stylemap( "est_placemark_4", "est_circle_4",
                         "est_circle_4_highlight" );

    // Est Circle Lvl 5 (Red) Placemark
    kml.append_style( "est_circle_5", "ff0000ff", 0.8,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_style( "est_circle_5_highlight", "ff0000ff", 0.9,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_stylemap( "est_placemark_5", "est_circle_5",
                         "est_circle_5_highlight" );
  }

  void write_gcps_kml( KMLFile& kml,
                       ControlNetwork const& cnet ) {
    kml.enter_folder( "Ground Control Points",
                      "Used for Bundle Adjustment in VW" );

    unsigned count = 0;
    for ( ControlNetwork::const_iterator iter = cnet.begin();
          iter != cnet.end(); ++iter ) {
      if ( (*iter).type() == ControlPoint::GroundControlPoint ) {
        count++;
        Vector3 llr = cartography::xyz_to_lon_lat_radius( (*iter).position() );

        std::ostringstream desc;
        // GCP data
        desc << "
Ground Control Point
";
        desc << "Lon: " << llr.x() << " deg
";
        desc << "Lat: " << llr.y() << " deg
";
        desc << "Rad: " << llr.z() << " m
";

        // Images viewing
        desc << "
Viewed by:

";
        for ( ControlPoint::const_iterator measure = (*iter).begin();
              measure != (*iter).end(); ++measure ) {
          desc << "
" << "[" << (*measure).image_id() << "] "
               << (*measure).serial() << "
";
        }
        desc << "
";

        if ( (*iter).id() != "Null" ) {
          kml.append_placemark( llr.x(), llr.y(),
                                (*iter).id(), desc.str(),
                                "gcp_placemark" );
        } else {
          std::ostringstream gcp_name;
          gcp_name << "GCP " << count;
          kml.append_placemark( llr.x(), llr.y(),
                                gcp_name.str(), desc.str(),
                                "gcp_placemark" );
        }
      }
    }

    kml.exit_folder();
  }

  void write_3d_est_kml( KMLFile& kml,
                         ControlNetwork const& cnet,
                         std::vector<double>& image_errors ) {
    kml.enter_folder( "3D Point estimates",
                      "Used for Bundle Adjustment in VW" );

    std::list<Vector3> points; // Lon, Lat, Interest

    unsigned index = 0;
    for ( ControlNetwork::const_iterator iter = cnet.begin();
          iter != cnet.end(); ++iter ) {
      Vector3 llr = cartography::xyz_to_lon_lat_radius( (*iter).position() );
      double mean_image_error = 0;
      int count_measures = 0;
      for ( ControlPoint::const_iterator m_iter = (*iter).begin();
            m_iter != (*iter).end(); ++m_iter ) {
        mean_image_error += image_errors[index];
        index++;
        count_measures++;
      }
      mean_image_error /= count_measures;
      if ( (*iter).type() == ControlPoint::TiePoint )
        points.push_back( Vector3(llr.x(),llr.y(), mean_image_error) );
    }

    // Grow a bounding box
    BBox2 total;
    for ( std::list<Vector3>::iterator it = points.begin();
          it != points.end(); ++it )
      total.grow( Vector2((*it).x(),(*it).y()) );

    // Building tiles of smaller bounding boxes
    Vector2f lower_corner = total.min();
    Vector2f upper_corner = total.max();
    lower_corner.x() = floor( lower_corner.x() );
    lower_corner.y() = floor( lower_corner.y() );
    upper_corner.x() = ceil( upper_corner.x() );
    upper_corner.y() = ceil( upper_corner.y() );

    // Finding the maximium and minimium error
    double min = 1e20, max = -1;
    for ( std::list<Vector3>::iterator it = points.begin();
          it != points.end(); ++it ) {
      if ( (*it).z() < min )
        min = (*it).z();
      if ( (*it).z() > max )
        max = (*it).z();
    }

    recursive_kml_placemark( kml, points, kml.name(), min, max,
                             upper_corner.y(), lower_corner.y(),
                             upper_corner.x(), lower_corner.x(), 0 );

    kml.exit_folder();
  }

  void recursive_kml_placemark( KMLFile& kml,
                                std::list<Vector3>& list,
                                std::string const& name,
                                double& min, double& max,
                                float& north, float& south,
                                float& east, float& west,
                                int recursive_lvl) {
    // Sub divides
    std::vector<float> north_dv;
    north_dv.push_back(north); north_dv.push_back(north);
    north_dv.push_back(south+(north-south)/2);
    north_dv.push_back( north_dv[2] );
    std::vector<float> south_dv;
    south_dv.push_back( north_dv[3] ); south_dv.push_back( north_dv[3] );
    south_dv.push_back( south ); south_dv.push_back( south );
    std::vector<float> east_dv;
    east_dv.push_back( east ); east_dv.push_back( west + (east-west)/2 );
    east_dv.push_back( east_dv[0] ); east_dv.push_back( east_dv[1] );
    std::vector<float> west_dv;
    west_dv.push_back( east_dv[1] ); west_dv.push_back( west );
    west_dv.push_back( west_dv[0] ); west_dv.push_back( west_dv[1] );
    double diff = max - min;

    // Checking list
    int count = 0;
    for ( std::list<Vector3>::iterator it = list.begin();
          it != list.end(); ++it )
      count++;
    if ( count <= 500 ) {
      // Write a termination file
      kml.enter_folder("","");

      // Regioning
      kml.open_bracket("Region");
      kml.append_latlonaltbox( north, south, east, west );
      kml.append_lod( 512, -1 );
      kml.close_bracket();

      // Placemarks
      for ( std::list<Vector3>::iterator it = list.begin();
            it != list.end(); ++it ) {
        std::ostringstream desc;
        desc << "Image error: " << (*it).z();
        if ( (*it).z() > 4*diff/5 + min )
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_5" );
        else if ( (*it).z() > 3*diff/5 + min )
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_4" );
        else if ( (*it).z() > 2*diff/5 + min )
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_3" );
        else if ( (*it).z() > 1*diff/5 + min )
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_2" );
        else
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_1" );
      }

      kml.exit_folder();
      return;
    } else {
      // Write a branching file
      list.sort( vector_sorting );

      kml.enter_folder("","");

      for ( char i = 0; i < 4; i++ ) {
        std::ostringstream link;
        if ( recursive_lvl == 0 )
          link << "data/";
        link << name << int(i) << ".kml";
        kml.append_network( link.str(),
                            north_dv[i], south_dv[i],
                            east_dv[i], west_dv[i] );
      }

      kml.enter_folder("","");

      // Regioning
      kml.open_bracket("Region");
      kml.append_latlonaltbox( north, south, east, west );
      kml.append_lod( 512, -1 );
      kml.close_bracket();

      // Placemarks
      count = 500;
      std::list<Vector3>::iterator it = list.begin();
      while ( count > 0 ) {
        std::ostringstream desc;
        desc << "Image error: " << (*it).z();
        if ( (*it).z() > 4*diff/5 + min )
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_5" );
        else if ( (*it).z() > 3*diff/5 + min )
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_4" );
        else if ( (*it).z() > 2*diff/5 + min )
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_3" );
        else if ( (*it).z() > 1*diff/5 + min )
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_2" );
        else
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_1" );
        it = list.erase( it );
        count--;
      }

      kml.exit_folder();
      kml.exit_folder();
    }

    // Making calls to make lower levels
    for ( char i = 0; i < 4; i++ ) {
      std::list<Vector3> temp;
      for ( std::list<Vector3>::iterator it = list.begin();
            it != list.end(); ++it )
        if ( (*it).y() < north_dv[i] && (*it).y() > south_dv[i] &&
             (*it).x() < east_dv[i] && (*it).x() > west_dv[i] ) {
          temp.push_back( *it );
          it = list.erase( it );
          it--;
        }
      if ( !temp.empty() ) {
        std::ostringstream new_name;
        new_name << name << int(i);
        std::ostringstream dir;
        if ( kml.directory() != "" )
          dir << kml.directory() << "/";
        if ( recursive_lvl == 0 )
          dir << "data/";
        KMLFile subsection( new_name.str() + ".kml",
                            new_name.str(), dir.str() );
        write_kml_styles( subsection );
        recursive_kml_placemark( subsection,
                                 temp, new_name.str(),
                                 min, max,
                                 north_dv[i], south_dv[i],
                                 east_dv[i], west_dv[i],
                                 recursive_lvl+1 );
      }
    }

    if ( !list.empty() )
      std::cout << "Error! Vector not empty!\n";

  }

  bool vector_sorting( Vector3 i, Vector3 j) {
    return (i.z() > j.z());
  }

}}
<commit_msg>Increased precision in BA report KML.<commit_after>// __BEGIN_LICENSE__
// Copyright (C) 2006-2010 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__

#include <vw/BundleAdjustment/BundleAdjustReport.h>
namespace fs = boost::filesystem;

namespace vw {
namespace ba {

  void write_kml_styles( KMLFile& kml ) {
    // GCP Placemark Style
    kml.append_style( "gcp_circle", "", 1.2,
                      "http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png" );
    kml.append_style( "gcp_circle_highlight", "", 1.4,
                      "http://maps.google.com/mapfiles/kml/shapes/placemark_circle_highlight.png" );
    kml.append_stylemap( "gcp_placemark", "gcp_circle",
                         "gcp_circle_highlight" );

    // Est Circle Lvl 1 (Green) Placemark
    kml.append_style( "est_circle_1", "ff00ff00", 0.8,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_style( "est_circle_1_highlight", "ff00ff00", 0.9,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_stylemap( "est_placemark_1", "est_circle_1",
                         "est_circle_1_highlight" );

    // Est Circle Lvl 2 (Green-Yellow) Placemark
    kml.append_style( "est_circle_2", "ff00ff80", 0.8,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_style( "est_circle_2_highlight", "ff00ff80", 0.9,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_stylemap( "est_placemark_2", "est_circle_2",
                         "est_circle_2_highlight" );

    // Est Circle Lvl 3 (Yellow) Placemark
    kml.append_style( "est_circle_3", "ff00ffff", 0.8,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_style( "est_circle_3_highlight", "ff00ffff", 0.9,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_stylemap( "est_placemark_3", "est_circle_3",
                         "est_circle_3_highlight" );

    // Est Circle Lvl 4 (Red-Yellow) Placemark
    kml.append_style( "est_circle_4", "ff0080ff", 0.8,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_style( "est_circle_4_highlight", "ff0080ff", 0.9,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_stylemap( "est_placemark_4", "est_circle_4",
                         "est_circle_4_highlight" );

    // Est Circle Lvl 5 (Red) Placemark
    kml.append_style( "est_circle_5", "ff0000ff", 0.8,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_style( "est_circle_5_highlight", "ff0000ff", 0.9,
                      "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png" );
    kml.append_stylemap( "est_placemark_5", "est_circle_5",
                         "est_circle_5_highlight" );
  }

  void write_gcps_kml( KMLFile& kml,
                       ControlNetwork const& cnet ) {
    kml.enter_folder( "Ground Control Points",
                      "Used for Bundle Adjustment in VW" );

    unsigned count = 0;
    for ( ControlNetwork::const_iterator iter = cnet.begin();
          iter != cnet.end(); ++iter ) {
      if ( (*iter).type() == ControlPoint::GroundControlPoint ) {
        count++;
        Vector3 llr = cartography::xyz_to_lon_lat_radius( (*iter).position() );

        std::ostringstream desc;
        // GCP data
        desc << "
Ground Control Point
";
        desc << "Lon: " << llr.x() << " deg
";
        desc << "Lat: " << llr.y() << " deg
";
        desc << "Rad: " << std::setprecision(12)
             << llr.z() << " m
";

        // Images viewing
        desc << "
Viewed by:

";
        for ( ControlPoint::const_iterator measure = (*iter).begin();
              measure != (*iter).end(); ++measure ) {
          desc << "
" << "[" << (*measure).image_id() << "] "
               << (*measure).serial() << " ( " << measure->position()[0] << ", "
               << measure->position()[1] <<  " ) " << "
";
        }
        desc << "
";

        if ( (*iter).id() != "Null" ) {
          kml.append_placemark( llr.x(), llr.y(),
                                (*iter).id(), desc.str(),
                                "gcp_placemark" );
        } else {
          std::ostringstream gcp_name;
          gcp_name << "GCP " << count;
          kml.append_placemark( llr.x(), llr.y(),
                                gcp_name.str(), desc.str(),
                                "gcp_placemark" );
        }
      }
    }

    kml.exit_folder();
  }

  void write_3d_est_kml( KMLFile& kml,
                         ControlNetwork const& cnet,
                         std::vector<double>& image_errors ) {
    kml.enter_folder( "3D Point estimates",
                      "Used for Bundle Adjustment in VW" );

    std::list<Vector3> points; // Lon, Lat, Interest

    unsigned index = 0;
    for ( ControlNetwork::const_iterator iter = cnet.begin();
          iter != cnet.end(); ++iter ) {
      Vector3 llr = cartography::xyz_to_lon_lat_radius( (*iter).position() );
      double mean_image_error = 0;
      int count_measures = 0;
      for ( ControlPoint::const_iterator m_iter = (*iter).begin();
            m_iter != (*iter).end(); ++m_iter ) {
        mean_image_error += image_errors[index];
        index++;
        count_measures++;
      }
      mean_image_error /= count_measures;
      if ( (*iter).type() == ControlPoint::TiePoint )
        points.push_back( Vector3(llr.x(),llr.y(), mean_image_error) );
    }

    // Grow a bounding box
    BBox2 total;
    for ( std::list<Vector3>::iterator it = points.begin();
          it != points.end(); ++it )
      total.grow( Vector2((*it).x(),(*it).y()) );

    // Building tiles of smaller bounding boxes
    Vector2f lower_corner = total.min();
    Vector2f upper_corner = total.max();
    lower_corner.x() = floor( lower_corner.x() );
    lower_corner.y() = floor( lower_corner.y() );
    upper_corner.x() = ceil( upper_corner.x() );
    upper_corner.y() = ceil( upper_corner.y() );

    // Finding the maximium and minimium error
    double min = 1e20, max = -1;
    for ( std::list<Vector3>::iterator it = points.begin();
          it != points.end(); ++it ) {
      if ( (*it).z() < min )
        min = (*it).z();
      if ( (*it).z() > max )
        max = (*it).z();
    }

    recursive_kml_placemark( kml, points, kml.name(), min, max,
                             upper_corner.y(), lower_corner.y(),
                             upper_corner.x(), lower_corner.x(), 0 );

    kml.exit_folder();
  }

  void recursive_kml_placemark( KMLFile& kml,
                                std::list<Vector3>& list,
                                std::string const& name,
                                double& min, double& max,
                                float& north, float& south,
                                float& east, float& west,
                                int recursive_lvl) {
    // Sub divides
    std::vector<float> north_dv;
    north_dv.push_back(north); north_dv.push_back(north);
    north_dv.push_back(south+(north-south)/2);
    north_dv.push_back( north_dv[2] );
    std::vector<float> south_dv;
    south_dv.push_back( north_dv[3] ); south_dv.push_back( north_dv[3] );
    south_dv.push_back( south ); south_dv.push_back( south );
    std::vector<float> east_dv;
    east_dv.push_back( east ); east_dv.push_back( west + (east-west)/2 );
    east_dv.push_back( east_dv[0] ); east_dv.push_back( east_dv[1] );
    std::vector<float> west_dv;
    west_dv.push_back( east_dv[1] ); west_dv.push_back( west );
    west_dv.push_back( west_dv[0] ); west_dv.push_back( west_dv[1] );
    double diff = max - min;

    // Checking list
    int count = 0;
    for ( std::list<Vector3>::iterator it = list.begin();
          it != list.end(); ++it )
      count++;
    if ( count <= 500 ) {
      // Write a termination file
      kml.enter_folder("","");

      // Regioning
      kml.open_bracket("Region");
      kml.append_latlonaltbox( north, south, east, west );
      kml.append_lod( 512, -1 );
      kml.close_bracket();

      // Placemarks
      for ( std::list<Vector3>::iterator it = list.begin();
            it != list.end(); ++it ) {
        std::ostringstream desc;
        desc << "Image error: " << (*it).z();
        if ( (*it).z() > 4*diff/5 + min )
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_5" );
        else if ( (*it).z() > 3*diff/5 + min )
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_4" );
        else if ( (*it).z() > 2*diff/5 + min )
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_3" );
        else if ( (*it).z() > 1*diff/5 + min )
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_2" );
        else
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_1" );
      }

      kml.exit_folder();
      return;
    } else {
      // Write a branching file
      list.sort( vector_sorting );

      kml.enter_folder("","");

      for ( char i = 0; i < 4; i++ ) {
        std::ostringstream link;
        if ( recursive_lvl == 0 )
          link << "data/";
        link << name << int(i) << ".kml";
        kml.append_network( link.str(),
                            north_dv[i], south_dv[i],
                            east_dv[i], west_dv[i] );
      }

      kml.enter_folder("","");

      // Regioning
      kml.open_bracket("Region");
      kml.append_latlonaltbox( north, south, east, west );
      kml.append_lod( 512, -1 );
      kml.close_bracket();

      // Placemarks
      count = 500;
      std::list<Vector3>::iterator it = list.begin();
      while ( count > 0 ) {
        std::ostringstream desc;
        desc << "Image error: " << (*it).z();
        if ( (*it).z() > 4*diff/5 + min )
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_5" );
        else if ( (*it).z() > 3*diff/5 + min )
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_4" );
        else if ( (*it).z() > 2*diff/5 + min )
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_3" );
        else if ( (*it).z() > 1*diff/5 + min )
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_2" );
        else
          kml.append_placemark( (*it).x(), (*it).y(),
                                "", desc.str(),
                                "est_placemark_1" );
        it = list.erase( it );
        count--;
      }

      kml.exit_folder();
      kml.exit_folder();
    }

    // Making calls to make lower levels
    for ( char i = 0; i < 4; i++ ) {
      std::list<Vector3> temp;
      for ( std::list<Vector3>::iterator it = list.begin();
            it != list.end(); ++it )
        if ( (*it).y() < north_dv[i] && (*it).y() > south_dv[i] &&
             (*it).x() < east_dv[i] && (*it).x() > west_dv[i] ) {
          temp.push_back( *it );
          it = list.erase( it );
          it--;
        }
      if ( !temp.empty() ) {
        std::ostringstream new_name;
        new_name << name << int(i);
        std::ostringstream dir;
        if ( kml.directory() != "" )
          dir << kml.directory() << "/";
        if ( recursive_lvl == 0 )
          dir << "data/";
        KMLFile subsection( new_name.str() + ".kml",
                            new_name.str(), dir.str() );
        write_kml_styles( subsection );
        recursive_kml_placemark( subsection,
                                 temp, new_name.str(),
                                 min, max,
                                 north_dv[i], south_dv[i],
                                 east_dv[i], west_dv[i],
                                 recursive_lvl+1 );
      }
    }

    if ( !list.empty() )
      std::cout << "Error! Vector not empty!\n";

  }

  bool vector_sorting( Vector3 i, Vector3 j) {
    return (i.z() > j.z());
  }

}}
<|endoftext|>


<commit_before>/*******************************************************************************

Licensed to the OpenCOR team under one or more contributor license agreements.
See the NOTICE.txt file distributed with this work for additional information
regarding copyright ownership. The OpenCOR team licenses this file to you under
the Apache License, Version 2.0 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.

*******************************************************************************/

//==============================================================================
// User message widget
//==============================================================================

#include "guiutils.h"
#include "usermessagewidget.h"

//==============================================================================

#include <Qt>

//==============================================================================

#include <QBuffer>
#include <QFont>
#include <QIcon>
#include <QSizePolicy>
#include <QWidget>

//==============================================================================

namespace OpenCOR {
namespace Core {

//==============================================================================

void UserMessageWidget::constructor(const QString &pIcon,
                                    const QString &pMessage,
                                    const QString &pExtraMessage)
{
    // Some initialisations

    mIcon = QString();
    mMessage = QString();
    mExtraMessage = QString();

    // Customise our background

    setAutoFillBackground(true);
    setBackgroundRole(QPalette::Base);

    // Increase the size of our font

    QFont newFont = font();

    newFont.setPointSizeF(1.35*newFont.pointSize());

    setFont(newFont);

    // Some other customisations

    setContextMenuPolicy(Qt::NoContextMenu);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    setWordWrap(true);

    // 'Initialise' our message

    setIconMessage(pIcon, pMessage, pExtraMessage);
}

//==============================================================================

UserMessageWidget::UserMessageWidget(const QString &pIcon,
                                     const QString &pMessage,
                                     const QString &pExtraMessage,
                                     QWidget *pParent) :
    QLabel(pParent)
{
    // Construct our object

    constructor(pIcon, pMessage, pExtraMessage);
}

//==============================================================================

UserMessageWidget::UserMessageWidget(const QString &pIcon,
                                     const QString &pMessage,
                                     QWidget *pParent) :
    QLabel(pParent)
{
    // Construct our object

    constructor(pIcon, pMessage);
}

//==============================================================================

UserMessageWidget::UserMessageWidget(const QString &pIcon, QWidget *pParent) :
    QLabel(pParent)
{
    // Construct our object

    constructor(pIcon);
}

//==============================================================================

UserMessageWidget::UserMessageWidget(QWidget *pParent) :
    QLabel(pParent)
{
    // Construct our object

    constructor();
}

//==============================================================================

void UserMessageWidget::setIconMessage(const QString &pIcon,
                                       const QString &pMessage,
                                       const QString &pExtraMessage)
{
    // Set our message, if needed

    if (   pIcon.compare(mIcon)
        || pMessage.compare(mMessage)
        || pExtraMessage.compare(mExtraMessage)) {
        // Keep track of the new values for our icon, message and extra message

        mIcon = pIcon;
        mMessage = pMessage;
        mExtraMessage = pExtraMessage;

        // Set our text as HTML
        // Note: we want our icon to have a final size of 32px by 32px. However,
        //       it may be that it has a different size to begin with. Normally,
        //       we would rely on QLabel's HTML support (and in particular on
        //       the width and height attributes of the img element) to have our
        //       icon resized for us, but this results in a pixelated and
        //       therefore ugly image. So, instead, we retrieve a data URI for
        //       our resized icon...

        if (mExtraMessage.isEmpty())
            setText(QString("
"
                            "
"
                            "
"
                            "            "
                            "                "
                            "            	"
                            "            "
                            "
"
                            "                    %2"
                            "
"
                            "            	"
                            "
"
                            "
"
                            "
").arg(iconDataUri(mIcon, 32, 32), mMessage));
        else
            setText(QString("
"
                            "
"
                            "
"
                            "            "
                            "                "
                            "            	"
                            "            "
                            "
"
                            "                    %2"
                            "
"
                            "
"
                            "                    (%3)"
                            "
"
                            "            	"
                            "
"
                            "
"
                            "
").arg(iconDataUri(mIcon, 32, 32), mMessage, mExtraMessage));
    }
}

//==============================================================================

void UserMessageWidget::setMessage(const QString &pMessage,
                                   const QString &pExtraMessage)
{
    // Set our message

    setIconMessage(mIcon, pMessage, pExtraMessage);
}

//==============================================================================

}   // namespace Core
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Slight improvement to Core::UserMessageWidget.<commit_after>/*******************************************************************************

Licensed to the OpenCOR team under one or more contributor license agreements.
See the NOTICE.txt file distributed with this work for additional information
regarding copyright ownership. The OpenCOR team licenses this file to you under
the Apache License, Version 2.0 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.

*******************************************************************************/

//==============================================================================
// User message widget
//==============================================================================

#include "guiutils.h"
#include "usermessagewidget.h"

//==============================================================================

#include <Qt>

//==============================================================================

#include <QBuffer>
#include <QFont>
#include <QIcon>
#include <QSizePolicy>
#include <QWidget>

//==============================================================================

namespace OpenCOR {
namespace Core {

//==============================================================================

void UserMessageWidget::constructor(const QString &pIcon,
                                    const QString &pMessage,
                                    const QString &pExtraMessage)
{
    // Some initialisations

    mIcon = QString();
    mMessage = QString();
    mExtraMessage = QString();

    // Customise our background

    setAutoFillBackground(true);
    setBackgroundRole(QPalette::Base);

    // Increase the size of our font

    QFont newFont = font();

    newFont.setPointSizeF(1.35*newFont.pointSize());

    setFont(newFont);

    // Some other customisations

    setContextMenuPolicy(Qt::NoContextMenu);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    setWordWrap(true);

    // 'Initialise' our message

    setIconMessage(pIcon, pMessage, pExtraMessage);
}

//==============================================================================

UserMessageWidget::UserMessageWidget(const QString &pIcon,
                                     const QString &pMessage,
                                     const QString &pExtraMessage,
                                     QWidget *pParent) :
    QLabel(pParent)
{
    // Construct our object

    constructor(pIcon, pMessage, pExtraMessage);
}

//==============================================================================

UserMessageWidget::UserMessageWidget(const QString &pIcon,
                                     const QString &pMessage,
                                     QWidget *pParent) :
    QLabel(pParent)
{
    // Construct our object

    constructor(pIcon, pMessage);
}

//==============================================================================

UserMessageWidget::UserMessageWidget(const QString &pIcon, QWidget *pParent) :
    QLabel(pParent)
{
    // Construct our object

    constructor(pIcon);
}

//==============================================================================

UserMessageWidget::UserMessageWidget(QWidget *pParent) :
    QLabel(pParent)
{
    // Construct our object

    constructor();
}

//==============================================================================

void UserMessageWidget::setIconMessage(const QString &pIcon,
                                       const QString &pMessage,
                                       const QString &pExtraMessage)
{
    // Set our message, if needed

    if (   pIcon.compare(mIcon)
        || pMessage.compare(mMessage)
        || pExtraMessage.compare(mExtraMessage)) {
        // Keep track of the new values for our icon, message and extra message

        mIcon = pIcon;
        mMessage = pMessage;
        mExtraMessage = pExtraMessage;

        // Set our text as HTML
        // Note: we want our icon to have a final size of 32px by 32px. However,
        //       it may be that it has a different size to begin with. Normally,
        //       we would rely on QLabel's HTML support (and in particular on
        //       the width and height attributes of the img element) to have our
        //       icon resized for us, but this results in a pixelated and
        //       therefore ugly image. So, instead, we retrieve a data URI for
        //       our resized icon...

        if (mExtraMessage.isEmpty())
            setText(QString("
"
                            "
"
                            "
"
                            "            "
                            "                "
                            "            	"
                            "            "
                            "
"
                            "                    %2"
                            "
"
                            "            	"
                            "
"
                            "
"
                            "
").arg(iconDataUri(mIcon, 32, 32), mMessage));
        else
            setText(QString("
"
                            "
"
                            "
"
                            "            "
                            "                "
                            "            	"
                            "            "
                            "
"
                            "                    %2"
                            "
"
                            "
"
                            "                    (%3)"
                            "
"
                            "            	"
                            "
"
                            "
"
                            "
").arg(iconDataUri(mIcon, 32, 32), mMessage, mExtraMessage));
    }
}

//==============================================================================

void UserMessageWidget::setMessage(const QString &pMessage,
                                   const QString &pExtraMessage)
{
    // Set our message

    setIconMessage(mIcon, pMessage, pExtraMessage);
}

//==============================================================================

}   // namespace Core
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>


<commit_before>#include <b9/interpreter.hpp>
#include <b9/jit.hpp>
#include <b9/loader.hpp>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>

/// B9run's usage string. Printed when run with -help.
static const char* usage =
    "Usage: b9run [<option>...] [--] <module> [<main>]\n"
    "   Or: b9run -help\n"
    "Jit Options:\n"
    "  -jit:         Enable the jit\n"
    "  -directcall:  make direct jit to jit calls\n"
    "  -passparam:   Pass arguments in CPU registers\n"
    "  -lazyvmstate: Only update the VM state as needed\n"
    "Run Options:\n"
    "  -loop <n>:    Run the program <n> times\n"
    "  -inline <n>:  Enable inlining\n"
    "  -debug:       Enable debug code\n"
    "  -verbose:     Run with verbose printing\n"
    "  -help:        Print this help message";

/// The b9run program's global configuration.
struct RunConfig {
  b9::Config b9;
  const char* moduleName = "";
  const char* mainFunction = "b9main";
  std::size_t loopCount = 1;
  bool verbose = false;
  std::vector<b9::StackElement> usrArgs;
};

std::ostream& operator<<(std::ostream& out, const RunConfig& cfg) {
  out << "Module:       " << cfg.moduleName << std::endl
      << "Function:     " << cfg.mainFunction << std::endl
      << "Looping:      " << cfg.loopCount << std::endl;

  out << "Arguments:    [ ";
  for (const auto& arg : cfg.usrArgs) {
    out << arg << " ";
  }
  out << "]" << std::endl;

  out << cfg.b9;
  return out;
}

/// Parse CLI arguments and set up the config.
static bool parseArguments(RunConfig& cfg, const int argc, char* argv[]) {
  std::size_t i = 1;

  for (; i < argc; i++) {
    const char* arg = argv[i];

    if (strcmp(arg, "-help") == 0) {
      std::cout << usage << std::endl;
      exit(EXIT_SUCCESS);
    } else if (strcmp(arg, "-loop") == 0) {
      cfg.loopCount = atoi(argv[++i]);
    } else if (strcmp(arg, "-inline") == 0) {
      cfg.b9.maxInlineDepth = atoi(argv[++i]);
    } else if (strcmp(arg, "-verbose") == 0) {
      cfg.verbose = true;
      cfg.b9.verbose = true;
    } else if (strcmp(arg, "-debug") == 0) {
      cfg.b9.debug = true;
    } else if (strcmp(arg, "-function") == 0) {
      cfg.mainFunction = argv[++i];
    } else if (strcmp(arg, "-jit") == 0) {
      cfg.b9.jit = true;
    } else if (strcmp(arg, "-directcall") == 0) {
      cfg.b9.directCall = true;
    } else if (strcmp(arg, "-passparam") == 0) {
      cfg.b9.passParam = true;
    } else if (strcmp(arg, "-lazyvmstate") == 0) {
      cfg.b9.lazyVmState = true;
    } else if (strcmp(arg, "--") == 0) {
      i++;
      break;
    } else if (strcmp(arg, "-") == 0) {
      std::cerr << "Unrecognized option: " << arg << std::endl;
      return false;
    } else {
      break;
    }
  }

  // check for user defined module
  if (i < argc) {
    cfg.moduleName = argv[i++];
  } else {
    std::cerr << "No module name given to b9run" << std::endl;
    return false;
  }

  // check for user defined arguments
  for (; i < argc; i++) {
    cfg.usrArgs.push_back(std::atoi(argv[i]));
  }

  return true;
}

static void run(const RunConfig& cfg) {
  b9::VirtualMachine vm{cfg.b9};
  b9::DlLoader loader{true};

  auto module = loader.loadModule(cfg.moduleName);
  vm.load(module);

  if (cfg.b9.jit) {
    vm.generateAllCode();
  }

  size_t functionIndex = module->findFunction(cfg.mainFunction);
  if (cfg.loopCount == 1) {
    b9::StackElement returnVal = vm.run(functionIndex, cfg.usrArgs);
    std::cout << std::endl
              << cfg.mainFunction << " returned: " << returnVal << std::endl;
  } else {
    b9::StackElement returnVal;
    std::cout << "\nRunning " << cfg.mainFunction << " " << cfg.loopCount
              << " times:" << std::endl;
    for (std::size_t i = 1; i <= cfg.loopCount; i++) {
      returnVal = vm.run(functionIndex, cfg.usrArgs);
      std::cout << "Return value of iteration " << i << ": " << returnVal
                << std::endl;
    }
  }
}

int main(int argc, char* argv[]) {
  RunConfig cfg;

  if (!parseArguments(cfg, argc, argv)) {
    std::cerr << usage << std::endl;
    exit(EXIT_FAILURE);
  }

  if (cfg.verbose) {
    std::cout << cfg << std::endl << std::endl;
  }

  try {
    run(cfg);
  } catch (const b9::DlException& e) {
    std::cerr << "Failed to load module: " << e.what() << std::endl;
    exit(EXIT_FAILURE);
  } catch (const b9::FunctionNotFoundException& e) {
    std::cerr << "Failed to find function: " << e.what() << std::endl;
    exit(EXIT_FAILURE);
  } catch (const b9::BadFunctionCallException& e) {
    std::cerr << "Failed to call function " << e.what() << std::endl;
    exit(EXIT_FAILURE);
  } catch (const b9::CompilationException& e) {
    std::cerr << "Failed to compile function: " << e.what() << std::endl;
    exit(EXIT_FAILURE);
  }

  exit(EXIT_SUCCESS);
}
<commit_msg>Simplify the result printing<commit_after>#include <b9/interpreter.hpp>
#include <b9/jit.hpp>
#include <b9/loader.hpp>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>

/// B9run's usage string. Printed when run with -help.
static const char* usage =
    "Usage: b9run [<option>...] [--] <module> [<main>]\n"
    "   Or: b9run -help\n"
    "Jit Options:\n"
    "  -jit:         Enable the jit\n"
    "  -directcall:  make direct jit to jit calls\n"
    "  -passparam:   Pass arguments in CPU registers\n"
    "  -lazyvmstate: Only update the VM state as needed\n"
    "Run Options:\n"
    "  -loop <n>:    Run the program <n> times\n"
    "  -inline <n>:  Enable inlining\n"
    "  -debug:       Enable debug code\n"
    "  -verbose:     Run with verbose printing\n"
    "  -help:        Print this help message";

/// The b9run program's global configuration.
struct RunConfig {
  b9::Config b9;
  const char* moduleName = "";
  const char* mainFunction = "b9main";
  std::size_t loopCount = 1;
  bool verbose = false;
  std::vector<b9::StackElement> usrArgs;
};

std::ostream& operator<<(std::ostream& out, const RunConfig& cfg) {
  out << "Module:       " << cfg.moduleName << std::endl
      << "Function:     " << cfg.mainFunction << std::endl
      << "Looping:      " << cfg.loopCount << std::endl;

  out << "Arguments:    [ ";
  for (const auto& arg : cfg.usrArgs) {
    out << arg << " ";
  }
  out << "]" << std::endl;

  out << cfg.b9;
  return out;
}

/// Parse CLI arguments and set up the config.
static bool parseArguments(RunConfig& cfg, const int argc, char* argv[]) {
  std::size_t i = 1;

  for (; i < argc; i++) {
    const char* arg = argv[i];

    if (strcmp(arg, "-help") == 0) {
      std::cout << usage << std::endl;
      exit(EXIT_SUCCESS);
    } else if (strcmp(arg, "-loop") == 0) {
      cfg.loopCount = atoi(argv[++i]);
    } else if (strcmp(arg, "-inline") == 0) {
      cfg.b9.maxInlineDepth = atoi(argv[++i]);
    } else if (strcmp(arg, "-verbose") == 0) {
      cfg.verbose = true;
      cfg.b9.verbose = true;
    } else if (strcmp(arg, "-debug") == 0) {
      cfg.b9.debug = true;
    } else if (strcmp(arg, "-function") == 0) {
      cfg.mainFunction = argv[++i];
    } else if (strcmp(arg, "-jit") == 0) {
      cfg.b9.jit = true;
    } else if (strcmp(arg, "-directcall") == 0) {
      cfg.b9.directCall = true;
    } else if (strcmp(arg, "-passparam") == 0) {
      cfg.b9.passParam = true;
    } else if (strcmp(arg, "-lazyvmstate") == 0) {
      cfg.b9.lazyVmState = true;
    } else if (strcmp(arg, "--") == 0) {
      i++;
      break;
    } else if (strcmp(arg, "-") == 0) {
      std::cerr << "Unrecognized option: " << arg << std::endl;
      return false;
    } else {
      break;
    }
  }

  // check for user defined module
  if (i < argc) {
    cfg.moduleName = argv[i++];
  } else {
    std::cerr << "No module name given to b9run" << std::endl;
    return false;
  }

  // check for user defined arguments
  for (; i < argc; i++) {
    cfg.usrArgs.push_back(std::atoi(argv[i]));
  }

  return true;
}

static void run(const RunConfig& cfg) {
  b9::VirtualMachine vm{cfg.b9};
  b9::DlLoader loader{true};

  auto module = loader.loadModule(cfg.moduleName);
  vm.load(module);

  if (cfg.b9.jit) {
    vm.generateAllCode();
  }

  size_t functionIndex = module->findFunction(cfg.mainFunction);
  for (std::size_t i = 0; i < cfg.loopCount; i += 1) {
    auto result = vm.run(functionIndex, cfg.usrArgs);
    std::cout << std::endl << "=> " << result << std::endl;
  }
}

int main(int argc, char* argv[]) {
  RunConfig cfg;

  if (!parseArguments(cfg, argc, argv)) {
    std::cerr << usage << std::endl;
    exit(EXIT_FAILURE);
  }

  if (cfg.verbose) {
    std::cout << cfg << std::endl << std::endl;
  }

  try {
    run(cfg);
  } catch (const b9::DlException& e) {
    std::cerr << "Failed to load module: " << e.what() << std::endl;
    exit(EXIT_FAILURE);
  } catch (const b9::FunctionNotFoundException& e) {
    std::cerr << "Failed to find function: " << e.what() << std::endl;
    exit(EXIT_FAILURE);
  } catch (const b9::BadFunctionCallException& e) {
    std::cerr << "Failed to call function " << e.what() << std::endl;
    exit(EXIT_FAILURE);
  } catch (const b9::CompilationException& e) {
    std::cerr << "Failed to compile function: " << e.what() << std::endl;
    exit(EXIT_FAILURE);
  }

  exit(EXIT_SUCCESS);
}
<|endoftext|>


<commit_before>//
// Created by qife on 16/1/11.
//

#include <string>
#include <locale>
#include <stack>
#include <queue>
#include <functional>

using NodeDeque = std::deque<Expr::ExprNode>;

static bool GetRePolishExpression(const char *str, NodeDeque &nodes)
{
    using namespace Expr;

    int paren = 0;
    std::queue<ExprNode> exprNodes;     // 表达式节点
    auto tmp = SkipWhiteSpace(str);
    tmp = TestSignDigit(tmp, exprNodes);

    while (true) {
        tmp = SkipWhiteSpace(tmp);
        if (*tmp == '(') {
            ExprNode node(ExprType::Operator);
            node.data.op = '(';
            exprNodes.push(std::move(node));

            tmp = SkipWhiteSpace(tmp, 1);
            tmp = TestSignDigit(tmp, exprNodes);
            ++paren;
        }

        if (!ReadNumOrProp(&tmp, exprNodes)) {
            return false;
        }

        tmp = SkipWhiteSpace(tmp);
        if (*tmp == ')') {
            if (--paren < 0) {
                return false;
            }

            ExprNode node(ExprType::Operator);
            node.data.op = ')';
            exprNodes.push(std::move(node));

            tmp = SkipWhiteSpace(tmp, 1);
        }

        if (*tmp) {
            if (!ReadOperator(&tmp, exprNodes)) {
                return false;
            }
        } else {
            break;
        }
    }
    if (paren != 0) {
        return false;
    }

    std::stack<ExprNode> opStack;   // 运算符暂存堆栈
    while (!exprNodes.empty()) {
        ExprNode &node = exprNodes.front();

        if (node.type == ExprType::Operator) {
            char op = node.data.op;
            if (opStack.empty() || op == '(') {
                opStack.push(std::move(node));
                exprNodes.pop();
                continue;
            }
            if (op == ')') {
                while (!opStack.empty()) {
                    ExprNode &tmpOpNode = opStack.top();
                    if (tmpOpNode.data.op != '(') {
                        nodes.push_back(std::move(tmpOpNode));
                        opStack.pop();
                    } else {
                        opStack.pop();
                        break;
                    }
                }

                exprNodes.pop();
                continue;
            }

            ExprNode &opNode = opStack.top();
            if (opNode.data.op == '(') {
                opStack.push(std::move(node));
                exprNodes.pop();
                continue;
            }
            if (OpLessOrEqual(op, opNode.data.op)) {
                nodes.push_back(std::move(opNode));
                opStack.pop();
                while (!opStack.empty()) {
                    ExprNode &tmpOpNode = opStack.top();
                    if (OpLessOrEqual(op, tmpOpNode.data.op)) {
                        nodes.push_back(std::move(tmpOpNode));
                        opStack.pop();
                    } else {
                        break;
                    }
                }

                opStack.push(std::move(node));
                exprNodes.pop();
            } else {
                opStack.push(std::move(node));
                exprNodes.pop();
            }
        } else {
            nodes.push_back(std::move(node));
            exprNodes.pop();
        }
    }
    while (!opStack.empty()) {
        nodes.push_back(std::move(opStack.top()));
        opStack.pop();
    }

    return true;
}

static bool ComputeRePolish(const NodeDeque &nodes, const std::function<bool(const std::string &, double *)> &get, double *result)
{
    std::stack<double> computeStack;

    for (const auto &item : nodes) {
        switch (item.type) {
            case Expr::Numeric: {
                computeStack.push(item.data.num);
                continue;
            }

            case Expr::Property: {
                double value = 0.0;
                if (get(*item.data.prop, &value)) {
                    computeStack.push(value);
                    continue;
                } else {
                    return false;
                }
            }

            case Expr::Operator: {
                if (computeStack.size() < 2) {
                    return false;
                }

                double num2 = computeStack.top();
                computeStack.pop();
                double num1 = computeStack.top();
                computeStack.pop();

                switch (item.data.op) {
                    case '+':
                        computeStack.push(num1 + num2);
                        continue;

                    case '-':
                        computeStack.push(num1 - num2);
                        continue;

                    case '*':
                        computeStack.push(num1 * num2);
                        continue;

                    case '/':
                        computeStack.push(num1 / num2);
                        continue;

                    case '%':
                        computeStack.push((int)num1 % (int)num2); // TODO: test int value
                        continue;

                    default:
                        return false;
                }
            }

            case Expr::Boolean:
                return false;
        }
    }

    if (computeStack.size() == 1) {
        *result = computeStack.top();
        return true;
    }

    return false;
}

static int GetOperatorPriority(char op)
{
    switch (op) {
        case '+':
        case '-':
            return 1;

        case '*':
        case '/':
        case '%':
            return 3;

        default:
            return 0;
    }
}

static bool OpLessOrEqual(char op1, char op2)
{
    int p1 = GetOperatorPriority(op1);
    int p2 = GetOperatorPriority(op2);

    return p1 <= p2;
}

static const char *TestSignDigit(const char *str, std::queue<Expr::ExprNode> &nodes)
{
    using namespace Expr;

    if (*str == '-') {
        ExprNode node(ExprType::Numeric);
        node.data.num = 0;
        nodes.push(std::move(node));

        node.type = ExprType::Operator;
        node.data.op = '-';
        nodes.push(std::move(node));

        return str + 1;
    }
    if (*str == '+') {
        return str + 1;
    }

    return str;
}

static bool ReadNumOrProp(const char **str, std::queue<Expr::ExprNode> &nodes)
{
    using namespace Expr;

    auto tmp = *str;
    tmp = SkipWhiteSpace(tmp);

    if (*tmp == '@') {
        if (*(tmp + 1) != '.') {
            return false;
        }
        tmp += 2;

        unsigned int len = 0;
        auto start = tmp;
        while (true) {
            switch (*start) {
                case '+':
                case '-':
                case '*':
                case '/':
                case '%':
                case ')':
                case ' ':
                    break;

                case '(':
                    return false;

                default:
                    ++len;
                    ++start;
                    continue;
            }

            if (len == 0) {
                return false;
            }

            ExprNode node(ExprType::Property);
            node.data.prop = new std::string(tmp, len);
            nodes.push(std::move(node));
            break;
        }

        *str = start;
        return true;
    } else {
        if (!std::isdigit(*tmp)) {
            return false;
        }

        char *end = nullptr;
        auto num = std::strtod(tmp, &end);
        if (nullptr == end) {
            return false;
        }

        ExprNode node(ExprType::Numeric);
        node.data.num = num;
        nodes.push(std::move(node));

        *str = end;
        return true;
    }
}

static bool ReadOperator(const char **str, std::queue<Expr::ExprNode> &nodes)
{
    using namespace Expr;

    auto tmp = *str;

    switch (*tmp) {
        case '+':
        case '-':
        case '*':
        case '/':
        case '%': {
            ExprNode node(ExprType::Operator);
            node.data.op = *tmp;
            nodes.push(std::move(node));

            *str = tmp + 1;
            return true;
        }

        default:
            return false;
    }
}
<commit_msg>remove unused file.<commit_after><|endoftext|>


<commit_before>/**
 * \file
 * \brief Definitions of low-level SPI master drivers for SPIv2 in STM32
 *
 * \author Copyright (C) 2016-2017 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "distortos/chip/spis.hpp"

#include "distortos/chip/ChipSpiMasterLowLevel.hpp"

namespace distortos
{

namespace chip
{

/*---------------------------------------------------------------------------------------------------------------------+
| SPI1 global objects and functions
+---------------------------------------------------------------------------------------------------------------------*/

#ifdef CONFIG_CHIP_STM32_SPIV2_SPI1_ENABLE

ChipSpiMasterLowLevel spi1 {ChipSpiMasterLowLevel::spi1Parameters};

/**
 * \brief SPI1 interrupt handler
 */

extern "C" void SPI1_IRQHandler()
{
	spi1.interruptHandler();
}

#endif	// def CONFIG_CHIP_STM32_SPIV2_SPI1_ENABLE

/*---------------------------------------------------------------------------------------------------------------------+
| SPI2 global objects and functions
+---------------------------------------------------------------------------------------------------------------------*/

#ifdef CONFIG_CHIP_STM32_SPIV2_SPI2_ENABLE

ChipSpiMasterLowLevel spi2 {ChipSpiMasterLowLevel::spi2Parameters};

/**
 * \brief SPI2 interrupt handler
 */

extern "C" void SPI2_IRQHandler()
{
	spi2.interruptHandler();
}

#endif	// def CONFIG_CHIP_STM32_SPIV2_SPI2_ENABLE

/*---------------------------------------------------------------------------------------------------------------------+
| SPI3 global objects and functions
+---------------------------------------------------------------------------------------------------------------------*/

#ifdef CONFIG_CHIP_STM32_SPIV2_SPI3_ENABLE

ChipSpiMasterLowLevel spi3 {ChipSpiMasterLowLevel::spi3Parameters};

/**
 * \brief SPI3 interrupt handler
 */

extern "C" void SPI3_IRQHandler()
{
	spi3.interruptHandler();
}

#endif	// def CONFIG_CHIP_STM32_SPIV2_SPI3_ENABLE

/*---------------------------------------------------------------------------------------------------------------------+
| SPI4 global objects and functions
+---------------------------------------------------------------------------------------------------------------------*/

#ifdef CONFIG_CHIP_STM32_SPIV2_SPI4_ENABLE

ChipSpiMasterLowLevel spi4 {ChipSpiMasterLowLevel::spi4Parameters};

/**
 * \brief SPI4 interrupt handler
 */

extern "C" void SPI4_IRQHandler()
{
	spi4.interruptHandler();
}

#endif	// def CONFIG_CHIP_STM32_SPIV2_SPI4_ENABLE

/*---------------------------------------------------------------------------------------------------------------------+
| SPI5 global objects and functions
+---------------------------------------------------------------------------------------------------------------------*/

#ifdef CONFIG_CHIP_STM32_SPIV2_SPI5_ENABLE

ChipSpiMasterLowLevel spi5 {ChipSpiMasterLowLevel::spi5Parameters};

/**
 * \brief SPI5 interrupt handler
 */

extern "C" void SPI5_IRQHandler()
{
	spi5.interruptHandler();
}

#endif	// def CONFIG_CHIP_STM32_SPIV2_SPI5_ENABLE

/*---------------------------------------------------------------------------------------------------------------------+
| SPI6 global objects and functions
+---------------------------------------------------------------------------------------------------------------------*/

#ifdef CONFIG_CHIP_STM32_SPIV2_SPI6_ENABLE

ChipSpiMasterLowLevel spi6 {ChipSpiMasterLowLevel::spi6Parameters};

/**
 * \brief SPI6 interrupt handler
 */

extern "C" void SPI6_IRQHandler()
{
	spi6.interruptHandler();
}

#endif	// def CONFIG_CHIP_STM32_SPIV2_SPI6_ENABLE

}	// namespace chip

}	// namespace distortos
<commit_msg>Rearrange things in STM32-SPIv2-spis.cpp<commit_after>/**
 * \file
 * \brief Definitions of low-level SPI master drivers for SPIv2 in STM32
 *
 * \author Copyright (C) 2016-2017 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "distortos/chip/spis.hpp"

#include "distortos/chip/ChipSpiMasterLowLevel.hpp"

namespace distortos
{

namespace chip
{

/*---------------------------------------------------------------------------------------------------------------------+
| global objects
+---------------------------------------------------------------------------------------------------------------------*/

#ifdef CONFIG_CHIP_STM32_SPIV2_SPI1_ENABLE

ChipSpiMasterLowLevel spi1 {ChipSpiMasterLowLevel::spi1Parameters};

#endif	// def CONFIG_CHIP_STM32_SPIV2_SPI1_ENABLE

#ifdef CONFIG_CHIP_STM32_SPIV2_SPI2_ENABLE

ChipSpiMasterLowLevel spi2 {ChipSpiMasterLowLevel::spi2Parameters};

#endif	// def CONFIG_CHIP_STM32_SPIV2_SPI2_ENABLE

#ifdef CONFIG_CHIP_STM32_SPIV2_SPI3_ENABLE

ChipSpiMasterLowLevel spi3 {ChipSpiMasterLowLevel::spi3Parameters};

#endif	// def CONFIG_CHIP_STM32_SPIV2_SPI3_ENABLE

#ifdef CONFIG_CHIP_STM32_SPIV2_SPI4_ENABLE

ChipSpiMasterLowLevel spi4 {ChipSpiMasterLowLevel::spi4Parameters};

#endif	// def CONFIG_CHIP_STM32_SPIV2_SPI4_ENABLE

#ifdef CONFIG_CHIP_STM32_SPIV2_SPI5_ENABLE

ChipSpiMasterLowLevel spi5 {ChipSpiMasterLowLevel::spi5Parameters};

#endif	// def CONFIG_CHIP_STM32_SPIV2_SPI5_ENABLE

#ifdef CONFIG_CHIP_STM32_SPIV2_SPI6_ENABLE

ChipSpiMasterLowLevel spi6 {ChipSpiMasterLowLevel::spi6Parameters};

#endif	// def CONFIG_CHIP_STM32_SPIV2_SPI6_ENABLE

/*---------------------------------------------------------------------------------------------------------------------+
| global functions
+---------------------------------------------------------------------------------------------------------------------*/

#ifdef CONFIG_CHIP_STM32_SPIV2_SPI1_ENABLE

/**
 * \brief SPI1 interrupt handler
 */

extern "C" void SPI1_IRQHandler()
{
	spi1.interruptHandler();
}

#endif	// def CONFIG_CHIP_STM32_SPIV2_SPI1_ENABLE

#ifdef CONFIG_CHIP_STM32_SPIV2_SPI2_ENABLE

/**
 * \brief SPI2 interrupt handler
 */

extern "C" void SPI2_IRQHandler()
{
	spi2.interruptHandler();
}

#endif	// def CONFIG_CHIP_STM32_SPIV2_SPI2_ENABLE

#ifdef CONFIG_CHIP_STM32_SPIV2_SPI3_ENABLE

/**
 * \brief SPI3 interrupt handler
 */

extern "C" void SPI3_IRQHandler()
{
	spi3.interruptHandler();
}

#endif	// def CONFIG_CHIP_STM32_SPIV2_SPI3_ENABLE

#ifdef CONFIG_CHIP_STM32_SPIV2_SPI4_ENABLE

/**
 * \brief SPI4 interrupt handler
 */

extern "C" void SPI4_IRQHandler()
{
	spi4.interruptHandler();
}

#endif	// def CONFIG_CHIP_STM32_SPIV2_SPI4_ENABLE

#ifdef CONFIG_CHIP_STM32_SPIV2_SPI5_ENABLE

/**
 * \brief SPI5 interrupt handler
 */

extern "C" void SPI5_IRQHandler()
{
	spi5.interruptHandler();
}

#endif	// def CONFIG_CHIP_STM32_SPIV2_SPI5_ENABLE

#ifdef CONFIG_CHIP_STM32_SPIV2_SPI6_ENABLE

/**
 * \brief SPI6 interrupt handler
 */

extern "C" void SPI6_IRQHandler()
{
	spi6.interruptHandler();
}

#endif	// def CONFIG_CHIP_STM32_SPIV2_SPI6_ENABLE

}	// namespace chip

}	// namespace distortos
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2010, Willow Garage, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Willow Garage, Inc. nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "triangle_list_marker.h"

#include "marker_selection_handler.h"
#include "rviz/default_plugin/marker_display.h"
#include "rviz/selection/selection_manager.h"
#include "rviz/uniform_string_stream.h"

#include "rviz/display_context.h"
#include "rviz/mesh_loader.h"
#include "marker_display.h"

#include <OGRE/OgreSceneNode.h>
#include <OGRE/OgreSceneManager.h>
#include <OGRE/OgreManualObject.h>
#include <OGRE/OgreMaterialManager.h>
#include <OGRE/OgreTextureManager.h>
#include <OGRE/OgreTechnique.h>

namespace rviz
{

TriangleListMarker::TriangleListMarker(MarkerDisplay* owner, DisplayContext* context, Ogre::SceneNode* parent_node)
: MarkerBase(owner, context, parent_node)
, manual_object_(0)
{
}

TriangleListMarker::~TriangleListMarker()
{
  context_->getSceneManager()->destroyManualObject(manual_object_);

  for (size_t i = 0; i < material_->getNumTechniques(); ++i)
  {
    Ogre::Technique* t = material_->getTechnique(i);
    // hack hack hack, really need to do a shader-based way of picking, rather than
    // creating a texture for each object
    if (t->getSchemeName() == "Pick")
    {
      Ogre::TextureManager::getSingleton().remove(t->getPass(0)->getTextureUnitState(0)->getTextureName());
    }
  }

  material_->unload();
  Ogre::MaterialManager::getSingleton().remove(material_->getName());
}

void TriangleListMarker::onNewMessage(const MarkerConstPtr& old_message, const MarkerConstPtr& new_message)
{
  ROS_ASSERT(new_message->type == visualization_msgs::Marker::TRIANGLE_LIST);

  size_t num_points = new_message->points.size();
  if( (num_points % 3) != 0 || num_points == 0 )
  {
    std::stringstream ss;
    if( num_points == 0 )
    {
      ss << "TriMesh marker [" << getStringID() << "] has no points.";
    }
    else
    {
      ss << "TriMesh marker [" << getStringID() << "] has a point count which is not divisible by 3 [" << num_points <<"]";
    }
    if ( owner_ )
    {
      owner_->setMarkerStatus(getID(), StatusProperty::Error, ss.str());
    }
    ROS_DEBUG("%s", ss.str().c_str());

    scene_node_->setVisible( false );
    return;
  }
  else
  {
    scene_node_->setVisible( true );
  }

  if (!manual_object_)
  {
    static uint32_t count = 0;
    UniformStringStream ss;
    ss << "Triangle List Marker" << count++;
    manual_object_ = context_->getSceneManager()->createManualObject(ss.str());
    scene_node_->attachObject(manual_object_);

    ss << "Material";
    material_name_ = ss.str();
    material_ = Ogre::MaterialManager::getSingleton().create( material_name_, ROS_PACKAGE_NAME );
    material_->setReceiveShadows(false);
    material_->getTechnique(0)->setLightingEnabled(true);
    material_->setCullingMode(Ogre::CULL_NONE);

    context_->getSelectionManager()->removeObject(coll_);

    SelectionManager* sel_man = context_->getSelectionManager();
    coll_ = sel_man->createHandle();
    sel_man->addPickTechnique(coll_, material_);
    sel_man->addObject( coll_, SelectionHandlerPtr(new MarkerSelectionHandler(this, MarkerID(new_message->ns, new_message->id))) );
  }

  Ogre::Vector3 pos, scale;
  Ogre::Quaternion orient;
  transform(new_message, pos, orient, scale);

  if ( owner_ &&  (new_message->scale.x * new_message->scale.y * new_message->scale.z == 0.0f) )
  {
    owner_->setMarkerStatus(getID(), StatusProperty::Warn, "Scale of 0 in one of x/y/z");
  }

  setPosition(pos);
  setOrientation(orient);
  scene_node_->setScale(scale);

  // If we have the same number of tris as previously, just update the object
  if (old_message && num_points == old_message->points.size())
  {
    manual_object_->beginUpdate(0);
  }
  else // Otherwise clear it and begin anew
  {
    manual_object_->clear();
    manual_object_->estimateVertexCount(num_points);
    manual_object_->begin(material_name_, Ogre::RenderOperation::OT_TRIANGLE_LIST);
  }

  bool has_vertex_colors = new_message->colors.size() == num_points;
  bool any_vertex_has_alpha = false;

  if (has_vertex_colors)
  {
    for (size_t i = 0; i < num_points; ++i)
    {
      manual_object_->position(new_message->points[i].x, new_message->points[i].y, new_message->points[i].z);
      any_vertex_has_alpha = any_vertex_has_alpha || (new_message->colors[i].a < 0.9998);
      manual_object_->colour(new_message->colors[i].r, new_message->colors[i].g, new_message->colors[i].b, new_message->color.a * new_message->colors[i].a);
    }
  }
  else
  {
    for (size_t i = 0; i < num_points; ++i)
    {
      manual_object_->position(new_message->points[i].x, new_message->points[i].y, new_message->points[i].z);
    }
  }

  manual_object_->end();

  if (has_vertex_colors)
  {
    material_->getTechnique(0)->setLightingEnabled(false);
  }
  else
  {
    material_->getTechnique(0)->setLightingEnabled(true);
    float r,g,b,a;
    r = new_message->color.r;
    g = new_message->color.g;
    b = new_message->color.b;
    a = new_message->color.a;
    material_->getTechnique(0)->setAmbient( r,g,b );
    material_->getTechnique(0)->setDiffuse( 0,0,0,a );
  }

  if( (!has_vertex_colors && new_message->color.a < 0.9998) || (has_vertex_colors && any_vertex_has_alpha))
  {
    material_->getTechnique(0)->setSceneBlending( Ogre::SBT_TRANSPARENT_ALPHA );
    material_->getTechnique(0)->setDepthWriteEnabled( false );
  }
  else
  {
    material_->getTechnique(0)->setSceneBlending( Ogre::SBT_REPLACE );
    material_->getTechnique(0)->setDepthWriteEnabled( true );
  }
}

S_MaterialPtr TriangleListMarker::getMaterials()
{
  S_MaterialPtr materials;
  materials.insert( material_ );
  return materials;
}

}

<commit_msg>discard marker if transform() fails. Otherwise uninitialized Ogre vectors are passed in and segfaults happen<commit_after>/*
 * Copyright (c) 2010, Willow Garage, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Willow Garage, Inc. nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "triangle_list_marker.h"

#include "marker_selection_handler.h"
#include "rviz/default_plugin/marker_display.h"
#include "rviz/selection/selection_manager.h"
#include "rviz/uniform_string_stream.h"

#include "rviz/display_context.h"
#include "rviz/mesh_loader.h"
#include "marker_display.h"

#include <OGRE/OgreSceneNode.h>
#include <OGRE/OgreSceneManager.h>
#include <OGRE/OgreManualObject.h>
#include <OGRE/OgreMaterialManager.h>
#include <OGRE/OgreTextureManager.h>
#include <OGRE/OgreTechnique.h>

namespace rviz
{

TriangleListMarker::TriangleListMarker(MarkerDisplay* owner, DisplayContext* context, Ogre::SceneNode* parent_node)
: MarkerBase(owner, context, parent_node)
, manual_object_(0)
{
}

TriangleListMarker::~TriangleListMarker()
{
  context_->getSceneManager()->destroyManualObject(manual_object_);

  for (size_t i = 0; i < material_->getNumTechniques(); ++i)
  {
    Ogre::Technique* t = material_->getTechnique(i);
    // hack hack hack, really need to do a shader-based way of picking, rather than
    // creating a texture for each object
    if (t->getSchemeName() == "Pick")
    {
      Ogre::TextureManager::getSingleton().remove(t->getPass(0)->getTextureUnitState(0)->getTextureName());
    }
  }

  material_->unload();
  Ogre::MaterialManager::getSingleton().remove(material_->getName());
}

void TriangleListMarker::onNewMessage(const MarkerConstPtr& old_message, const MarkerConstPtr& new_message)
{
  ROS_ASSERT(new_message->type == visualization_msgs::Marker::TRIANGLE_LIST);

  size_t num_points = new_message->points.size();
  if( (num_points % 3) != 0 || num_points == 0 )
  {
    std::stringstream ss;
    if( num_points == 0 )
    {
      ss << "TriMesh marker [" << getStringID() << "] has no points.";
    }
    else
    {
      ss << "TriMesh marker [" << getStringID() << "] has a point count which is not divisible by 3 [" << num_points <<"]";
    }
    if ( owner_ )
    {
      owner_->setMarkerStatus(getID(), StatusProperty::Error, ss.str());
    }
    ROS_DEBUG("%s", ss.str().c_str());

    scene_node_->setVisible( false );
    return;
  }
  else
  {
    scene_node_->setVisible( true );
  }

  if (!manual_object_)
  {
    static uint32_t count = 0;
    UniformStringStream ss;
    ss << "Triangle List Marker" << count++;
    manual_object_ = context_->getSceneManager()->createManualObject(ss.str());
    scene_node_->attachObject(manual_object_);

    ss << "Material";
    material_name_ = ss.str();
    material_ = Ogre::MaterialManager::getSingleton().create( material_name_, ROS_PACKAGE_NAME );
    material_->setReceiveShadows(false);
    material_->getTechnique(0)->setLightingEnabled(true);
    material_->setCullingMode(Ogre::CULL_NONE);

    context_->getSelectionManager()->removeObject(coll_);

    SelectionManager* sel_man = context_->getSelectionManager();
    coll_ = sel_man->createHandle();
    sel_man->addPickTechnique(coll_, material_);
    sel_man->addObject( coll_, SelectionHandlerPtr(new MarkerSelectionHandler(this, MarkerID(new_message->ns, new_message->id))) );
  }

  Ogre::Vector3 pos, scale;
  Ogre::Quaternion orient;
  if (!transform(new_message, pos, orient, scale))
  {
    ROS_DEBUG("Unable to transform marker message");
    scene_node_->setVisible( false );
    return;
  }

  if ( owner_ &&  (new_message->scale.x * new_message->scale.y * new_message->scale.z == 0.0f) )
  {
    owner_->setMarkerStatus(getID(), StatusProperty::Warn, "Scale of 0 in one of x/y/z");
  }

  setPosition(pos);
  setOrientation(orient);
  scene_node_->setScale(scale);

  // If we have the same number of tris as previously, just update the object
  if (old_message && num_points == old_message->points.size())
  {
    manual_object_->beginUpdate(0);
  }
  else // Otherwise clear it and begin anew
  {
    manual_object_->clear();
    manual_object_->estimateVertexCount(num_points);
    manual_object_->begin(material_name_, Ogre::RenderOperation::OT_TRIANGLE_LIST);
  }

  bool has_vertex_colors = new_message->colors.size() == num_points;
  bool any_vertex_has_alpha = false;

  if (has_vertex_colors)
  {
    for (size_t i = 0; i < num_points; ++i)
    {
      manual_object_->position(new_message->points[i].x, new_message->points[i].y, new_message->points[i].z);
      any_vertex_has_alpha = any_vertex_has_alpha || (new_message->colors[i].a < 0.9998);
      manual_object_->colour(new_message->colors[i].r, new_message->colors[i].g, new_message->colors[i].b, new_message->color.a * new_message->colors[i].a);
    }
  }
  else
  {
    for (size_t i = 0; i < num_points; ++i)
    {
      manual_object_->position(new_message->points[i].x, new_message->points[i].y, new_message->points[i].z);
    }
  }

  manual_object_->end();

  if (has_vertex_colors)
  {
    material_->getTechnique(0)->setLightingEnabled(false);
  }
  else
  {
    material_->getTechnique(0)->setLightingEnabled(true);
    float r,g,b,a;
    r = new_message->color.r;
    g = new_message->color.g;
    b = new_message->color.b;
    a = new_message->color.a;
    material_->getTechnique(0)->setAmbient( r,g,b );
    material_->getTechnique(0)->setDiffuse( 0,0,0,a );
  }

  if( (!has_vertex_colors && new_message->color.a < 0.9998) || (has_vertex_colors && any_vertex_has_alpha))
  {
    material_->getTechnique(0)->setSceneBlending( Ogre::SBT_TRANSPARENT_ALPHA );
    material_->getTechnique(0)->setDepthWriteEnabled( false );
  }
  else
  {
    material_->getTechnique(0)->setSceneBlending( Ogre::SBT_REPLACE );
    material_->getTechnique(0)->setDepthWriteEnabled( true );
  }
}

S_MaterialPtr TriangleListMarker::getMaterials()
{
  S_MaterialPtr materials;
  materials.insert( material_ );
  return materials;
}

}

<|endoftext|>