<commit_before>//**************************************************************************************************
//
//     OSSIM Open Source Geospatial Data Processing Library
//     See top level LICENSE.txt file for license information
//
//**************************************************************************************************

#include <ossim/util/ossimSubImageTool.h>
#include <ossim/base/ossimConstants.h>
#include <ossim/base/ossimApplicationUsage.h>
#include <ossim/base/ossimNotify.h>
#include <ossim/base/ossimException.h>
#include <ossim/base/ossimString.h>
#include <ossim/base/ossimKeywordNames.h>
#include <ossim/imaging/ossimImageHandlerRegistry.h>
#include <ossim/imaging/ossimImageGeometry.h>
#include <ossim/projection/ossimRpcSolver.h>
#include <ossim/base/ossimXmlDocument.h>
#include <iostream>

using namespace std;

const char* ossimSubImageTool::DESCRIPTION  = "Tool for extracting a sub-image from a full image."
      " No reprojection is done. Presently, the subimage geometry is represented by an RPC "
      "replacement model until generic models can support subimage chipping.";
const char* BBOX_KW = "bbox";

ossimSubImageTool::ossimSubImageTool()
:  m_geomFormat (OGEOM)
{
}

ossimSubImageTool::~ossimSubImageTool()
{
}

void ossimSubImageTool::setUsage(ossimArgumentParser& ap)
{
   // Add options.
   ossimApplicationUsage* au = ap.getApplicationUsage();
   ossimString usageString = ap.getApplicationName();
   usageString += " subimage [options] <input-image> <output-image>";
   au->setCommandLineUsage(usageString);

   // Set the command line options:
   au->setDescription(DESCRIPTION);

   // Base class has its own. Skip the ossimChipProcTool usage as that adds a lot of view-space
   // specific stuff not used in this tool:
   ossimTool::setUsage(ap);

   au->addCommandLineOption(
         "--bbox <ulx> <uly> <lrx> <lry>",
         "Specify upper-left and lower-right bounds the image rect (in pixels).");
   au->addCommandLineOption(
         "-e | --entry <N> ",
         "For multi image entries which entry do you wish to extract. For list "
         "of entries use: \"ossim-info -i <your_image>\" ");
   au->addCommandLineOption(
         "--geom <format>", "Specifies format of the subimage RPC geometry file."
         " Possible values are: \"OGEOM\" (OSSIM geometry, default), \"DG\" (DigitalGlobe WV/QB "
         ".RPB format), \"JSON\" (MSP-style JSON), or \"XML\". Case insensitive.");
}

bool ossimSubImageTool::initialize(ossimArgumentParser& ap)
{
   if (!ossimTool::initialize(ap))
      return false;
   if (m_helpRequested)
      return true;

   string tempString1;
   ossimArgumentParser::ossimParameter stringParam1(tempString1);
   string tempString2;
   ossimArgumentParser::ossimParameter stringParam2(tempString2);
   string tempString3;
   ossimArgumentParser::ossimParameter stringParam3(tempString3);
   string tempString4;
   ossimArgumentParser::ossimParameter stringParam4(tempString4);
   double tempDouble1;
   ossimArgumentParser::ossimParameter doubleParam1(tempDouble1);
   double tempDouble2;
   ossimArgumentParser::ossimParameter doubleParam2(tempDouble2);
   vector<ossimString> paramList;

   ossim_uint32 readerPropIdx = 0;
   ossim_uint32 writerPropIdx = 0;
   ostringstream keys;

   if ( ap.read("--bbox", stringParam1, stringParam2, stringParam3, stringParam4))
   {
      ostringstream ostr;
      ostr<<tempString1<<" "<<tempString2<<" "<<tempString3<<" "<<tempString4<<ends;
      m_kwl.addPair( string(BBOX_KW), ostr.str() );
   }
   if ( ap.read("-e", stringParam1) || ap.read("--entry", stringParam1) )
      m_kwl.addPair( string(ossimKeywordNames::ENTRY_KW), tempString1 );

   if ( ap.read("--geom", stringParam1))
   {
      ossimString formatStr (tempString1);
      formatStr.upcase();
      if (formatStr == "OGEOM")
         m_geomFormat = OGEOM;
      else if (formatStr == "DG")
         m_geomFormat = DG;
      else if (formatStr == "JSON")
         m_geomFormat = JSON;
      else if (formatStr == "XML")
         m_geomFormat = XML;
      else
      {
         ostringstream errMsg;
         errMsg << " ERROR: ossimSubImageTool ["<<__LINE__<<"] Unknown geometry format <"
               <<formatStr<<"> specified. Aborting." << endl;
         throw ossimException( errMsg.str() );
      }
   }
   processRemainingArgs(ap);

   return true;
}

void ossimSubImageTool::initialize(const ossimKeywordlist& kwl)
{
   m_productFilename = m_kwl.find(ossimKeywordNames::OUTPUT_FILE_KW);

   // Init chain with handler:
   ostringstream key;
   key<<ossimKeywordNames::IMAGE_FILE_KW<<"0";
   ossimFilename fname = m_kwl.findKey(key.str());
   ossimRefPtr<ossimImageHandler> handler =
         ossimImageHandlerRegistry::instance()->open(fname, true, false);
   if (!handler)
   {
      ostringstream errMsg;
      errMsg<<"ERROR: ossimSubImageTool ["<<__LINE__<<"] Could not open <"<<fname<<">"<<ends;
      throw ossimException(errMsg.str());
   }

   // Look for the entry keyand set it:
   ossim_uint32 entryIndex = 0;
   ossimString os = m_kwl.find(ossimKeywordNames::ENTRY_KW);
   if (os)
      entryIndex = os.toUInt32();
   if (!handler->setCurrentEntry( entryIndex ))
   {
      ostringstream errMsg;
      errMsg << " ERROR: ossimSubImageTool ["<<__LINE__<<"] Entry " << entryIndex << " out of range!" << endl;
      throw ossimException( errMsg.str() );
   }
   m_procChain->add(handler.get());

   // And finally the bounding rect:
   ossimString lookup = m_kwl.find(BBOX_KW);
   lookup.trim();
   vector<ossimString> substrings = lookup.split(", ", true);
   if (substrings.size() != 4)
   {
      ostringstream errMsg;
      errMsg << "ossimSubImageTool ["<<__LINE__<<"] Incorrect number of values specified for bbox!";
      throw( ossimException(errMsg.str()) );
   }

   int ulx = substrings[0].toInt32();
   int uly = substrings[1].toInt32();
   int lrx = substrings[2].toInt32();
   int lry = substrings[3].toInt32();

   // Check for swap:
   if ( ulx > lrx )
   {
      int tmpF = ulx;
      ulx = lrx;
      lrx = tmpF;
   }
   if ( uly > lry )
   {
      int tmpF = uly;
      uly = lry;
      lry = tmpF;
   }

   // Use of view rect here is same as image space since there is no renderer:
   m_aoiViewRect.set_ul(ossimIpt(ulx, uly));
   m_aoiViewRect.set_lr(ossimIpt(lrx, lry));
   m_needCutRect = true;

   finalizeChain();
}

bool ossimSubImageTool::execute()
{
   // Compute RPC representation of subimage:
   ossimRefPtr<ossimImageGeometry> inputGeom = m_procChain->getImageGeometry();
   if (!inputGeom || !inputGeom->getProjection())
   {
      ostringstream errMsg;
      errMsg << " ERROR: ossimSubImageTool ["<<__LINE__<<"] Null projection returned for input "
            "image!" << endl;
      throw ossimException( errMsg.str() );
   }

   ossimRefPtr<ossimProjection> inputProj = inputGeom->getProjection();
   ossimRefPtr<ossimRpcModel> rpc;
   ossimRefPtr<ossimRpcSolver> solver = new ossimRpcSolver(false);
   bool converged = false;

   // If the input projection itself is an RPC, just copy it. No solving required:
   ossimRpcModel* inputRpc = dynamic_cast<ossimRpcModel*>(inputGeom->getProjection());
   if (inputRpc)
      rpc = inputRpc;
   else
   {
      converged = solver->solve(m_aoiViewRect, inputGeom.get());
      rpc = solver->getRpcModel();
   }

   // The RPC needs to be shifted in image space so that it will work in the subimage coordinates:
   rpc->setImageOffset(m_aoiViewRect.ul());
   m_geom = new ossimImageGeometry(nullptr, rpc.get());
   m_geom->setImageSize(m_aoiViewRect.size());
   ossimKeywordlist kwl;
   m_geom->saveState(kwl);

   bool success = ossimChipProcTool::execute();
   if (!success)
      return false;

   // Need to save the subimage RPC data:
   bool write_ok = false;
   ossimFilename geomFile (m_productFilename);
   if (m_geomFormat == OGEOM) // Default case if none specified
   {
      geomFile.setExtension("geom");
      write_ok = kwl.write(geomFile);
   }
   else if (m_geomFormat == JSON)
   {
#if OSSIM_HAS_JSONCPP
      geomFile.setExtension("json");
      ofstream jsonStream (geomFile.string());
      if (!jsonStream.fail())
      {
         // Note that only the model/projection is saved here, not the full ossimImageGeometry that
         // contains the subimage shift transform. So need to cheat and add the shift to the RPC
         // line and sample offsets:
         write_ok = rpc->toJSON(jsonStream);
         jsonStream.close();
      }
#else
      ostringstream errMsg;
      errMsg << " ERROR: ossimSubImageTool ["<<__LINE__<<"] JSON geometry output requested but JSON is not "
            "available in this build! <" << endl;
      throw ossimException( errMsg.str() );
#endif
   }
   else if (m_geomFormat == DG)
   {
      geomFile.setExtension("RPB");
      ofstream rpbStream (geomFile.string());
      if (!rpbStream.fail())
      {
         write_ok = rpc->toRPB(rpbStream);
         rpbStream.close();
      }
   }
   else if (m_geomFormat == XML)
   {
      geomFile.setExtension("xml");
      ossimXmlDocument xmlDocument;
      xmlDocument.fromKwl(kwl);
      write_ok = xmlDocument.write(geomFile);
   }

   if (write_ok)
      ossimNotify(ossimNotifyLevel_INFO) << "Wrote geometry file to <"<<geomFile<<">.\n" << endl;
   else
   {
      ossimNotify(ossimNotifyLevel_FATAL) << "Error encountered writing output RPC geometry file."
            << std::endl;
      return false;
   }

   return true;
}

<commit_msg>Shortenned description<commit_after>//**************************************************************************************************
//
//     OSSIM Open Source Geospatial Data Processing Library
//     See top level LICENSE.txt file for license information
//
//**************************************************************************************************

#include <ossim/util/ossimSubImageTool.h>
#include <ossim/base/ossimConstants.h>
#include <ossim/base/ossimApplicationUsage.h>
#include <ossim/base/ossimNotify.h>
#include <ossim/base/ossimException.h>
#include <ossim/base/ossimString.h>
#include <ossim/base/ossimKeywordNames.h>
#include <ossim/imaging/ossimImageHandlerRegistry.h>
#include <ossim/imaging/ossimImageGeometry.h>
#include <ossim/projection/ossimRpcSolver.h>
#include <ossim/base/ossimXmlDocument.h>
#include <iostream>

using namespace std;

const char* ossimSubImageTool::DESCRIPTION  = "Tool for extracting a sub-image from a full image.";
const char* BBOX_KW = "bbox";

ossimSubImageTool::ossimSubImageTool()
:  m_geomFormat (OGEOM)
{
}

ossimSubImageTool::~ossimSubImageTool()
{
}

void ossimSubImageTool::setUsage(ossimArgumentParser& ap)
{
   // Add options.
   ossimApplicationUsage* au = ap.getApplicationUsage();
   ossimString usageString = ap.getApplicationName();
   usageString += " subimage [options] <input-image> <output-image>";
   au->setCommandLineUsage(usageString);

   ostringstream descr;
   descr << DESCRIPTION << "\n\n"
         <<  " No reprojection is done. Presently, the subimage geometry is represented by an RPC "
         << "replacement model until generic models can support subimage chipping.";
   au->setDescription(descr.str());

   // Set the command line options:
   // Base class has its own. Skip the ossimChipProcTool usage as that adds a lot of view-space
   // specific stuff not used in this tool:
   ossimTool::setUsage(ap);

   au->addCommandLineOption(
         "--bbox <ulx> <uly> <lrx> <lry>",
         "Specify upper-left and lower-right bounds the image rect (in pixels).");
   au->addCommandLineOption(
         "-e | --entry <N> ",
         "For multi image entries which entry do you wish to extract. For list "
         "of entries use: \"ossim-info -i <your_image>\" ");
   au->addCommandLineOption(
         "--geom <format>", "Specifies format of the subimage RPC geometry file."
         " Possible values are: \"OGEOM\" (OSSIM geometry, default), \"DG\" (DigitalGlobe WV/QB "
         ".RPB format), \"JSON\" (MSP-style JSON), or \"XML\". Case insensitive.");
}

bool ossimSubImageTool::initialize(ossimArgumentParser& ap)
{
   if (!ossimTool::initialize(ap))
      return false;
   if (m_helpRequested)
      return true;

   string tempString1;
   ossimArgumentParser::ossimParameter stringParam1(tempString1);
   string tempString2;
   ossimArgumentParser::ossimParameter stringParam2(tempString2);
   string tempString3;
   ossimArgumentParser::ossimParameter stringParam3(tempString3);
   string tempString4;
   ossimArgumentParser::ossimParameter stringParam4(tempString4);
   double tempDouble1;
   ossimArgumentParser::ossimParameter doubleParam1(tempDouble1);
   double tempDouble2;
   ossimArgumentParser::ossimParameter doubleParam2(tempDouble2);
   vector<ossimString> paramList;

   ossim_uint32 readerPropIdx = 0;
   ossim_uint32 writerPropIdx = 0;
   ostringstream keys;

   if ( ap.read("--bbox", stringParam1, stringParam2, stringParam3, stringParam4))
   {
      ostringstream ostr;
      ostr<<tempString1<<" "<<tempString2<<" "<<tempString3<<" "<<tempString4<<ends;
      m_kwl.addPair( string(BBOX_KW), ostr.str() );
   }
   if ( ap.read("-e", stringParam1) || ap.read("--entry", stringParam1) )
      m_kwl.addPair( string(ossimKeywordNames::ENTRY_KW), tempString1 );

   if ( ap.read("--geom", stringParam1))
   {
      ossimString formatStr (tempString1);
      formatStr.upcase();
      if (formatStr == "OGEOM")
         m_geomFormat = OGEOM;
      else if (formatStr == "DG")
         m_geomFormat = DG;
      else if (formatStr == "JSON")
         m_geomFormat = JSON;
      else if (formatStr == "XML")
         m_geomFormat = XML;
      else
      {
         ostringstream errMsg;
         errMsg << " ERROR: ossimSubImageTool ["<<__LINE__<<"] Unknown geometry format <"
               <<formatStr<<"> specified. Aborting." << endl;
         throw ossimException( errMsg.str() );
      }
   }
   processRemainingArgs(ap);

   return true;
}

void ossimSubImageTool::initialize(const ossimKeywordlist& kwl)
{
   m_productFilename = m_kwl.find(ossimKeywordNames::OUTPUT_FILE_KW);

   // Init chain with handler:
   ostringstream key;
   key<<ossimKeywordNames::IMAGE_FILE_KW<<"0";
   ossimFilename fname = m_kwl.findKey(key.str());
   ossimRefPtr<ossimImageHandler> handler =
         ossimImageHandlerRegistry::instance()->open(fname, true, false);
   if (!handler)
   {
      ostringstream errMsg;
      errMsg<<"ERROR: ossimSubImageTool ["<<__LINE__<<"] Could not open <"<<fname<<">"<<ends;
      throw ossimException(errMsg.str());
   }

   // Look for the entry keyand set it:
   ossim_uint32 entryIndex = 0;
   ossimString os = m_kwl.find(ossimKeywordNames::ENTRY_KW);
   if (os)
      entryIndex = os.toUInt32();
   if (!handler->setCurrentEntry( entryIndex ))
   {
      ostringstream errMsg;
      errMsg << " ERROR: ossimSubImageTool ["<<__LINE__<<"] Entry " << entryIndex << " out of range!" << endl;
      throw ossimException( errMsg.str() );
   }
   m_procChain->add(handler.get());

   // And finally the bounding rect:
   ossimString lookup = m_kwl.find(BBOX_KW);
   lookup.trim();
   vector<ossimString> substrings = lookup.split(", ", true);
   if (substrings.size() != 4)
   {
      ostringstream errMsg;
      errMsg << "ossimSubImageTool ["<<__LINE__<<"] Incorrect number of values specified for bbox!";
      throw( ossimException(errMsg.str()) );
   }

   int ulx = substrings[0].toInt32();
   int uly = substrings[1].toInt32();
   int lrx = substrings[2].toInt32();
   int lry = substrings[3].toInt32();

   // Check for swap:
   if ( ulx > lrx )
   {
      int tmpF = ulx;
      ulx = lrx;
      lrx = tmpF;
   }
   if ( uly > lry )
   {
      int tmpF = uly;
      uly = lry;
      lry = tmpF;
   }

   // Use of view rect here is same as image space since there is no renderer:
   m_aoiViewRect.set_ul(ossimIpt(ulx, uly));
   m_aoiViewRect.set_lr(ossimIpt(lrx, lry));
   m_needCutRect = true;

   finalizeChain();
}

bool ossimSubImageTool::execute()
{
   // Compute RPC representation of subimage:
   ossimRefPtr<ossimImageGeometry> inputGeom = m_procChain->getImageGeometry();
   if (!inputGeom || !inputGeom->getProjection())
   {
      ostringstream errMsg;
      errMsg << " ERROR: ossimSubImageTool ["<<__LINE__<<"] Null projection returned for input "
            "image!" << endl;
      throw ossimException( errMsg.str() );
   }

   ossimRefPtr<ossimProjection> inputProj = inputGeom->getProjection();
   ossimRefPtr<ossimRpcModel> rpc;
   ossimRefPtr<ossimRpcSolver> solver = new ossimRpcSolver(false);
   bool converged = false;

   // If the input projection itself is an RPC, just copy it. No solving required:
   ossimRpcModel* inputRpc = dynamic_cast<ossimRpcModel*>(inputGeom->getProjection());
   if (inputRpc)
      rpc = inputRpc;
   else
   {
      converged = solver->solve(m_aoiViewRect, inputGeom.get());
      rpc = solver->getRpcModel();
   }

   // The RPC needs to be shifted in image space so that it will work in the subimage coordinates:
   rpc->setImageOffset(m_aoiViewRect.ul());
   m_geom = new ossimImageGeometry(nullptr, rpc.get());
   m_geom->setImageSize(m_aoiViewRect.size());
   ossimKeywordlist kwl;
   m_geom->saveState(kwl);

   bool success = ossimChipProcTool::execute();
   if (!success)
      return false;

   // Need to save the subimage RPC data:
   bool write_ok = false;
   ossimFilename geomFile (m_productFilename);
   if (m_geomFormat == OGEOM) // Default case if none specified
   {
      geomFile.setExtension("geom");
      write_ok = kwl.write(geomFile);
   }
   else if (m_geomFormat == JSON)
   {
#if OSSIM_HAS_JSONCPP
      geomFile.setExtension("json");
      ofstream jsonStream (geomFile.string());
      if (!jsonStream.fail())
      {
         // Note that only the model/projection is saved here, not the full ossimImageGeometry that
         // contains the subimage shift transform. So need to cheat and add the shift to the RPC
         // line and sample offsets:
         write_ok = rpc->toJSON(jsonStream);
         jsonStream.close();
      }
#else
      ostringstream errMsg;
      errMsg << " ERROR: ossimSubImageTool ["<<__LINE__<<"] JSON geometry output requested but JSON is not "
            "available in this build! <" << endl;
      throw ossimException( errMsg.str() );
#endif
   }
   else if (m_geomFormat == DG)
   {
      geomFile.setExtension("RPB");
      ofstream rpbStream (geomFile.string());
      if (!rpbStream.fail())
      {
         write_ok = rpc->toRPB(rpbStream);
         rpbStream.close();
      }
   }
   else if (m_geomFormat == XML)
   {
      geomFile.setExtension("xml");
      ossimXmlDocument xmlDocument;
      xmlDocument.fromKwl(kwl);
      write_ok = xmlDocument.write(geomFile);
   }

   if (write_ok)
      ossimNotify(ossimNotifyLevel_INFO) << "Wrote geometry file to <"<<geomFile<<">.\n" << endl;
   else
   {
      ossimNotify(ossimNotifyLevel_FATAL) << "Error encountered writing output RPC geometry file."
            << std::endl;
      return false;
   }

   return true;
}

<|endoftext|>


<commit_before>#include "gunsystem.hpp"
#include "../component/transformcomponent.hpp"
#include "../component/guncomponent.hpp"
#include "../component/lifecomponent.hpp"
#include "../component/physicscomponent.hpp"
#include "../component/modelcomponent.hpp"
#include "../component/rigidbodycomponent.hpp"

#include "../system/bulletphysicssystem.hpp"

#include "../entity.hpp"
#include "../src/gl/mesh.hpp"
#include "../src/engine.hpp"

GunSystem::~GunSystem() {}

void GunSystem::update(World& world, float delta) {
	std::vector<Entity*> toAdd;
	for (std::unique_ptr<Entity>& entity : world.getEntities()) {
		auto currGunComp = entity->getComponent<GunComponent>();
		if (!currGunComp)
			continue;

		if (currGunComp->shoot) {
			toAdd.push_back(entity.get());
			currGunComp->shoot = false;
			currGunComp->cooldown = currGunComp->cooldownLength;
		}
		if(currGunComp->cooldown > 0)
			currGunComp->cooldown -= 1 * delta;
	}
	for (Entity* entity : toAdd) {
		fireProjectile(entity, world.addEntity(sole::uuid4(), "Projectile"));
	}
}

void GunSystem::fireProjectile(Entity* me, Entity* projectile) {
	auto currTransform = me->getComponent<TransformComponent>();

	auto projTransComp = projectile->addComponent<TransformComponent>();
	projTransComp->setPosition(currTransform->getPosition());
	projTransComp->setRotation(currTransform->getRotation());
	projTransComp->setScale(glm::vec3(0.2f));

	auto projPhysComp = projectile->addComponent<PhysicsComponent>();
	projPhysComp->acceleration = glm::vec3(0,0,1);
	projPhysComp->velocity = projPhysComp->acceleration * glm::vec3(2);

	auto projLifeComp = projectile->addComponent<LifeComponent>();
	projLifeComp->currHP = projLifeComp->maxHP = 2;

	auto modelComp = projectile->addComponent<ModelComponent>();
	modelComp->meshData = Engine::getInstance().getMeshLoader()->getMesh("assets/objects/player.fbx");
	modelComp->meshData->mesh
		->addBuffer("m",
			[](GLuint id) {
		glBindBuffer(GL_ARRAY_BUFFER, id);
		glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4), NULL, GL_DYNAMIC_DRAW);

		for (int i = 0; i < 4; i++) {
			glEnableVertexAttribArray(ShaderAttributeID::m + i);
			glVertexAttribPointer(ShaderAttributeID::m + i, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)(sizeof(glm::vec4) * i));
			glVertexAttribDivisor(ShaderAttributeID::m + i, 1);
		}

		glBindBuffer(GL_ARRAY_BUFFER, 0);
	})
		.finalize();

	auto rigidbody = projectile->addComponent<RigidBodyComponent>();
	rigidbody->setHitboxHalfSize(projTransComp->getScale());
	rigidbody->setMass(1);
	Engine::getInstance().getSystem<BulletPhyisicsSystem>()->addRigidBody(rigidbody);
}

//bool GunSystem::fireRay(std::unique_ptr<Entity>& target, HitboxComponent::HitboxType inType) {
//	bool hit = false;
//	switch (inType)
//	{
//	case HitboxComponent::SPHERE: {
//		float t0, t1;
//		std::shared_ptr<HitboxComponent::HitboxSphere> hitbox = std::static_pointer_cast<HitboxComponent::HitboxSphere>(target->getComponent<HitboxComponent>()->hitbox);
//		std::shared_ptr<GunComponent::RayGun> raygun = std::static_pointer_cast<GunComponent::RayGun>(gun);
//		glm::vec3 L = hitbox->center - raygun->ray.o;
//		float tca = glm::dot(L, raygun->ray.dir);
//		if (tca < 0)
//			return false;
//		float d2 = glm::dot(L, L) - tca * tca;
//		if (d2 > hitbox->radius2)
//			return false;
//		float thc = sqrt(hitbox->radius2 - d2);
//		t0 = tca - thc;
//		t1 = tca + thc;
//		if (t0 > t1)
//			std::swap(t0, t1);
//
//		if (t0 < 0) {
//			t0 = t1;
//			if (t0 < 0)
//				return false;
//		}
//
//		raygun->ray.t[0] = raygun->ray.o + t0 * raygun->ray.dir;
//		raygun->ray.t[1] = raygun->ray.o + t1 * raygun->ray.dir;
//		gun = raygun;
//		printf("Entry: %f %f %f\n, Exit: %f %f %f\n\n", raygun->ray.t[0].x, raygun->ray.t[0].y, raygun->ray.t[0].z,
//			raygun->ray.t[1].x, raygun->ray.t[1].y, raygun->ray.t[1].z);
//		hit = true;
//		break;
//	}
//	case HitboxComponent::TETRAHEDRON: {
//
//		break;
//	}
//	case HitboxComponent::AABB: {
//
//		break;
//	}
//	default:
//		break;
//	}
//	return hit;
//}

void GunSystem::registerImGui() {

}<commit_msg>Fixed some things<commit_after>#include "gunsystem.hpp"
#include "../component/transformcomponent.hpp"
#include "../component/guncomponent.hpp"
#include "../component/lifecomponent.hpp"
#include "../component/physicscomponent.hpp"
#include "../component/modelcomponent.hpp"
#include "../component/rigidbodycomponent.hpp"

#include "../system/bulletphysicssystem.hpp"

#include "../entity.hpp"
#include "../src/gl/mesh.hpp"
#include "../src/engine.hpp"

GunSystem::~GunSystem() {}

void GunSystem::update(World& world, float delta) {
	std::vector<Entity*> toAdd;
	for (std::unique_ptr<Entity>& entity : world.getEntities()) {
		auto currGunComp = entity->getComponent<GunComponent>();
		if (!currGunComp)
			continue;

		if (currGunComp->shoot) {
			toAdd.push_back(entity.get());
			currGunComp->shoot = false;
			currGunComp->cooldown = currGunComp->cooldownLength;
		}
		if(currGunComp->cooldown > 0)
			currGunComp->cooldown -= 1 * delta;
	}
	for (Entity* entity : toAdd) {
		fireProjectile(entity, world.addEntity(sole::uuid4(), "Projectile"));
	}
}

void GunSystem::fireProjectile(Entity* me, Entity* projectile) {
	auto transComp = me->getComponent<TransformComponent>();
	auto transProj = projectile->addComponent<TransformComponent>();

	transProj->setPosition(transComp->getPosition());
	transProj->setRotation(transComp->getRotation());
	transProj->setScale(transComp->getScale() * 0.5f);
	transProj->setDirection(glm::vec3(0,0,1)); // should be transComp->getDirection() instead of 0,0,1 but the direction is weird.

	auto currRdbComp = me->getComponent<RigidBodyComponent>();
	auto projRdbComp = projectile->addComponent<RigidBodyComponent>();

	auto projMs = projRdbComp->getMotionState();

	btTransform projRdbTrans = currRdbComp->getRigidBody()->getWorldTransform();

	printf("x: %f, y: %f, z: %f\n", cast(projRdbTrans.getOrigin()).x, cast(projRdbTrans.getOrigin()).y, cast(projRdbTrans.getOrigin()).z);

	projRdbComp->setHitboxHalfSize(currRdbComp->getHitboxHalfSize() * 0.5f);
	projRdbComp->setMass(1);
	projRdbComp->setFriction(0);
	projRdbComp->getRigidBody()->applyCentralImpulse(cast(transProj->getDirection() * 5.0f));
	projRdbComp->getRigidBody()->setWorldTransform(projRdbTrans);

	//projMs->setWorldTransform(projRdbTrans);
	//rdbComp->getRigidBody()->applyCentralImpulse(cast(glm::vec3(4)));

	auto projLifeComp = projectile->addComponent<LifeComponent>();
	projLifeComp->currHP = projLifeComp->maxHP = 2;

	auto modelComp = projectile->addComponent<ModelComponent>();
	modelComp->meshData = Engine::getInstance().getMeshLoader()->getMesh("assets/objects/player.fbx");
	modelComp->meshData->mesh
		->addBuffer("m",
			[](GLuint id) {
		glBindBuffer(GL_ARRAY_BUFFER, id);
		glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4), NULL, GL_DYNAMIC_DRAW);

		for (int i = 0; i < 4; i++) {
			glEnableVertexAttribArray(ShaderAttributeID::m + i);
			glVertexAttribPointer(ShaderAttributeID::m + i, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)(sizeof(glm::vec4) * i));
			glVertexAttribDivisor(ShaderAttributeID::m + i, 1);
		}

		glBindBuffer(GL_ARRAY_BUFFER, 0);
	})
		.finalize();

	Engine::getInstance().getSystem<BulletPhyisicsSystem>()->addRigidBody(projRdbComp);
}

//bool GunSystem::fireRay(std::unique_ptr<Entity>& target, HitboxComponent::HitboxType inType) {
//	bool hit = false;
//	switch (inType)
//	{
//	case HitboxComponent::SPHERE: {
//		float t0, t1;
//		std::shared_ptr<HitboxComponent::HitboxSphere> hitbox = std::static_pointer_cast<HitboxComponent::HitboxSphere>(target->getComponent<HitboxComponent>()->hitbox);
//		std::shared_ptr<GunComponent::RayGun> raygun = std::static_pointer_cast<GunComponent::RayGun>(gun);
//		glm::vec3 L = hitbox->center - raygun->ray.o;
//		float tca = glm::dot(L, raygun->ray.dir);
//		if (tca < 0)
//			return false;
//		float d2 = glm::dot(L, L) - tca * tca;
//		if (d2 > hitbox->radius2)
//			return false;
//		float thc = sqrt(hitbox->radius2 - d2);
//		t0 = tca - thc;
//		t1 = tca + thc;
//		if (t0 > t1)
//			std::swap(t0, t1);
//
//		if (t0 < 0) {
//			t0 = t1;
//			if (t0 < 0)
//				return false;
//		}
//
//		raygun->ray.t[0] = raygun->ray.o + t0 * raygun->ray.dir;
//		raygun->ray.t[1] = raygun->ray.o + t1 * raygun->ray.dir;
//		gun = raygun;
//		printf("Entry: %f %f %f\n, Exit: %f %f %f\n\n", raygun->ray.t[0].x, raygun->ray.t[0].y, raygun->ray.t[0].z,
//			raygun->ray.t[1].x, raygun->ray.t[1].y, raygun->ray.t[1].z);
//		hit = true;
//		break;
//	}
//	case HitboxComponent::TETRAHEDRON: {
//
//		break;
//	}
//	case HitboxComponent::AABB: {
//
//		break;
//	}
//	default:
//		break;
//	}
//	return hit;
//}

void GunSystem::registerImGui() {

}<|endoftext|>


<commit_before>// Copyright (c) 2015-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <chain.h>
#include <chainparams.h>
#include <streams.h>
#include <zmq/zmqpublishnotifier.h>
#include <validation.h>
#include <util/system.h>
#include <rpc/server.h>

static std::multimap<std::string, CZMQAbstractPublishNotifier*> mapPublishNotifiers;

static const char *MSG_HASHBLOCK = "hashblock";
static const char *MSG_HASHTX    = "hashtx";
static const char *MSG_RAWBLOCK  = "rawblock";
static const char *MSG_RAWTX     = "rawtx";
// SYSCOIN
static const char *MSG_RAWMEMPOOLTX  = "rawmempooltx";
static const char *MSG_HASHGVOTE     = "hashgovernancevote";
static const char *MSG_HASHGOBJ      = "hashgovernanceobject";
static const char *MSG_RAWGVOTE      = "rawgovernancevote";
static const char *MSG_RAWGOBJ       = "rawgovernanceobject";
// Internal function to send multipart message
static int zmq_send_multipart(void *sock, const void* data, size_t size, ...)
{
    va_list args;
    va_start(args, size);

    while (1)
    {
        zmq_msg_t msg;

        int rc = zmq_msg_init_size(&msg, size);
        if (rc != 0)
        {
            zmqError("Unable to initialize ZMQ msg");
            va_end(args);
            return -1;
        }

        void *buf = zmq_msg_data(&msg);
        memcpy(buf, data, size);

        data = va_arg(args, const void*);

        rc = zmq_msg_send(&msg, sock, data ? ZMQ_SNDMORE : 0);
        if (rc == -1)
        {
            zmqError("Unable to send ZMQ msg");
            zmq_msg_close(&msg);
            va_end(args);
            return -1;
        }

        zmq_msg_close(&msg);

        if (!data)
            break;

        size = va_arg(args, size_t);
    }
    va_end(args);
    return 0;
}

bool CZMQAbstractPublishNotifier::Initialize(void *pcontext)
{
    assert(!psocket);

    // check if address is being used by other publish notifier
    std::multimap<std::string, CZMQAbstractPublishNotifier*>::iterator i = mapPublishNotifiers.find(address);

    if (i==mapPublishNotifiers.end())
    {
        psocket = zmq_socket(pcontext, ZMQ_PUB);
        if (!psocket)
        {
            zmqError("Failed to create socket");
            return false;
        }

        LogPrint(BCLog::ZMQ, "zmq: Outbound message high water mark for %s at %s is %d\n", type, address, outbound_message_high_water_mark);

        int rc = zmq_setsockopt(psocket, ZMQ_SNDHWM, &outbound_message_high_water_mark, sizeof(outbound_message_high_water_mark));
        if (rc != 0)
        {
            zmqError("Failed to set outbound message high water mark");
            zmq_close(psocket);
            return false;
        }

        rc = zmq_bind(psocket, address.c_str());
        if (rc != 0)
        {
            zmqError("Failed to bind address");
            zmq_close(psocket);
            return false;
        }

        // register this notifier for the address, so it can be reused for other publish notifier
        mapPublishNotifiers.insert(std::make_pair(address, this));
        return true;
    }
    else
    {
        LogPrint(BCLog::ZMQ, "zmq: Reusing socket for address %s\n", address);
        LogPrint(BCLog::ZMQ, "zmq: Outbound message high water mark for %s at %s is %d\n", type, address, outbound_message_high_water_mark);

        psocket = i->second->psocket;
        mapPublishNotifiers.insert(std::make_pair(address, this));

        return true;
    }
}

void CZMQAbstractPublishNotifier::Shutdown()
{
    // Early return if Initialize was not called
    if (!psocket) return;

    int count = mapPublishNotifiers.count(address);

    // remove this notifier from the list of publishers using this address
    typedef std::multimap<std::string, CZMQAbstractPublishNotifier*>::iterator iterator;
    std::pair<iterator, iterator> iterpair = mapPublishNotifiers.equal_range(address);

    for (iterator it = iterpair.first; it != iterpair.second; ++it)
    {
        if (it->second==this)
        {
            mapPublishNotifiers.erase(it);
            break;
        }
    }

    if (count == 1)
    {
        LogPrint(BCLog::ZMQ, "zmq: Close socket at address %s\n", address);
        int linger = 0;
        zmq_setsockopt(psocket, ZMQ_LINGER, &linger, sizeof(linger));
        zmq_close(psocket);
    }

    psocket = nullptr;
}

bool CZMQAbstractPublishNotifier::SendMessage(const char *command, const void* data, size_t size)
{
    assert(psocket);

    /* send three parts, command & data & a LE 4byte sequence number */
    unsigned char msgseq[sizeof(uint32_t)];
    WriteLE32(&msgseq[0], nSequence);
    int rc = zmq_send_multipart(psocket, command, strlen(command), data, size, msgseq, (size_t)sizeof(uint32_t), nullptr);
    if (rc == -1)
        return false;

    /* increment memory only sequence number after sending */
    nSequence++;

    return true;
}

bool CZMQPublishHashBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
{
    uint256 hash = pindex->GetBlockHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish hashblock %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    return SendMessage(MSG_HASHBLOCK, data, 32);
}

bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &transaction)
{
    uint256 hash = transaction.GetHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish hashtx %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    return SendMessage(MSG_HASHTX, data, 32);
}

bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
{
    LogPrint(BCLog::ZMQ, "zmq: Publish rawblock %s\n", pindex->GetBlockHash().GetHex());

    const Consensus::Params& consensusParams = Params().GetConsensus();
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
    {
        LOCK(cs_main);
        CBlock block;
        if(!ReadBlockFromDisk(block, pindex, consensusParams))
        {
            zmqError("Can't read block from disk");
            return false;
        }

        ss << block;
    }

    return SendMessage(MSG_RAWBLOCK, &(*ss.begin()), ss.size());
}
bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &transaction)
{
    uint256 hash = transaction.GetHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish rawtx %s\n", hash.GetHex());
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
    ss << transaction;
    return SendMessage(MSG_RAWTX, &(*ss.begin()), ss.size());
}
// SYSCOIN
bool CZMQPublishHashGovernanceVoteNotifier::NotifyGovernanceVote(const CGovernanceVote &vote)
{
    uint256 hash = vote.GetHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish hashgovernancevote %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    return SendMessage(MSG_HASHGVOTE, data, 32);
}

bool CZMQPublishHashGovernanceObjectNotifier::NotifyGovernanceObject(const CGovernanceObject &object)
{
    uint256 hash = object.GetHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish hashgovernanceobject %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    return SendMessage(MSG_HASHGOBJ, data, 32);
}
bool CZMQPublishRawGovernanceVoteNotifier::NotifyGovernanceVote(const CGovernanceVote &vote)
{
    uint256 nHash = vote.GetHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish rawgovernanceobject: hash = %s, vote = %d\n", nHash.ToString(), vote.ToString());
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
    ss << vote;
    return SendMessage(MSG_RAWGVOTE, &(*ss.begin()), ss.size());
}

bool CZMQPublishRawGovernanceObjectNotifier::NotifyGovernanceObject(const CGovernanceObject &govobj)
{
    uint256 nHash = govobj.GetHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish rawgovernanceobject: hash = %s, type = %d\n", nHash.ToString(), govobj.GetObjectType());
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
    ss << govobj;
    return SendMessage(MSG_RAWGOBJ, &(*ss.begin()), ss.size());
}
bool CZMQPublishRawMempoolTransactionNotifier::NotifyTransactionMempool(const CTransaction &transaction)
{
    uint256 hash = transaction.GetHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish rawmempooltx %s\n", hash.GetHex());
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
    ss << transaction;
    return SendMessage(MSG_RAWMEMPOOLTX, &(*ss.begin()), ss.size());
}

bool CZMQPublishRawSyscoinNotifier::NotifySyscoinUpdate(const char * value, const char * topic)
{
    LogPrint(BCLog::ZMQ, "zmq: Publish raw syscoin payload for topic %s: %s\n", topic, value);
    return SendMessage(topic, value, strlen(value));
}<commit_msg>incl<commit_after>// Copyright (c) 2015-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <chain.h>
#include <chainparams.h>
#include <streams.h>
#include <zmq/zmqpublishnotifier.h>
#include <validation.h>
#include <util/system.h>
#include <rpc/server.h>
#include <governance/governance-vote.h>
#include <governance/governance-object.h>
static std::multimap<std::string, CZMQAbstractPublishNotifier*> mapPublishNotifiers;

static const char *MSG_HASHBLOCK = "hashblock";
static const char *MSG_HASHTX    = "hashtx";
static const char *MSG_RAWBLOCK  = "rawblock";
static const char *MSG_RAWTX     = "rawtx";
// SYSCOIN
static const char *MSG_RAWMEMPOOLTX  = "rawmempooltx";
static const char *MSG_HASHGVOTE     = "hashgovernancevote";
static const char *MSG_HASHGOBJ      = "hashgovernanceobject";
static const char *MSG_RAWGVOTE      = "rawgovernancevote";
static const char *MSG_RAWGOBJ       = "rawgovernanceobject";
// Internal function to send multipart message
static int zmq_send_multipart(void *sock, const void* data, size_t size, ...)
{
    va_list args;
    va_start(args, size);

    while (1)
    {
        zmq_msg_t msg;

        int rc = zmq_msg_init_size(&msg, size);
        if (rc != 0)
        {
            zmqError("Unable to initialize ZMQ msg");
            va_end(args);
            return -1;
        }

        void *buf = zmq_msg_data(&msg);
        memcpy(buf, data, size);

        data = va_arg(args, const void*);

        rc = zmq_msg_send(&msg, sock, data ? ZMQ_SNDMORE : 0);
        if (rc == -1)
        {
            zmqError("Unable to send ZMQ msg");
            zmq_msg_close(&msg);
            va_end(args);
            return -1;
        }

        zmq_msg_close(&msg);

        if (!data)
            break;

        size = va_arg(args, size_t);
    }
    va_end(args);
    return 0;
}

bool CZMQAbstractPublishNotifier::Initialize(void *pcontext)
{
    assert(!psocket);

    // check if address is being used by other publish notifier
    std::multimap<std::string, CZMQAbstractPublishNotifier*>::iterator i = mapPublishNotifiers.find(address);

    if (i==mapPublishNotifiers.end())
    {
        psocket = zmq_socket(pcontext, ZMQ_PUB);
        if (!psocket)
        {
            zmqError("Failed to create socket");
            return false;
        }

        LogPrint(BCLog::ZMQ, "zmq: Outbound message high water mark for %s at %s is %d\n", type, address, outbound_message_high_water_mark);

        int rc = zmq_setsockopt(psocket, ZMQ_SNDHWM, &outbound_message_high_water_mark, sizeof(outbound_message_high_water_mark));
        if (rc != 0)
        {
            zmqError("Failed to set outbound message high water mark");
            zmq_close(psocket);
            return false;
        }

        rc = zmq_bind(psocket, address.c_str());
        if (rc != 0)
        {
            zmqError("Failed to bind address");
            zmq_close(psocket);
            return false;
        }

        // register this notifier for the address, so it can be reused for other publish notifier
        mapPublishNotifiers.insert(std::make_pair(address, this));
        return true;
    }
    else
    {
        LogPrint(BCLog::ZMQ, "zmq: Reusing socket for address %s\n", address);
        LogPrint(BCLog::ZMQ, "zmq: Outbound message high water mark for %s at %s is %d\n", type, address, outbound_message_high_water_mark);

        psocket = i->second->psocket;
        mapPublishNotifiers.insert(std::make_pair(address, this));

        return true;
    }
}

void CZMQAbstractPublishNotifier::Shutdown()
{
    // Early return if Initialize was not called
    if (!psocket) return;

    int count = mapPublishNotifiers.count(address);

    // remove this notifier from the list of publishers using this address
    typedef std::multimap<std::string, CZMQAbstractPublishNotifier*>::iterator iterator;
    std::pair<iterator, iterator> iterpair = mapPublishNotifiers.equal_range(address);

    for (iterator it = iterpair.first; it != iterpair.second; ++it)
    {
        if (it->second==this)
        {
            mapPublishNotifiers.erase(it);
            break;
        }
    }

    if (count == 1)
    {
        LogPrint(BCLog::ZMQ, "zmq: Close socket at address %s\n", address);
        int linger = 0;
        zmq_setsockopt(psocket, ZMQ_LINGER, &linger, sizeof(linger));
        zmq_close(psocket);
    }

    psocket = nullptr;
}

bool CZMQAbstractPublishNotifier::SendMessage(const char *command, const void* data, size_t size)
{
    assert(psocket);

    /* send three parts, command & data & a LE 4byte sequence number */
    unsigned char msgseq[sizeof(uint32_t)];
    WriteLE32(&msgseq[0], nSequence);
    int rc = zmq_send_multipart(psocket, command, strlen(command), data, size, msgseq, (size_t)sizeof(uint32_t), nullptr);
    if (rc == -1)
        return false;

    /* increment memory only sequence number after sending */
    nSequence++;

    return true;
}

bool CZMQPublishHashBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
{
    uint256 hash = pindex->GetBlockHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish hashblock %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    return SendMessage(MSG_HASHBLOCK, data, 32);
}

bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &transaction)
{
    uint256 hash = transaction.GetHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish hashtx %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    return SendMessage(MSG_HASHTX, data, 32);
}

bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
{
    LogPrint(BCLog::ZMQ, "zmq: Publish rawblock %s\n", pindex->GetBlockHash().GetHex());

    const Consensus::Params& consensusParams = Params().GetConsensus();
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
    {
        LOCK(cs_main);
        CBlock block;
        if(!ReadBlockFromDisk(block, pindex, consensusParams))
        {
            zmqError("Can't read block from disk");
            return false;
        }

        ss << block;
    }

    return SendMessage(MSG_RAWBLOCK, &(*ss.begin()), ss.size());
}
bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &transaction)
{
    uint256 hash = transaction.GetHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish rawtx %s\n", hash.GetHex());
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
    ss << transaction;
    return SendMessage(MSG_RAWTX, &(*ss.begin()), ss.size());
}
// SYSCOIN
bool CZMQPublishHashGovernanceVoteNotifier::NotifyGovernanceVote(const CGovernanceVote &vote)
{
    uint256 hash = vote.GetHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish hashgovernancevote %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    return SendMessage(MSG_HASHGVOTE, data, 32);
}

bool CZMQPublishHashGovernanceObjectNotifier::NotifyGovernanceObject(const CGovernanceObject &object)
{
    uint256 hash = object.GetHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish hashgovernanceobject %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    return SendMessage(MSG_HASHGOBJ, data, 32);
}
bool CZMQPublishRawGovernanceVoteNotifier::NotifyGovernanceVote(const CGovernanceVote &vote)
{
    uint256 nHash = vote.GetHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish rawgovernanceobject: hash = %s, vote = %d\n", nHash.ToString(), vote.ToString());
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
    ss << vote;
    return SendMessage(MSG_RAWGVOTE, &(*ss.begin()), ss.size());
}

bool CZMQPublishRawGovernanceObjectNotifier::NotifyGovernanceObject(const CGovernanceObject &govobj)
{
    uint256 nHash = govobj.GetHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish rawgovernanceobject: hash = %s, type = %d\n", nHash.ToString(), govobj.GetObjectType());
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
    ss << govobj;
    return SendMessage(MSG_RAWGOBJ, &(*ss.begin()), ss.size());
}
bool CZMQPublishRawMempoolTransactionNotifier::NotifyTransactionMempool(const CTransaction &transaction)
{
    uint256 hash = transaction.GetHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish rawmempooltx %s\n", hash.GetHex());
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
    ss << transaction;
    return SendMessage(MSG_RAWMEMPOOLTX, &(*ss.begin()), ss.size());
}

bool CZMQPublishRawSyscoinNotifier::NotifySyscoinUpdate(const char * value, const char * topic)
{
    LogPrint(BCLog::ZMQ, "zmq: Publish raw syscoin payload for topic %s: %s\n", topic, value);
    return SendMessage(topic, value, strlen(value));
}<|endoftext|>


<commit_before>// Copyright (c) 2015 The Bitcoin Core developers
// Copyright (c) 2015-2018 The Bitcoin Unlimited developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "zmqpublishnotifier.h"
#include "chainparams.h"
#include "main.h"
#include "util.h"

static std::multimap<std::string, CZMQAbstractPublishNotifier *> mapPublishNotifiers;

// Internal function to send multipart message
static int zmq_send_multipart(void *sock, const void *data, size_t size, ...)
{
    va_list args;
    va_start(args, size);

    while (1)
    {
        zmq_msg_t msg;

        int rc = zmq_msg_init_size(&msg, size);
        if (rc != 0)
        {
            zmqError("Unable to initialize ZMQ msg");
            return -1;
        }

        void *buf = zmq_msg_data(&msg);
        memcpy(buf, data, size);

        data = va_arg(args, const void *);

        rc = zmq_msg_send(&msg, sock, data ? ZMQ_SNDMORE : 0);
        if (rc == -1)
        {
            zmqError("Unable to send ZMQ msg");
            zmq_msg_close(&msg);
            return -1;
        }

        zmq_msg_close(&msg);

        if (!data)
            break;

        size = va_arg(args, size_t);
    }
    return 0;
}

bool CZMQAbstractPublishNotifier::Initialize(void *pcontext)
{
    assert(!psocket);

    // check if address is being used by other publish notifier
    std::multimap<std::string, CZMQAbstractPublishNotifier *>::iterator i = mapPublishNotifiers.find(address);

    if (i == mapPublishNotifiers.end())
    {
        psocket = zmq_socket(pcontext, ZMQ_PUB);
        if (!psocket)
        {
            zmqError("Failed to create socket");
            return false;
        }

        int rc = zmq_bind(psocket, address.c_str());
        if (rc != 0)
        {
            zmqError("Failed to bind address");
            return false;
        }

        // register this notifier for the address, so it can be reused for other publish notifier
        mapPublishNotifiers.insert(std::make_pair(address, this));
        return true;
    }
    else
    {
        LOG(ZMQ, "zmq: Reusing socket for address %s\n", address);

        psocket = i->second->psocket;
        mapPublishNotifiers.insert(std::make_pair(address, this));

        return true;
    }
}

void CZMQAbstractPublishNotifier::Shutdown()
{
    assert(psocket);

    int count = mapPublishNotifiers.count(address);

    // remove this notifier from the list of publishers using this address
    typedef std::multimap<std::string, CZMQAbstractPublishNotifier *>::iterator iterator;
    std::pair<iterator, iterator> iterpair = mapPublishNotifiers.equal_range(address);

    for (iterator it = iterpair.first; it != iterpair.second; ++it)
    {
        if (it->second == this)
        {
            mapPublishNotifiers.erase(it);
            break;
        }
    }

    if (count == 1)
    {
        LOG(ZMQ, "Close socket at address %s\n", address);
        int linger = 0;
        zmq_setsockopt(psocket, ZMQ_LINGER, &linger, sizeof(linger));
        zmq_close(psocket);
    }

    psocket = 0;
}

bool CZMQPublishHashBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
{
    uint256 hash = pindex->GetBlockHash();
    LOG(ZMQ, "zmq: Publish hashblock %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    int rc = zmq_send_multipart(psocket, "hashblock", 9, data, 32, 0);
    return rc == 0;
}

bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransactionRef &ptx)
{
    uint256 hash = ptx->GetHash();
    LOG(ZMQ, "zmq: Publish hashtx %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    int rc = zmq_send_multipart(psocket, "hashtx", 6, data, 32, 0);
    return rc == 0;
}

bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
{
    LOG(ZMQ, "zmq: Publish rawblock %s\n", pindex->GetBlockHash().GetHex());

    const Consensus::Params &consensusParams = Params().GetConsensus();
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
    {
        LOCK(cs_main);
        CBlock block;
        if (!ReadBlockFromDisk(block, pindex, consensusParams))
        {
            zmqError("Can't read block from disk");
            return false;
        }

        ss << block;
    }

    int rc = zmq_send_multipart(psocket, "rawblock", 8, &(*ss.begin()), ss.size(), 0);
    return rc == 0;
}

bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransactionRef &ptx)
{
    uint256 hash = ptx->GetHash();
    LOG(ZMQ, "zmq: Publish rawtx %s\n", hash.GetHex());
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
    ss << *ptx;
    int rc = zmq_send_multipart(psocket, "rawtx", 5, &(*ss.begin()), ss.size(), 0);
    return rc == 0;
}
<commit_msg>[zmq] Call va_end() on va_start()ed args.<commit_after>// Copyright (c) 2015 The Bitcoin Core developers
// Copyright (c) 2015-2018 The Bitcoin Unlimited developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "zmqpublishnotifier.h"
#include "chainparams.h"
#include "main.h"
#include "util.h"

static std::multimap<std::string, CZMQAbstractPublishNotifier *> mapPublishNotifiers;

// Internal function to send multipart message
static int zmq_send_multipart(void *sock, const void *data, size_t size, ...)
{
    va_list args;
    va_start(args, size);

    while (1)
    {
        zmq_msg_t msg;

        int rc = zmq_msg_init_size(&msg, size);
        if (rc != 0)
        {
            zmqError("Unable to initialize ZMQ msg");
            va_end(args);
            return -1;
        }

        void *buf = zmq_msg_data(&msg);
        memcpy(buf, data, size);

        data = va_arg(args, const void *);

        rc = zmq_msg_send(&msg, sock, data ? ZMQ_SNDMORE : 0);
        if (rc == -1)
        {
            zmqError("Unable to send ZMQ msg");
            zmq_msg_close(&msg);
            va_end(args);
            return -1;
        }

        zmq_msg_close(&msg);

        if (!data)
            break;

        size = va_arg(args, size_t);
    }
    va_end(args);
    return 0;
}

bool CZMQAbstractPublishNotifier::Initialize(void *pcontext)
{
    assert(!psocket);

    // check if address is being used by other publish notifier
    std::multimap<std::string, CZMQAbstractPublishNotifier *>::iterator i = mapPublishNotifiers.find(address);

    if (i == mapPublishNotifiers.end())
    {
        psocket = zmq_socket(pcontext, ZMQ_PUB);
        if (!psocket)
        {
            zmqError("Failed to create socket");
            return false;
        }

        int rc = zmq_bind(psocket, address.c_str());
        if (rc != 0)
        {
            zmqError("Failed to bind address");
            return false;
        }

        // register this notifier for the address, so it can be reused for other publish notifier
        mapPublishNotifiers.insert(std::make_pair(address, this));
        return true;
    }
    else
    {
        LOG(ZMQ, "zmq: Reusing socket for address %s\n", address);

        psocket = i->second->psocket;
        mapPublishNotifiers.insert(std::make_pair(address, this));

        return true;
    }
}

void CZMQAbstractPublishNotifier::Shutdown()
{
    assert(psocket);

    int count = mapPublishNotifiers.count(address);

    // remove this notifier from the list of publishers using this address
    typedef std::multimap<std::string, CZMQAbstractPublishNotifier *>::iterator iterator;
    std::pair<iterator, iterator> iterpair = mapPublishNotifiers.equal_range(address);

    for (iterator it = iterpair.first; it != iterpair.second; ++it)
    {
        if (it->second == this)
        {
            mapPublishNotifiers.erase(it);
            break;
        }
    }

    if (count == 1)
    {
        LOG(ZMQ, "Close socket at address %s\n", address);
        int linger = 0;
        zmq_setsockopt(psocket, ZMQ_LINGER, &linger, sizeof(linger));
        zmq_close(psocket);
    }

    psocket = 0;
}

bool CZMQPublishHashBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
{
    uint256 hash = pindex->GetBlockHash();
    LOG(ZMQ, "zmq: Publish hashblock %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    int rc = zmq_send_multipart(psocket, "hashblock", 9, data, 32, 0);
    return rc == 0;
}

bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransactionRef &ptx)
{
    uint256 hash = ptx->GetHash();
    LOG(ZMQ, "zmq: Publish hashtx %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    int rc = zmq_send_multipart(psocket, "hashtx", 6, data, 32, 0);
    return rc == 0;
}

bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
{
    LOG(ZMQ, "zmq: Publish rawblock %s\n", pindex->GetBlockHash().GetHex());

    const Consensus::Params &consensusParams = Params().GetConsensus();
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
    {
        LOCK(cs_main);
        CBlock block;
        if (!ReadBlockFromDisk(block, pindex, consensusParams))
        {
            zmqError("Can't read block from disk");
            return false;
        }

        ss << block;
    }

    int rc = zmq_send_multipart(psocket, "rawblock", 8, &(*ss.begin()), ss.size(), 0);
    return rc == 0;
}

bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransactionRef &ptx)
{
    uint256 hash = ptx->GetHash();
    LOG(ZMQ, "zmq: Publish rawtx %s\n", hash.GetHex());
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
    ss << *ptx;
    int rc = zmq_send_multipart(psocket, "rawtx", 5, &(*ss.begin()), ss.size(), 0);
    return rc == 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <chain.h>
#include <chainparams.h>
#include <streams.h>
#include <zmq/zmqpublishnotifier.h>
#include <validation.h>
#include <util.h>
#include <rpc/server.h>

static std::multimap<std::string, CZMQAbstractPublishNotifier*> mapPublishNotifiers;

static const char *MSG_HASHBLOCK  = "hashblock";
static const char *MSG_HASHTX     = "hashtx";
static const char *MSG_HASHGVOTE  = "hashgovernancevote";
static const char *MSG_HASHGOBJ   = "hashgovernanceobject";
static const char *MSG_RAWBLOCK   = "rawblock";
static const char *MSG_RAWTX      = "rawtx";
static const char *MSG_RAWGVOTE   = "rawgovernancevote";
static const char *MSG_RAWGOBJ    = "rawgovernanceobject";

// Internal function to send multipart message
static int zmq_send_multipart(void *sock, const void* data, size_t size, ...)
{
    va_list args;
    va_start(args, size);

    while (1)
    {
        zmq_msg_t msg;

        int rc = zmq_msg_init_size(&msg, size);
        if (rc != 0)
        {
            zmqError("Unable to initialize ZMQ msg");
            va_end(args);
            return -1;
        }

        void *buf = zmq_msg_data(&msg);
        memcpy(buf, data, size);

        data = va_arg(args, const void*);

        rc = zmq_msg_send(&msg, sock, data ? ZMQ_SNDMORE : 0);
        if (rc == -1)
        {
            zmqError("Unable to send ZMQ msg");
            zmq_msg_close(&msg);
            va_end(args);
            return -1;
        }

        zmq_msg_close(&msg);

        if (!data)
            break;

        size = va_arg(args, size_t);
    }
    va_end(args);
    return 0;
}

bool CZMQAbstractPublishNotifier::Initialize(void *pcontext)
{
    assert(!psocket);

    // check if address is being used by other publish notifier
    std::multimap<std::string, CZMQAbstractPublishNotifier*>::iterator i = mapPublishNotifiers.find(address);

    if (i==mapPublishNotifiers.end())
    {
        psocket = zmq_socket(pcontext, ZMQ_PUB);
        if (!psocket)
        {
            zmqError("Failed to create socket");
            return false;
        }

        int rc = zmq_bind(psocket, address.c_str());
        if (rc!=0)
        {
            zmqError("Failed to bind address");
            zmq_close(psocket);
            return false;
        }

        // register this notifier for the address, so it can be reused for other publish notifier
        mapPublishNotifiers.insert(std::make_pair(address, this));
        return true;
    }
    else
    {
        LogPrint(BCLog::ZMQ, "zmq: Reusing socket for address %s\n", address);

        psocket = i->second->psocket;
        mapPublishNotifiers.insert(std::make_pair(address, this));

        return true;
    }
}

void CZMQAbstractPublishNotifier::Shutdown()
{
    assert(psocket);

    int count = mapPublishNotifiers.count(address);

    // remove this notifier from the list of publishers using this address
    typedef std::multimap<std::string, CZMQAbstractPublishNotifier*>::iterator iterator;
    std::pair<iterator, iterator> iterpair = mapPublishNotifiers.equal_range(address);

    for (iterator it = iterpair.first; it != iterpair.second; ++it)
    {
        if (it->second==this)
        {
            mapPublishNotifiers.erase(it);
            break;
        }
    }

    if (count == 1)
    {
        LogPrint(BCLog::ZMQ, "Close socket at address %s\n", address);
        int linger = 0;
        zmq_setsockopt(psocket, ZMQ_LINGER, &linger, sizeof(linger));
        zmq_close(psocket);
    }

    psocket = nullptr;
}

bool CZMQAbstractPublishNotifier::SendMessage(const char *command, const void* data, size_t size)
{
    assert(psocket);

    /* send three parts, command & data & a LE 4byte sequence number */
    unsigned char msgseq[sizeof(uint32_t)];
    WriteLE32(&msgseq[0], nSequence);
    int rc = zmq_send_multipart(psocket, command, strlen(command), data, size, msgseq, (size_t)sizeof(uint32_t), nullptr);
    if (rc == -1)
        return false;

    /* increment memory only sequence number after sending */
    nSequence++;

    return true;
}

bool CZMQPublishHashBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
{
    uint256 hash = pindex->GetBlockHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish hashblock %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    return SendMessage(MSG_HASHBLOCK, data, 32);
}

bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &transaction)
{
    uint256 hash = transaction.GetHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish hashtx %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    return SendMessage(MSG_HASHTX, data, 32);
}

bool CZMQPublishHashGovernanceVoteNotifier::NotifyGovernanceVote(const CGovernanceVote &vote)
{
    uint256 hash = vote.GetHash();
    LogPrint("zmq", "zmq: Publish hashgovernancevote %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    return SendMessage(MSG_HASHGVOTE, data, 32);
}

bool CZMQPublishHashGovernanceObjectNotifier::NotifyGovernanceObject(const CGovernanceObject &object)
{
    uint256 hash = object.GetHash();
    LogPrint("zmq", "zmq: Publish hashgovernanceobject %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    return SendMessage(MSG_HASHGOBJ, data, 32);
}

bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
{
    LogPrint(BCLog::ZMQ, "zmq: Publish rawblock %s\n", pindex->GetBlockHash().GetHex());

    const Consensus::Params& consensusParams = Params().GetConsensus();
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
    {
        LOCK(cs_main);
        CBlock block;
        if(!ReadBlockFromDisk(block, pindex, consensusParams))
        {
            zmqError("Can't read block from disk");
            return false;
        }

        ss << block;
    }

    return SendMessage(MSG_RAWBLOCK, &(*ss.begin()), ss.size());
}

bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &transaction)
{
    uint256 hash = transaction.GetHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish rawtx %s\n", hash.GetHex());
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
    ss << transaction;
    return SendMessage(MSG_RAWTX, &(*ss.begin()), ss.size());
}

bool CZMQPublishRawGovernanceVoteNotifier::NotifyGovernanceVote(const CGovernanceVote &vote)
{
    uint256 nHash = vote.GetHash();
    LogPrint("gobject", "gobject: Publish rawgovernanceobject: hash = %s, vote = %d\n", nHash.ToString(), vote.ToString());
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
    ss << vote;
    return SendMessage(MSG_RAWGVOTE, &(*ss.begin()), ss.size());
}

bool CZMQPublishRawGovernanceObjectNotifier::NotifyGovernanceObject(const CGovernanceObject &govobj)
{
    uint256 nHash = govobj.GetHash();
    LogPrint("gobject", "gobject: Publish rawgovernanceobject: hash = %s, type = %d\n", nHash.ToString(), govobj.GetObjectType());
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
    ss << govobj;
    return SendMessage(MSG_RAWGOBJ, &(*ss.begin()), ss.size());
}
<commit_msg>fix logging in ZMQ<commit_after>// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <chain.h>
#include <chainparams.h>
#include <streams.h>
#include <zmq/zmqpublishnotifier.h>
#include <validation.h>
#include <util.h>
#include <rpc/server.h>

static std::multimap<std::string, CZMQAbstractPublishNotifier*> mapPublishNotifiers;

static const char *MSG_HASHBLOCK  = "hashblock";
static const char *MSG_HASHTX     = "hashtx";
static const char *MSG_HASHGVOTE  = "hashgovernancevote";
static const char *MSG_HASHGOBJ   = "hashgovernanceobject";
static const char *MSG_RAWBLOCK   = "rawblock";
static const char *MSG_RAWTX      = "rawtx";
static const char *MSG_RAWGVOTE   = "rawgovernancevote";
static const char *MSG_RAWGOBJ    = "rawgovernanceobject";

// Internal function to send multipart message
static int zmq_send_multipart(void *sock, const void* data, size_t size, ...)
{
    va_list args;
    va_start(args, size);

    while (1)
    {
        zmq_msg_t msg;

        int rc = zmq_msg_init_size(&msg, size);
        if (rc != 0)
        {
            zmqError("Unable to initialize ZMQ msg");
            va_end(args);
            return -1;
        }

        void *buf = zmq_msg_data(&msg);
        memcpy(buf, data, size);

        data = va_arg(args, const void*);

        rc = zmq_msg_send(&msg, sock, data ? ZMQ_SNDMORE : 0);
        if (rc == -1)
        {
            zmqError("Unable to send ZMQ msg");
            zmq_msg_close(&msg);
            va_end(args);
            return -1;
        }

        zmq_msg_close(&msg);

        if (!data)
            break;

        size = va_arg(args, size_t);
    }
    va_end(args);
    return 0;
}

bool CZMQAbstractPublishNotifier::Initialize(void *pcontext)
{
    assert(!psocket);

    // check if address is being used by other publish notifier
    std::multimap<std::string, CZMQAbstractPublishNotifier*>::iterator i = mapPublishNotifiers.find(address);

    if (i==mapPublishNotifiers.end())
    {
        psocket = zmq_socket(pcontext, ZMQ_PUB);
        if (!psocket)
        {
            zmqError("Failed to create socket");
            return false;
        }

        int rc = zmq_bind(psocket, address.c_str());
        if (rc!=0)
        {
            zmqError("Failed to bind address");
            zmq_close(psocket);
            return false;
        }

        // register this notifier for the address, so it can be reused for other publish notifier
        mapPublishNotifiers.insert(std::make_pair(address, this));
        return true;
    }
    else
    {
        LogPrint(BCLog::ZMQ, "zmq: Reusing socket for address %s\n", address);

        psocket = i->second->psocket;
        mapPublishNotifiers.insert(std::make_pair(address, this));

        return true;
    }
}

void CZMQAbstractPublishNotifier::Shutdown()
{
    assert(psocket);

    int count = mapPublishNotifiers.count(address);

    // remove this notifier from the list of publishers using this address
    typedef std::multimap<std::string, CZMQAbstractPublishNotifier*>::iterator iterator;
    std::pair<iterator, iterator> iterpair = mapPublishNotifiers.equal_range(address);

    for (iterator it = iterpair.first; it != iterpair.second; ++it)
    {
        if (it->second==this)
        {
            mapPublishNotifiers.erase(it);
            break;
        }
    }

    if (count == 1)
    {
        LogPrint(BCLog::ZMQ, "Close socket at address %s\n", address);
        int linger = 0;
        zmq_setsockopt(psocket, ZMQ_LINGER, &linger, sizeof(linger));
        zmq_close(psocket);
    }

    psocket = nullptr;
}

bool CZMQAbstractPublishNotifier::SendMessage(const char *command, const void* data, size_t size)
{
    assert(psocket);

    /* send three parts, command & data & a LE 4byte sequence number */
    unsigned char msgseq[sizeof(uint32_t)];
    WriteLE32(&msgseq[0], nSequence);
    int rc = zmq_send_multipart(psocket, command, strlen(command), data, size, msgseq, (size_t)sizeof(uint32_t), nullptr);
    if (rc == -1)
        return false;

    /* increment memory only sequence number after sending */
    nSequence++;

    return true;
}

bool CZMQPublishHashBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
{
    uint256 hash = pindex->GetBlockHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish hashblock %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    return SendMessage(MSG_HASHBLOCK, data, 32);
}

bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &transaction)
{
    uint256 hash = transaction.GetHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish hashtx %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    return SendMessage(MSG_HASHTX, data, 32);
}

bool CZMQPublishHashGovernanceVoteNotifier::NotifyGovernanceVote(const CGovernanceVote &vote)
{
    uint256 hash = vote.GetHash();
    LogPrint("zmq", "zmq: Publish hashgovernancevote %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    return SendMessage(MSG_HASHGVOTE, data, 32);
}

bool CZMQPublishHashGovernanceObjectNotifier::NotifyGovernanceObject(const CGovernanceObject &object)
{
    uint256 hash = object.GetHash();
    LogPrint("zmq", "zmq: Publish hashgovernanceobject %s\n", hash.GetHex());
    char data[32];
    for (unsigned int i = 0; i < 32; i++)
        data[31 - i] = hash.begin()[i];
    return SendMessage(MSG_HASHGOBJ, data, 32);
}

bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
{
    LogPrint(BCLog::ZMQ, "zmq: Publish rawblock %s\n", pindex->GetBlockHash().GetHex());

    const Consensus::Params& consensusParams = Params().GetConsensus();
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
    {
        LOCK(cs_main);
        CBlock block;
        if(!ReadBlockFromDisk(block, pindex, consensusParams))
        {
            zmqError("Can't read block from disk");
            return false;
        }

        ss << block;
    }

    return SendMessage(MSG_RAWBLOCK, &(*ss.begin()), ss.size());
}

bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &transaction)
{
    uint256 hash = transaction.GetHash();
    LogPrint(BCLog::ZMQ, "zmq: Publish rawtx %s\n", hash.GetHex());
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
    ss << transaction;
    return SendMessage(MSG_RAWTX, &(*ss.begin()), ss.size());
}

bool CZMQPublishRawGovernanceVoteNotifier::NotifyGovernanceVote(const CGovernanceVote &vote)
{
    uint256 nHash = vote.GetHash();
    LogPrint(BCLog::GOV, "gobject: Publish rawgovernanceobject: hash = %s, vote = %d\n", nHash.ToString(), vote.ToString());
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
    ss << vote;
    return SendMessage(MSG_RAWGVOTE, &(*ss.begin()), ss.size());
}

bool CZMQPublishRawGovernanceObjectNotifier::NotifyGovernanceObject(const CGovernanceObject &govobj)
{
    uint256 nHash = govobj.GetHash();
    LogPrint(BCLog::GOV, "gobject: Publish rawgovernanceobject: hash = %s, type = %d\n", nHash.ToString(), govobj.GetObjectType());
    CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
    ss << govobj;
    return SendMessage(MSG_RAWGOBJ, &(*ss.begin()), ss.size());
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2009-2012, Willow Garage, Inc.
 *  Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho,
 *                      Johns Hopkins University
 *
 *  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 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.
 *
 * $Id$
 *
 */

namespace pcl {
  namespace poisson {

    //////////////////////
    // Polynomial Roots //
    //////////////////////
#include <math.h>
#include "pcl/surface/poisson/factor.h"
    int Factor(double a1,double a0,double roots[1][2],const double& EPS){
      if(fabs(a1)<=EPS){return 0;}
      roots[0][0]=-a0/a1;
      roots[0][1]=0;
      return 1;
    }
    int Factor(double a2,double a1,double a0,double roots[2][2],const double& EPS){
      double d;
      if(fabs(a2)<=EPS){return Factor(a1,a0,roots,EPS);}

      d=a1*a1-4*a0*a2;
      a1/=(2*a2);
      if(d<0){
        d=sqrt(-d)/(2*a2);
        roots[0][0]=roots[1][0]=-a1;
        roots[0][1]=-d;
        roots[1][1]= d;
      }
      else{
        d=sqrt(d)/(2*a2);
        roots[0][1]=roots[1][1]=0;
        roots[0][0]=-a1-d;
        roots[1][0]=-a1+d;
      }
      return 2;
    }
    // Solution taken from: http://mathworld.wolfram.com/CubicFormula.html
    // and http://www.csit.fsu.edu/~burkardt/f_src/subpak/subpak.f90
    int Factor(double a3,double a2,double a1,double a0,double roots[3][2],const double& EPS){
      double q,r,r2,q3;

      if(fabs(a3)<=EPS){return Factor(a2,a1,a0,roots,EPS);}
      a2/=a3;
      a1/=a3;
      a0/=a3;

      q=-(3*a1-a2*a2)/9;
      r=-(9*a2*a1-27*a0-2*a2*a2*a2)/54;
      r2=r*r;
      q3=q*q*q;

      if(r2<q3){
        double sqrQ=sqrt(q);
        double theta = acos ( r / (sqrQ*q) );
        double cTheta=cos(theta/3)*sqrQ;
        double sTheta=sin(theta/3)*sqrQ*SQRT_3/2;
        roots[0][1]=roots[1][1]=roots[2][1]=0;
        roots[0][0]=-2*cTheta;
        roots[1][0]=-2*(-cTheta*0.5-sTheta);
        roots[2][0]=-2*(-cTheta*0.5+sTheta);
      }
      else{
        double s1,s2,sqr=sqrt(r2-q3);
        double t;
        t=-r+sqr;
        if(t<0){s1=-pow(-t,1.0/3);}
        else{s1=pow(t,1.0/3);}
        t=-r-sqr;
        if(t<0){s2=-pow(-t,1.0/3);}
        else{s2=pow(t,1.0/3);}
        roots[0][1]=0;
        roots[0][0]=s1+s2;
        s1/=2;
        s2/=2;
        roots[1][0]= roots[2][0]=-s1-s2;
        roots[1][1]= SQRT_3*(s1-s2);
        roots[2][1]=-roots[1][1];
      }
      roots[0][0]-=a2/3;
      roots[1][0]-=a2/3;
      roots[2][0]-=a2/3;
      return 3;
    }
    double ArcTan2(const double& y,const double& x){
      /* This first case should never happen */
      if(y==0 && x==0){return 0;}
      if(x==0){
        if(y>0){return PI/2.0;}
        else{return -PI/2.0;}
      }
      if(x>=0){return atan(y/x);}
      else{
        if(y>=0){return atan(y/x)+PI;}
        else{return atan(y/x)-PI;}
      }
    }
    double Angle(const double in[2]){
      if((in[0]*in[0]+in[1]*in[1])==0.0){return 0;}
      else{return ArcTan2(in[1],in[0]);}
    }
    void Sqrt(const double in[2],double out[2]){
      double r=sqrt(sqrt(in[0]*in[0]+in[1]*in[1]));
      double a=Angle(in)*0.5;
      out[0]=r*cos(a);
      out[1]=r*sin(a);
    }
    void Add(const double in1[2],const double in2[2],double out[2]){
      out[0]=in1[0]+in2[0];
      out[1]=in1[1]+in2[1];
    }
    void Subtract(const double in1[2],const double in2[2],double out[2]){
      out[0]=in1[0]-in2[0];
      out[1]=in1[1]-in2[1];
    }
    void Multiply(const double in1[2],const double in2[2],double out[2]){
      out[0]=in1[0]*in2[0]-in1[1]*in2[1];
      out[1]=in1[0]*in2[1]+in1[1]*in2[0];
    }
    void Divide(const double in1[2],const double in2[2],double out[2]){
      double temp[2];
      double l=in2[0]*in2[0]+in2[1]*in2[1];
      temp[0]= in2[0]/l;
      temp[1]=-in2[1]/l;
      Multiply(in1,temp,out);
    }
    // Solution taken from: http://mathworld.wolfram.com/QuarticEquation.html
    // and http://www.csit.fsu.edu/~burkardt/f_src/subpak/subpak.f90
    int Factor(double a4,double a3,double a2,double a1,double a0,double roots[4][2],const double& EPS){
      double R[2],D[2],E[2],R2[2];

      if(fabs(a4)<EPS){return Factor(a3,a2,a1,a0,roots,EPS);}
      a3/=a4;
      a2/=a4;
      a1/=a4;
      a0/=a4;

      Factor(1.0,-a2,a3*a1-4.0*a0,-a3*a3*a0+4.0*a2*a0-a1*a1,roots,EPS);

      R2[0]=a3*a3/4.0-a2+roots[0][0];
      R2[1]=0;
      Sqrt(R2,R);
      if(fabs(R[0])>10e-8){
        double temp1[2],temp2[2];
        double p1[2],p2[2];

        p1[0]=a3*a3*0.75-2.0*a2-R2[0];
        p1[1]=0;

        temp2[0]=((4.0*a3*a2-8.0*a1-a3*a3*a3)/4.0);
        temp2[1]=0;
        Divide(temp2,R,p2);

        Add     (p1,p2,temp1);
        Subtract(p1,p2,temp2);

        Sqrt(temp1,D);
        Sqrt(temp2,E);
      }
      else{
        R[0]=R[1]=0;
        double temp1[2],temp2[2];
        temp1[0]=roots[0][0]*roots[0][0]-4.0*a0;
        temp1[1]=0;
        Sqrt(temp1,temp2);
        temp1[0]=a3*a3*0.75-2.0*a2+2.0*temp2[0];
        temp1[1]=                  2.0*temp2[1];
        Sqrt(temp1,D);
        temp1[0]=a3*a3*0.75-2.0*a2-2.0*temp2[0];
        temp1[1]=                 -2.0*temp2[1];
        Sqrt(temp1,E);
      }

      roots[0][0]=-a3/4.0+R[0]/2.0+D[0]/2.0;
      roots[0][1]=        R[1]/2.0+D[1]/2.0;

      roots[1][0]=-a3/4.0+R[0]/2.0-D[0]/2.0;
      roots[1][1]=        R[1]/2.0-D[1]/2.0;

      roots[2][0]=-a3/4.0-R[0]/2.0+E[0]/2.0;
      roots[2][1]=       -R[1]/2.0+E[1]/2.0;

      roots[3][0]=-a3/4.0-R[0]/2.0-E[0]/2.0;
      roots[3][1]=       -R[1]/2.0-E[1]/2.0;
      return 4;
    }

    int Solve(const double* eqns,const double* values,double* solutions,const int& dim){
      int i,j,eIndex;
      double v,m;
      int *index=new int[dim];
      int *set=new int[dim];
      double* myEqns=new double[dim*dim];
      double* myValues=new double[dim];

      for(i=0;i<dim*dim;i++){myEqns[i]=eqns[i];}
      for(i=0;i<dim;i++){
        myValues[i]=values[i];
        set[i]=0;
      }
      for(i=0;i<dim;i++){
        // Find the largest equation that has a non-zero entry in the i-th index
        m=-1;
        eIndex=-1;
        for(j=0;j<dim;j++){
          if(set[j]){continue;}
          if(myEqns[j*dim+i]!=0 && fabs(myEqns[j*dim+i])>m){
            m=fabs(myEqns[j*dim+i]);
            eIndex=j;
          }
        }
        if(eIndex==-1){
          delete[] index;
          delete[] myValues;
          delete[] myEqns;
          delete[] set;
          return 0;
        }
        // The position in which the solution for the i-th variable can be found
        index[i]=eIndex;
        set[eIndex]=1;

        // Normalize the equation
        v=myEqns[eIndex*dim+i];
        for(j=0;j<dim;j++){myEqns[eIndex*dim+j]/=v;}
        myValues[eIndex]/=v;

        // Subtract it off from everything else
        for(j=0;j<dim;j++){
          if(j==eIndex){continue;}
          double vv=myEqns[j*dim+i];
          for(int k=0;k<dim;k++){myEqns[j*dim+k]-=myEqns[eIndex*dim+k]*vv;}
          myValues[j]-=myValues[eIndex]*vv;
        }
      }
      for(i=0;i<dim;i++){solutions[i]=myValues[index[i]];}
      delete[] index;
      delete[] myValues;
      delete[] myEqns;
      delete[] set;
      return 1;
    }

  }
}
<commit_msg>move the includes out of the namespaces<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2009-2012, Willow Garage, Inc.
 *  Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho,
 *                      Johns Hopkins University
 *
 *  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 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.
 *
 * $Id$
 *
 */

#include <math.h>
#include "pcl/surface/poisson/factor.h"

namespace pcl {
  namespace poisson {

    //////////////////////
    // Polynomial Roots //
    //////////////////////

    int Factor(double a1,double a0,double roots[1][2],const double& EPS){
      if(fabs(a1)<=EPS){return 0;}
      roots[0][0]=-a0/a1;
      roots[0][1]=0;
      return 1;
    }
    int Factor(double a2,double a1,double a0,double roots[2][2],const double& EPS){
      double d;
      if(fabs(a2)<=EPS){return Factor(a1,a0,roots,EPS);}

      d=a1*a1-4*a0*a2;
      a1/=(2*a2);
      if(d<0){
        d=sqrt(-d)/(2*a2);
        roots[0][0]=roots[1][0]=-a1;
        roots[0][1]=-d;
        roots[1][1]= d;
      }
      else{
        d=sqrt(d)/(2*a2);
        roots[0][1]=roots[1][1]=0;
        roots[0][0]=-a1-d;
        roots[1][0]=-a1+d;
      }
      return 2;
    }
    // Solution taken from: http://mathworld.wolfram.com/CubicFormula.html
    // and http://www.csit.fsu.edu/~burkardt/f_src/subpak/subpak.f90
    int Factor(double a3,double a2,double a1,double a0,double roots[3][2],const double& EPS){
      double q,r,r2,q3;

      if(fabs(a3)<=EPS){return Factor(a2,a1,a0,roots,EPS);}
      a2/=a3;
      a1/=a3;
      a0/=a3;

      q=-(3*a1-a2*a2)/9;
      r=-(9*a2*a1-27*a0-2*a2*a2*a2)/54;
      r2=r*r;
      q3=q*q*q;

      if(r2<q3){
        double sqrQ=sqrt(q);
        double theta = acos ( r / (sqrQ*q) );
        double cTheta=cos(theta/3)*sqrQ;
        double sTheta=sin(theta/3)*sqrQ*SQRT_3/2;
        roots[0][1]=roots[1][1]=roots[2][1]=0;
        roots[0][0]=-2*cTheta;
        roots[1][0]=-2*(-cTheta*0.5-sTheta);
        roots[2][0]=-2*(-cTheta*0.5+sTheta);
      }
      else{
        double s1,s2,sqr=sqrt(r2-q3);
        double t;
        t=-r+sqr;
        if(t<0){s1=-pow(-t,1.0/3);}
        else{s1=pow(t,1.0/3);}
        t=-r-sqr;
        if(t<0){s2=-pow(-t,1.0/3);}
        else{s2=pow(t,1.0/3);}
        roots[0][1]=0;
        roots[0][0]=s1+s2;
        s1/=2;
        s2/=2;
        roots[1][0]= roots[2][0]=-s1-s2;
        roots[1][1]= SQRT_3*(s1-s2);
        roots[2][1]=-roots[1][1];
      }
      roots[0][0]-=a2/3;
      roots[1][0]-=a2/3;
      roots[2][0]-=a2/3;
      return 3;
    }
    double ArcTan2(const double& y,const double& x){
      /* This first case should never happen */
      if(y==0 && x==0){return 0;}
      if(x==0){
        if(y>0){return PI/2.0;}
        else{return -PI/2.0;}
      }
      if(x>=0){return atan(y/x);}
      else{
        if(y>=0){return atan(y/x)+PI;}
        else{return atan(y/x)-PI;}
      }
    }
    double Angle(const double in[2]){
      if((in[0]*in[0]+in[1]*in[1])==0.0){return 0;}
      else{return ArcTan2(in[1],in[0]);}
    }
    void Sqrt(const double in[2],double out[2]){
      double r=sqrt(sqrt(in[0]*in[0]+in[1]*in[1]));
      double a=Angle(in)*0.5;
      out[0]=r*cos(a);
      out[1]=r*sin(a);
    }
    void Add(const double in1[2],const double in2[2],double out[2]){
      out[0]=in1[0]+in2[0];
      out[1]=in1[1]+in2[1];
    }
    void Subtract(const double in1[2],const double in2[2],double out[2]){
      out[0]=in1[0]-in2[0];
      out[1]=in1[1]-in2[1];
    }
    void Multiply(const double in1[2],const double in2[2],double out[2]){
      out[0]=in1[0]*in2[0]-in1[1]*in2[1];
      out[1]=in1[0]*in2[1]+in1[1]*in2[0];
    }
    void Divide(const double in1[2],const double in2[2],double out[2]){
      double temp[2];
      double l=in2[0]*in2[0]+in2[1]*in2[1];
      temp[0]= in2[0]/l;
      temp[1]=-in2[1]/l;
      Multiply(in1,temp,out);
    }
    // Solution taken from: http://mathworld.wolfram.com/QuarticEquation.html
    // and http://www.csit.fsu.edu/~burkardt/f_src/subpak/subpak.f90
    int Factor(double a4,double a3,double a2,double a1,double a0,double roots[4][2],const double& EPS){
      double R[2],D[2],E[2],R2[2];

      if(fabs(a4)<EPS){return Factor(a3,a2,a1,a0,roots,EPS);}
      a3/=a4;
      a2/=a4;
      a1/=a4;
      a0/=a4;

      Factor(1.0,-a2,a3*a1-4.0*a0,-a3*a3*a0+4.0*a2*a0-a1*a1,roots,EPS);

      R2[0]=a3*a3/4.0-a2+roots[0][0];
      R2[1]=0;
      Sqrt(R2,R);
      if(fabs(R[0])>10e-8){
        double temp1[2],temp2[2];
        double p1[2],p2[2];

        p1[0]=a3*a3*0.75-2.0*a2-R2[0];
        p1[1]=0;

        temp2[0]=((4.0*a3*a2-8.0*a1-a3*a3*a3)/4.0);
        temp2[1]=0;
        Divide(temp2,R,p2);

        Add     (p1,p2,temp1);
        Subtract(p1,p2,temp2);

        Sqrt(temp1,D);
        Sqrt(temp2,E);
      }
      else{
        R[0]=R[1]=0;
        double temp1[2],temp2[2];
        temp1[0]=roots[0][0]*roots[0][0]-4.0*a0;
        temp1[1]=0;
        Sqrt(temp1,temp2);
        temp1[0]=a3*a3*0.75-2.0*a2+2.0*temp2[0];
        temp1[1]=                  2.0*temp2[1];
        Sqrt(temp1,D);
        temp1[0]=a3*a3*0.75-2.0*a2-2.0*temp2[0];
        temp1[1]=                 -2.0*temp2[1];
        Sqrt(temp1,E);
      }

      roots[0][0]=-a3/4.0+R[0]/2.0+D[0]/2.0;
      roots[0][1]=        R[1]/2.0+D[1]/2.0;

      roots[1][0]=-a3/4.0+R[0]/2.0-D[0]/2.0;
      roots[1][1]=        R[1]/2.0-D[1]/2.0;

      roots[2][0]=-a3/4.0-R[0]/2.0+E[0]/2.0;
      roots[2][1]=       -R[1]/2.0+E[1]/2.0;

      roots[3][0]=-a3/4.0-R[0]/2.0-E[0]/2.0;
      roots[3][1]=       -R[1]/2.0-E[1]/2.0;
      return 4;
    }

    int Solve(const double* eqns,const double* values,double* solutions,const int& dim){
      int i,j,eIndex;
      double v,m;
      int *index=new int[dim];
      int *set=new int[dim];
      double* myEqns=new double[dim*dim];
      double* myValues=new double[dim];

      for(i=0;i<dim*dim;i++){myEqns[i]=eqns[i];}
      for(i=0;i<dim;i++){
        myValues[i]=values[i];
        set[i]=0;
      }
      for(i=0;i<dim;i++){
        // Find the largest equation that has a non-zero entry in the i-th index
        m=-1;
        eIndex=-1;
        for(j=0;j<dim;j++){
          if(set[j]){continue;}
          if(myEqns[j*dim+i]!=0 && fabs(myEqns[j*dim+i])>m){
            m=fabs(myEqns[j*dim+i]);
            eIndex=j;
          }
        }
        if(eIndex==-1){
          delete[] index;
          delete[] myValues;
          delete[] myEqns;
          delete[] set;
          return 0;
        }
        // The position in which the solution for the i-th variable can be found
        index[i]=eIndex;
        set[eIndex]=1;

        // Normalize the equation
        v=myEqns[eIndex*dim+i];
        for(j=0;j<dim;j++){myEqns[eIndex*dim+j]/=v;}
        myValues[eIndex]/=v;

        // Subtract it off from everything else
        for(j=0;j<dim;j++){
          if(j==eIndex){continue;}
          double vv=myEqns[j*dim+i];
          for(int k=0;k<dim;k++){myEqns[j*dim+k]-=myEqns[eIndex*dim+k]*vv;}
          myValues[j]-=myValues[eIndex]*vv;
        }
      }
      for(i=0;i<dim;i++){solutions[i]=myValues[index[i]];}
      delete[] index;
      delete[] myValues;
      delete[] myEqns;
      delete[] set;
      return 1;
    }

  }
}
<|endoftext|>