<commit_before>#include "Core/SurfaceBehavior/SurfaceOptics/TranslucentMicrofacet.h"
#include "Core/Texture/TConstantTexture.h"
#include "Core/Ray.h"
#include "Math/TVector3.h"
#include "Math/Random.h"
#include "Math/constant.h"
#include "Core/SurfaceBehavior/Property/IsoTrowbridgeReitz.h"
#include "Math/math.h"
#include "Core/SurfaceBehavior/Property/SchlickApproxDielectricFresnel.h"
#include "Core/SurfaceBehavior/BsdfHelper.h"
#include "Common/assertion.h"
#include "Core/SidednessAgreement.h"

#include <memory>
#include <iostream>

namespace ph
{

TranslucentMicrofacet::TranslucentMicrofacet(
	const std::shared_ptr<DielectricFresnel>& fresnel,
	const std::shared_ptr<Microfacet>&        microfacet) :

	SurfaceOptics(),

	m_fresnel   (fresnel),
	m_microfacet(microfacet)
{
	PH_ASSERT(fresnel && microfacet);

	m_phenomena.set({ESP::GLOSSY_REFLECTION, ESP::GLOSSY_TRANSMISSION});
	m_numElementals = 2;
}

SurfacePhenomena TranslucentMicrofacet::getPhenomenaOf(const SurfaceElemental elemental) const
{
	switch(elemental)
	{
	case ALL_ELEMENTALS: return m_phenomena;
	case REFLECTION:     return SurfacePhenomena{ESP::GLOSSY_REFLECTION};
	case TRANSMISSION:   return SurfacePhenomena{ESP::GLOSSY_TRANSMISSION};
	default:             return SurfacePhenomena();
	}
}

void TranslucentMicrofacet::calcBsdf(
	const BsdfEvaluation::Input& in,
	BsdfEvaluation::Output&      out,
	const SidednessAgreement&    sidedness) const
{
	const Vector3R& N   = in.X.getShadingNormal();
	const real      NoL = N.dot(in.L);
	const real      NoV = N.dot(in.V);

	// reflection
	if(sidedness.isSameHemisphere(in.X, in.L, in.V) &&
	   (in.elemental == ALL_ELEMENTALS || in.elemental == REFLECTION))
	{
		Vector3R H;
		if(!BsdfHelper::makeHalfVectorSameHemisphere(in.L, in.V, N, &H))
		{
			out.bsdf.setValues(0);
			return;
		}

		const real HoV = H.dot(in.V);
		const real NoH = N.dot(H);
		const real HoL = H.dot(in.L);

		SpectralStrength F;
		m_fresnel->calcReflectance(HoL, &F);

		const real D = m_microfacet->distribution(in.X, N, H);
		const real G = m_microfacet->shadowing(in.X, N, H, in.L, in.V);

		out.bsdf = F.mul(D * G / (4.0_r * std::abs(NoV * NoL)));
	}
	// refraction
	else if(sidedness.isOppositeHemisphere(in.X, in.L, in.V) &&
	        (in.elemental == ALL_ELEMENTALS || in.elemental == TRANSMISSION))
	{
		real etaI = m_fresnel->getIorOuter();
		real etaT = m_fresnel->getIorInner();
		if(NoL < 0.0_r)
		{
			std::swap(etaI, etaT);
		}

		// H should be on the same hemisphere as N
		Vector3R H = in.L.mul(-etaI).add(in.V.mul(-etaT));
		if(H.isZero())
		{
			out.bsdf.setValues(0);
			return;
		}
		H.normalizeLocal();
		if(N.dot(H) < 0.0_r)
		{
			H.mulLocal(-1.0_r);
		}

		const real HoV = H.dot(in.V);
		const real NoH = N.dot(H);
		const real HoL = H.dot(in.L);

		SpectralStrength F;
		m_fresnel->calcTransmittance(HoL, &F);

		const real D = m_microfacet->distribution(in.X, N, H);
		const real G = m_microfacet->shadowing(in.X, N, H, in.L, in.V);

		const real dotTerm = std::abs(HoL * HoV / (NoV * NoL));
		const real iorTerm = etaI / (etaI * HoL + etaT * HoV);
		out.bsdf = F.complement().mul(D * G * dotTerm * (iorTerm * iorTerm));
	}
	else
	{
		out.bsdf.setValues(0);
	}
}

// Cook-Torrance microfacet specular BRDF for translucent surface is:
// |HoL||HoV|/(|NoL||NoV|)*(iorO^2)*(D(H)*F(V, H)*G(L, V, H))/(iorI*HoL+iorO*HoV)^2.
// The importance sampling strategy is to generate a microfacet normal (H) which
// follows D(H)'s distribution, and generate L by reflecting/refracting -V using H.
// The PDF for this sampling scheme is (D(H)*|NoH|)*(iorO^2*|HoV|/((iorI*HoL+iorO*HoV)^2)).
// The reason that the latter multiplier in the PDF exists is because there's a
// jacobian involved (from H's probability space to L's).
//
void TranslucentMicrofacet::calcBsdfSample(
	const BsdfSample::Input&  in,
	BsdfSample::Output&       out,
	const SidednessAgreement& sidedness) const
{
	const bool canReflect  = in.elemental == ALL_ELEMENTALS || in.elemental == REFLECTION;
	const bool canTransmit = in.elemental == ALL_ELEMENTALS || in.elemental == TRANSMISSION;

	if(!canReflect && !canTransmit)
	{
		out.pdfAppliedBsdf.setValues(0);
	}

	const Vector3R& N = in.X.getShadingNormal();

	Vector3R H;
	m_microfacet->genDistributedH(
		in.X,
		Random::genUniformReal_i0_e1(),
		Random::genUniformReal_i0_e1(),
		N, &H);

	SpectralStrength F;
	m_fresnel->calcReflectance(H.dot(in.V), &F);
	const real reflectProb = F.avg();

	bool sampleReflect  = canReflect;
	bool sampleTransmit = canTransmit;

	// we cannot sample both path, choose one randomly
	if(sampleReflect && sampleTransmit)
	{
		const real dart = Random::genUniformReal_i0_e1();
		if(dart < reflectProb)
		{
			sampleTransmit = false;
		}
		else
		{
			sampleReflect = false;
		}
	}

	PH_ASSERT(sampleReflect || sampleTransmit);

	if(sampleReflect)
	{
		// calculate reflected L
		out.L = in.V.mul(-1.0_r).reflect(H).normalizeLocal();
		if(!sidedness.isSameHemisphere(in.X, in.V, out.L))
		{
			return;
		}

		// account for probability
		if(in.elemental == ALL_ELEMENTALS)
		{
			F.divLocal(reflectProb);
		}
	}
	else if(sampleTransmit && m_fresnel->calcRefractDir(in.V, H, &(out.L)))
	{
		if(!sidedness.isOppositeHemisphere(in.X, in.V, out.L))
		{
			return;
		}

		m_fresnel->calcTransmittance(out.L.dot(H), &F);

		// account for probability
		if(in.elemental == ALL_ELEMENTALS)
		{
			F.divLocal(1.0_r - reflectProb);
		}
	}
	else
	{
		// RARE: may be called due to numerical error
		out.pdfAppliedBsdf.setValues(0);
		return;
	}

	const Vector3R& L = out.L;

	const real NoL = N.dot(L);
	const real HoL = H.dot(L);
	const real NoV = N.dot(in.V);
	const real NoH = N.dot(H);

	const real G        = m_microfacet->shadowing(in.X, N, H, L, in.V);
	const real dotTerms = std::abs(HoL / (NoV * NoL * NoH));
	out.pdfAppliedBsdf.setValues(F.mul(G * dotTerms));
}

void TranslucentMicrofacet::calcBsdfSamplePdfW(
	const BsdfPdfQuery::Input& in,
	BsdfPdfQuery::Output&      out,
	const SidednessAgreement&  sidedness) const
{
	const bool canReflect  = in.elemental == ALL_ELEMENTALS || in.elemental == REFLECTION;
	const bool canTransmit = in.elemental == ALL_ELEMENTALS || in.elemental == TRANSMISSION;

	const Vector3R& N = in.X.getShadingNormal();

	// reflection
	if(canReflect && sidedness.isSameHemisphere(in.X, in.L, in.V))
	{
		Vector3R H;
		if(!BsdfHelper::makeHalfVectorSameHemisphere(in.L, in.V, N, &H))
		{
			out.sampleDirPdfW = 0;
			return;
		}

		const real NoH = N.dot(H);
		const real HoL = H.dot(in.L);
		const real HoV = H.dot(in.V);
		const real D   = m_microfacet->distribution(in.X, N, H);

		SpectralStrength F;
		m_fresnel->calcReflectance(HoL, &F);
		const real reflectProb = in.elemental == ALL_ELEMENTALS ? F.avg() : 1.0_r;

		out.sampleDirPdfW = std::abs(D * NoH / (4.0_r * HoL)) * reflectProb;
	}
	// transmission
	else if(canTransmit && sidedness.isOppositeHemisphere(in.X, in.L, in.V))
	{
		const real NoV = N.dot(in.V);
		const real NoL = N.dot(in.L);

		real etaI = m_fresnel->getIorOuter();
		real etaT = m_fresnel->getIorInner();
		if(NoL < 0.0_r)
		{
			std::swap(etaI, etaT);
		}

		// here H will point into the medium with lower IoR
		// (see: B. Walter et al., Microfacet Models for Refraction, near the end of P.5)
		Vector3R H = in.L.mul(-etaI).add(in.V.mul(-etaT));
		if(H.isZero())
		{
			out.sampleDirPdfW = 0;
			return;
		}
		H.normalizeLocal();

		// make H in N's hemisphere
		if(N.dot(H) < 0.0_r)
		{
			H.mulLocal(-1.0_r);
		}

		const real HoV = H.dot(in.V);
		const real NoH = N.dot(H);
		const real HoL = H.dot(in.L);
		const real D   = m_microfacet->distribution(in.X, N, H);

		SpectralStrength F;
		m_fresnel->calcReflectance(HoL, &F);
		const real refractProb = in.elemental == ALL_ELEMENTALS ? 1.0_r - F.avg() : 1.0_r;

		const real iorTerm    = etaI * HoL + etaT * HoV;
		const real multiplier = (etaI * etaI * HoL) / (iorTerm * iorTerm);

		out.sampleDirPdfW = std::abs(D * NoH * multiplier) * refractProb;
	}
	else
	{
		out.sampleDirPdfW = 0.0_r;
	}
}

}// end namespace ph<commit_msg>[bugfix] corrected microfacet BTDF<commit_after>#include "Core/SurfaceBehavior/SurfaceOptics/TranslucentMicrofacet.h"
#include "Core/Texture/TConstantTexture.h"
#include "Core/Ray.h"
#include "Math/TVector3.h"
#include "Math/Random.h"
#include "Math/constant.h"
#include "Core/SurfaceBehavior/Property/IsoTrowbridgeReitz.h"
#include "Math/math.h"
#include "Core/SurfaceBehavior/Property/SchlickApproxDielectricFresnel.h"
#include "Core/SurfaceBehavior/BsdfHelper.h"
#include "Common/assertion.h"
#include "Core/SidednessAgreement.h"

#include <memory>
#include <iostream>

namespace ph
{

TranslucentMicrofacet::TranslucentMicrofacet(
	const std::shared_ptr<DielectricFresnel>& fresnel,
	const std::shared_ptr<Microfacet>&        microfacet) :

	SurfaceOptics(),

	m_fresnel   (fresnel),
	m_microfacet(microfacet)
{
	PH_ASSERT(fresnel && microfacet);

	m_phenomena.set({ESP::GLOSSY_REFLECTION, ESP::GLOSSY_TRANSMISSION});
	m_numElementals = 2;
}

SurfacePhenomena TranslucentMicrofacet::getPhenomenaOf(const SurfaceElemental elemental) const
{
	switch(elemental)
	{
	case ALL_ELEMENTALS: return m_phenomena;
	case REFLECTION:     return SurfacePhenomena{ESP::GLOSSY_REFLECTION};
	case TRANSMISSION:   return SurfacePhenomena{ESP::GLOSSY_TRANSMISSION};
	default:             return SurfacePhenomena();
	}
}

void TranslucentMicrofacet::calcBsdf(
	const BsdfEvaluation::Input& in,
	BsdfEvaluation::Output&      out,
	const SidednessAgreement&    sidedness) const
{
	const Vector3R& N   = in.X.getShadingNormal();
	const real      NoL = N.dot(in.L);
	const real      NoV = N.dot(in.V);

	// reflection
	if(sidedness.isSameHemisphere(in.X, in.L, in.V) &&
	   (in.elemental == ALL_ELEMENTALS || in.elemental == REFLECTION))
	{
		Vector3R H;
		if(!BsdfHelper::makeHalfVectorSameHemisphere(in.L, in.V, N, &H))
		{
			out.bsdf.setValues(0);
			return;
		}

		const real HoV = H.dot(in.V);
		const real NoH = N.dot(H);
		const real HoL = H.dot(in.L);

		SpectralStrength F;
		m_fresnel->calcReflectance(HoL, &F);

		const real D = m_microfacet->distribution(in.X, N, H);
		const real G = m_microfacet->shadowing(in.X, N, H, in.L, in.V);

		out.bsdf = F.mul(D * G / (4.0_r * std::abs(NoV * NoL)));
	}
	// refraction
	else if(sidedness.isOppositeHemisphere(in.X, in.L, in.V) &&
	        (in.elemental == ALL_ELEMENTALS || in.elemental == TRANSMISSION))
	{
		real etaI = m_fresnel->getIorOuter();
		real etaT = m_fresnel->getIorInner();
		if(NoL < 0.0_r)
		{
			std::swap(etaI, etaT);
		}

		// H should be on the same hemisphere as N
		Vector3R H = in.L.mul(-etaI).add(in.V.mul(-etaT));
		if(H.isZero())
		{
			out.bsdf.setValues(0);
			return;
		}
		H.normalizeLocal();
		if(N.dot(H) < 0.0_r)
		{
			H.mulLocal(-1.0_r);
		}

		const real HoV = H.dot(in.V);
		const real NoH = N.dot(H);
		const real HoL = H.dot(in.L);

		SpectralStrength F;
		m_fresnel->calcTransmittance(HoL, &F);

		const real D = m_microfacet->distribution(in.X, N, H);
		const real G = m_microfacet->shadowing(in.X, N, H, in.L, in.V);

		const real dotTerm = std::abs(HoL * HoV / (NoV * NoL));
		const real iorTerm = etaT / (etaI * HoL + etaT * HoV);
		out.bsdf = F.complement().mul(D * G * dotTerm * (iorTerm * iorTerm));
	}
	else
	{
		out.bsdf.setValues(0);
	}
}

// Cook-Torrance microfacet specular BRDF for translucent surface is:
// |HoL||HoV|/(|NoL||NoV|)*(iorO^2)*(D(H)*F(V, H)*G(L, V, H))/(iorI*HoL+iorO*HoV)^2.
// The importance sampling strategy is to generate a microfacet normal (H) which
// follows D(H)'s distribution, and generate L by reflecting/refracting -V using H.
// The PDF for this sampling scheme is (D(H)*|NoH|)*(iorO^2*|HoV|/((iorI*HoL+iorO*HoV)^2)).
// The reason that the latter multiplier in the PDF exists is because there's a
// jacobian involved (from H's probability space to L's).
//
void TranslucentMicrofacet::calcBsdfSample(
	const BsdfSample::Input&  in,
	BsdfSample::Output&       out,
	const SidednessAgreement& sidedness) const
{
	const bool canReflect  = in.elemental == ALL_ELEMENTALS || in.elemental == REFLECTION;
	const bool canTransmit = in.elemental == ALL_ELEMENTALS || in.elemental == TRANSMISSION;

	if(!canReflect && !canTransmit)
	{
		out.pdfAppliedBsdf.setValues(0);
	}

	const Vector3R& N = in.X.getShadingNormal();

	Vector3R H;
	m_microfacet->genDistributedH(
		in.X,
		Random::genUniformReal_i0_e1(),
		Random::genUniformReal_i0_e1(),
		N, &H);

	SpectralStrength F;
	m_fresnel->calcReflectance(H.dot(in.V), &F);
	const real reflectProb = F.avg();

	bool sampleReflect  = canReflect;
	bool sampleTransmit = canTransmit;

	// we cannot sample both path, choose one randomly
	if(sampleReflect && sampleTransmit)
	{
		const real dart = Random::genUniformReal_i0_e1();
		if(dart < reflectProb)
		{
			sampleTransmit = false;
		}
		else
		{
			sampleReflect = false;
		}
	}

	PH_ASSERT(sampleReflect || sampleTransmit);

	if(sampleReflect)
	{
		// calculate reflected L
		out.L = in.V.mul(-1.0_r).reflect(H).normalizeLocal();
		if(!sidedness.isSameHemisphere(in.X, in.V, out.L))
		{
			return;
		}

		// account for probability
		if(in.elemental == ALL_ELEMENTALS)
		{
			F.divLocal(reflectProb);
		}
	}
	else if(sampleTransmit && m_fresnel->calcRefractDir(in.V, H, &(out.L)))
	{
		if(!sidedness.isOppositeHemisphere(in.X, in.V, out.L))
		{
			return;
		}

		m_fresnel->calcTransmittance(H.dot(out.L), &F);

		real etaI = m_fresnel->getIorOuter();
		real etaT = m_fresnel->getIorInner();
		if(N.dot(out.L) < 0.0_r)
		{
			std::swap(etaI, etaT);
		}
		F.mulLocal(etaT * etaT / (etaI * etaI));

		// account for probability
		if(in.elemental == ALL_ELEMENTALS)
		{
			F.divLocal(1.0_r - reflectProb);
		}
	}
	else
	{
		// RARE: may be called due to numerical error
		out.pdfAppliedBsdf.setValues(0);
		return;
	}

	const Vector3R& L = out.L;

	const real NoL = N.dot(L);
	const real HoV = H.dot(in.V);
	const real NoV = N.dot(in.V);
	const real NoH = N.dot(H);

	const real G        = m_microfacet->shadowing(in.X, N, H, L, in.V);
	const real dotTerms = std::abs(HoV / (NoV * NoL * NoH));
	out.pdfAppliedBsdf.setValues(F.mul(G * dotTerms));
}

void TranslucentMicrofacet::calcBsdfSamplePdfW(
	const BsdfPdfQuery::Input& in,
	BsdfPdfQuery::Output&      out,
	const SidednessAgreement&  sidedness) const
{
	const bool canReflect  = in.elemental == ALL_ELEMENTALS || in.elemental == REFLECTION;
	const bool canTransmit = in.elemental == ALL_ELEMENTALS || in.elemental == TRANSMISSION;

	const Vector3R& N = in.X.getShadingNormal();

	// reflection
	if(canReflect && sidedness.isSameHemisphere(in.X, in.L, in.V))
	{
		Vector3R H;
		if(!BsdfHelper::makeHalfVectorSameHemisphere(in.L, in.V, N, &H))
		{
			out.sampleDirPdfW = 0;
			return;
		}

		const real NoH = N.dot(H);
		const real HoL = H.dot(in.L);
		const real HoV = H.dot(in.V);
		const real D   = m_microfacet->distribution(in.X, N, H);

		SpectralStrength F;
		m_fresnel->calcReflectance(HoL, &F);
		const real reflectProb = in.elemental == ALL_ELEMENTALS ? F.avg() : 1.0_r;

		out.sampleDirPdfW = std::abs(D * NoH / (4.0_r * HoL)) * reflectProb;
	}
	// transmission
	else if(canTransmit && sidedness.isOppositeHemisphere(in.X, in.L, in.V))
	{
		const real NoV = N.dot(in.V);
		const real NoL = N.dot(in.L);

		real etaI = m_fresnel->getIorOuter();
		real etaT = m_fresnel->getIorInner();
		if(NoL < 0.0_r)
		{
			std::swap(etaI, etaT);
		}

		// here H will point into the medium with lower IoR
		// (see: B. Walter et al., Microfacet Models for Refraction, near the end of P.5)
		Vector3R H = in.L.mul(-etaI).add(in.V.mul(-etaT));
		if(H.isZero())
		{
			out.sampleDirPdfW = 0;
			return;
		}
		H.normalizeLocal();

		// make H in N's hemisphere
		if(N.dot(H) < 0.0_r)
		{
			H.mulLocal(-1.0_r);
		}

		const real HoV = H.dot(in.V);
		const real NoH = N.dot(H);
		const real HoL = H.dot(in.L);
		const real D   = m_microfacet->distribution(in.X, N, H);

		SpectralStrength F;
		m_fresnel->calcReflectance(HoL, &F);
		const real refractProb = in.elemental == ALL_ELEMENTALS ? 1.0_r - F.avg() : 1.0_r;

		const real iorTerm    = etaI * HoL + etaT * HoV;
		const real multiplier = (etaI * etaI * HoL) / (iorTerm * iorTerm);

		out.sampleDirPdfW = std::abs(D * NoH * multiplier) * refractProb;
	}
	else
	{
		out.sampleDirPdfW = 0.0_r;
	}
}

}// end namespace ph<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkDiffusionFunctionCollection.h"
#include <math.h>
#include "mitkVector.h"

// for Windows
#ifndef M_PI
#define M_PI  3.14159265358979323846
#endif

// Namespace ::SH
#include <boost/math/special_functions/legendre.hpp>
#include <boost/math/special_functions/spherical_harmonic.hpp>
#include <boost/version.hpp>

// Namespace ::Gradients
#include "itkVectorContainer.h"
#include "vnl/vnl_vector.h"

//------------------------- SH-function ------------------------------------

double mitk::sh::factorial(int number) {
  if(number <= 1) return 1;
  double result = 1.0;
  for(int i=1; i<=number; i++)
    result *= i;
  return result;
}

void mitk::sh::Cart2Sph(double x, double y, double z, double *cart)
{
  double phi, th, rad;
  rad = sqrt(x*x+y*y+z*z);
  if( rad < mitk::eps )
  {
    th = M_PI/2;
    phi = M_PI/2;
  }
  else
  {
    th = acos(z/rad);
    phi = atan2(y, x);
  }
  cart[0] = phi;
  cart[1] = th;
  cart[2] = rad;
}

double mitk::sh::legendre0(int l)
{
  if( l%2 != 0 )
  {
    return 0;
  }
  else
  {
    double prod1 = 1.0;
    for(int i=1;i<l;i+=2) prod1 *= i;
    double prod2 = 1.0;
    for(int i=2;i<=l;i+=2) prod2 *= i;
    return pow(-1.0,l/2.0)*(prod1/prod2);
  }
}

double mitk::sh::Yj(int m, int l, double theta, double phi)
{
  if (m<0)
    return sqrt(2.0)*::boost::math::spherical_harmonic_r(l, -m, theta, phi);
  else if (m==0)
    return ::boost::math::spherical_harmonic_r(l, m, theta, phi);
  else
    return pow(-1.0,m)*sqrt(2.0)*::boost::math::spherical_harmonic_i(l, m, theta, phi);

  return 0;
}

//------------------------- gradients-function ------------------------------------

std::vector<unsigned int> mitk::gradients::GetAllUniqueDirections(const BValueMap & refBValueMap, GradientDirectionContainerType *refGradientsContainer )
{

  IndiciesVector directioncontainer;
  BValueMap::const_iterator mapIterator = refBValueMap.begin();

  if(refBValueMap.find(0) != refBValueMap.end() && refBValueMap.size() > 1)
    mapIterator++; //skip bzero Values

  for( ; mapIterator != refBValueMap.end(); mapIterator++){

    IndiciesVector currentShell = mapIterator->second;

    while(currentShell.size()>0)
    {
      unsigned int wntIndex = currentShell.back();
      currentShell.pop_back();

      IndiciesVector::iterator containerIt = directioncontainer.begin();
      bool directionExist = false;
      while(containerIt != directioncontainer.end())
      {
        if (fabs(dot(refGradientsContainer->ElementAt(*containerIt), refGradientsContainer->ElementAt(wntIndex)))  > 0.9998)
        {
          directionExist = true;
          break;
        }
        containerIt++;
      }
      if(!directionExist)
      {
        directioncontainer.push_back(wntIndex);
      }
    }
  }

  return directioncontainer;
}

bool mitk::gradients::CheckForDifferingShellDirections(const BValueMap & refBValueMap, GradientDirectionContainerType::ConstPointer refGradientsContainer)
{
  BValueMap::const_iterator mapIterator = refBValueMap.begin();

  if(refBValueMap.find(0) != refBValueMap.end() && refBValueMap.size() > 1)
    mapIterator++; //skip bzero Values

  for( ; mapIterator != refBValueMap.end(); mapIterator++){

    BValueMap::const_iterator mapIterator_2 = refBValueMap.begin();
    if(refBValueMap.find(0) != refBValueMap.end() && refBValueMap.size() > 1)
      mapIterator_2++; //skip bzero Values

    for( ; mapIterator_2 != refBValueMap.end(); mapIterator_2++){

      if(mapIterator_2 == mapIterator) continue;

      IndiciesVector currentShell = mapIterator->second;
      IndiciesVector testShell = mapIterator_2->second;
      for (unsigned int i = 0; i< currentShell.size(); i++)
        if (fabs(dot(refGradientsContainer->ElementAt(currentShell[i]), refGradientsContainer->ElementAt(testShell[i])))  <= 0.9998) { return true; }

    }
  }
  return false;
}

template<typename type>
double mitk::gradients::dot (vnl_vector_fixed< type ,3> const& v1, vnl_vector_fixed< type ,3 > const& v2 )
{
  double result = (v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]) / (v1.two_norm() * v2.two_norm());
  return result ;
}

vnl_matrix<double> mitk::gradients::ComputeSphericalFromCartesian(const IndiciesVector & refShell, const GradientDirectionContainerType * refGradientsContainer)
{

  vnl_matrix<double> Q(3, refShell.size());

  for(unsigned int i = 0; i < refShell.size(); i++)
  {
    GradientDirectionType dir = refGradientsContainer->ElementAt(refShell[i]);
    double x = dir.normalize().get(0);
    double y = dir.normalize().get(1);
    double z = dir.normalize().get(2);
    double cart[3];
    mitk::sh::Cart2Sph(x,y,z,cart);
    Q(0,i) = cart[0];
    Q(1,i) = cart[1];
    Q(2,i) = cart[2];
  }
  return Q;
}

vnl_matrix<double> mitk::gradients::ComputeSphericalHarmonicsBasis(const vnl_matrix<double> & QBallReference, const unsigned int & LOrder)
{
  vnl_matrix<double> SHBasisOutput(QBallReference.cols(), (LOrder+1)*(LOrder+2)*0.5);
  for(unsigned int i=0; i< SHBasisOutput.rows(); i++)
    for(unsigned int k = 0; k <= LOrder; k += 2)
      for(unsigned int m =- k; m <= k; m++)
      {
        int j = ( k * k + k + 2 ) / 2 + m - 1;
        double phi = QBallReference(0,i);
        double th = QBallReference(1,i);
        SHBasisOutput(i,j) = mitk::sh::Yj(m,k,th,phi);
      }
  return SHBasisOutput;
}

mitk::gradients::GradientDirectionContainerType::Pointer mitk::gradients::CreateNormalizedUniqueGradientDirectionContainer(const mitk::gradients::BValueMap & bValueMap,
    const GradientDirectionContainerType *origninalGradentcontainer)
{
  mitk::gradients::GradientDirectionContainerType::Pointer directioncontainer = mitk::gradients::GradientDirectionContainerType::New();
  BValueMap::const_iterator mapIterator = bValueMap.begin();

  if(bValueMap.find(0) != bValueMap.end() && bValueMap.size() > 1){
    mapIterator++; //skip bzero Values
    vnl_vector_fixed<double, 3> vec;
    vec.fill(0.0);
    directioncontainer->push_back(vec);
  }

  for( ; mapIterator != bValueMap.end(); mapIterator++){

    IndiciesVector currentShell = mapIterator->second;

    while(currentShell.size()>0)
    {
      unsigned int wntIndex = currentShell.back();
      currentShell.pop_back();

      mitk::gradients::GradientDirectionContainerType::Iterator containerIt = directioncontainer->Begin();
      bool directionExist = false;
      while(containerIt != directioncontainer->End())
      {
        if (fabs(dot(containerIt.Value(), origninalGradentcontainer->ElementAt(wntIndex)))  > 0.9998)
        {
          directionExist = true;
          break;
        }
        containerIt++;
      }
      if(!directionExist)
      {
        GradientDirectionType dir(origninalGradentcontainer->ElementAt(wntIndex));
        directioncontainer->push_back(dir.normalize());
      }
    }
  }

  return directioncontainer;
}
<commit_msg>unsigned int comparison warning killed a minus sign<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkDiffusionFunctionCollection.h"
#include <math.h>
#include "mitkVector.h"

// for Windows
#ifndef M_PI
#define M_PI  3.14159265358979323846
#endif

// Namespace ::SH
#include <boost/math/special_functions/legendre.hpp>
#include <boost/math/special_functions/spherical_harmonic.hpp>
#include <boost/version.hpp>

// Namespace ::Gradients
#include "itkVectorContainer.h"
#include "vnl/vnl_vector.h"

//------------------------- SH-function ------------------------------------

double mitk::sh::factorial(int number) {
  if(number <= 1) return 1;
  double result = 1.0;
  for(int i=1; i<=number; i++)
    result *= i;
  return result;
}

void mitk::sh::Cart2Sph(double x, double y, double z, double *cart)
{
  double phi, th, rad;
  rad = sqrt(x*x+y*y+z*z);
  if( rad < mitk::eps )
  {
    th = M_PI/2;
    phi = M_PI/2;
  }
  else
  {
    th = acos(z/rad);
    phi = atan2(y, x);
  }
  cart[0] = phi;
  cart[1] = th;
  cart[2] = rad;
}

double mitk::sh::legendre0(int l)
{
  if( l%2 != 0 )
  {
    return 0;
  }
  else
  {
    double prod1 = 1.0;
    for(int i=1;i<l;i+=2) prod1 *= i;
    double prod2 = 1.0;
    for(int i=2;i<=l;i+=2) prod2 *= i;
    return pow(-1.0,l/2.0)*(prod1/prod2);
  }
}

double mitk::sh::Yj(int m, int l, double theta, double phi)
{
  if (m<0)
    return sqrt(2.0)*::boost::math::spherical_harmonic_r(l, -m, theta, phi);
  else if (m==0)
    return ::boost::math::spherical_harmonic_r(l, m, theta, phi);
  else
    return pow(-1.0,m)*sqrt(2.0)*::boost::math::spherical_harmonic_i(l, m, theta, phi);

  return 0;
}

//------------------------- gradients-function ------------------------------------

std::vector<unsigned int> mitk::gradients::GetAllUniqueDirections(const BValueMap & refBValueMap, GradientDirectionContainerType *refGradientsContainer )
{

  IndiciesVector directioncontainer;
  BValueMap::const_iterator mapIterator = refBValueMap.begin();

  if(refBValueMap.find(0) != refBValueMap.end() && refBValueMap.size() > 1)
    mapIterator++; //skip bzero Values

  for( ; mapIterator != refBValueMap.end(); mapIterator++){

    IndiciesVector currentShell = mapIterator->second;

    while(currentShell.size()>0)
    {
      unsigned int wntIndex = currentShell.back();
      currentShell.pop_back();

      IndiciesVector::iterator containerIt = directioncontainer.begin();
      bool directionExist = false;
      while(containerIt != directioncontainer.end())
      {
        if (fabs(dot(refGradientsContainer->ElementAt(*containerIt), refGradientsContainer->ElementAt(wntIndex)))  > 0.9998)
        {
          directionExist = true;
          break;
        }
        containerIt++;
      }
      if(!directionExist)
      {
        directioncontainer.push_back(wntIndex);
      }
    }
  }

  return directioncontainer;
}

bool mitk::gradients::CheckForDifferingShellDirections(const BValueMap & refBValueMap, GradientDirectionContainerType::ConstPointer refGradientsContainer)
{
  BValueMap::const_iterator mapIterator = refBValueMap.begin();

  if(refBValueMap.find(0) != refBValueMap.end() && refBValueMap.size() > 1)
    mapIterator++; //skip bzero Values

  for( ; mapIterator != refBValueMap.end(); mapIterator++){

    BValueMap::const_iterator mapIterator_2 = refBValueMap.begin();
    if(refBValueMap.find(0) != refBValueMap.end() && refBValueMap.size() > 1)
      mapIterator_2++; //skip bzero Values

    for( ; mapIterator_2 != refBValueMap.end(); mapIterator_2++){

      if(mapIterator_2 == mapIterator) continue;

      IndiciesVector currentShell = mapIterator->second;
      IndiciesVector testShell = mapIterator_2->second;
      for (unsigned int i = 0; i< currentShell.size(); i++)
        if (fabs(dot(refGradientsContainer->ElementAt(currentShell[i]), refGradientsContainer->ElementAt(testShell[i])))  <= 0.9998) { return true; }

    }
  }
  return false;
}

template<typename type>
double mitk::gradients::dot (vnl_vector_fixed< type ,3> const& v1, vnl_vector_fixed< type ,3 > const& v2 )
{
  double result = (v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]) / (v1.two_norm() * v2.two_norm());
  return result ;
}

vnl_matrix<double> mitk::gradients::ComputeSphericalFromCartesian(const IndiciesVector & refShell, const GradientDirectionContainerType * refGradientsContainer)
{

  vnl_matrix<double> Q(3, refShell.size());
  Q.fill(0.0);

  for(unsigned int i = 0; i < refShell.size(); i++)
  {
    GradientDirectionType dir = refGradientsContainer->ElementAt(refShell[i]);
    double x = dir.normalize().get(0);
    double y = dir.normalize().get(1);
    double z = dir.normalize().get(2);
    double cart[3];
    mitk::sh::Cart2Sph(x,y,z,cart);
    Q(0,i) = cart[0];
    Q(1,i) = cart[1];
    Q(2,i) = cart[2];
  }
  return Q;
}

vnl_matrix<double> mitk::gradients::ComputeSphericalHarmonicsBasis(const vnl_matrix<double> & QBallReference, const unsigned int & LOrder)
{
  vnl_matrix<double> SHBasisOutput(QBallReference.cols(), (LOrder+1)*(LOrder+2)*0.5);
  SHBasisOutput.fill(0.0);
  for(int i=0; i< (int)SHBasisOutput.rows(); i++)
    for(int k = 0; k <= (int)LOrder; k += 2)
      for(int m =- k; m <= k; m++)
      {
        int j = ( k * k + k + 2 ) / 2.0 + m - 1;
        double phi = QBallReference(0,i);
        double th = QBallReference(1,i);
        double val = mitk::sh::Yj(m,k,th,phi);
        SHBasisOutput(i,j) = val;
      }
  return SHBasisOutput;
}

mitk::gradients::GradientDirectionContainerType::Pointer mitk::gradients::CreateNormalizedUniqueGradientDirectionContainer(const mitk::gradients::BValueMap & bValueMap,
    const GradientDirectionContainerType *origninalGradentcontainer)
{
  mitk::gradients::GradientDirectionContainerType::Pointer directioncontainer = mitk::gradients::GradientDirectionContainerType::New();
  BValueMap::const_iterator mapIterator = bValueMap.begin();

  if(bValueMap.find(0) != bValueMap.end() && bValueMap.size() > 1){
    mapIterator++; //skip bzero Values
    vnl_vector_fixed<double, 3> vec;
    vec.fill(0.0);
    directioncontainer->push_back(vec);
  }

  for( ; mapIterator != bValueMap.end(); mapIterator++){

    IndiciesVector currentShell = mapIterator->second;

    while(currentShell.size()>0)
    {
      unsigned int wntIndex = currentShell.back();
      currentShell.pop_back();

      mitk::gradients::GradientDirectionContainerType::Iterator containerIt = directioncontainer->Begin();
      bool directionExist = false;
      while(containerIt != directioncontainer->End())
      {
        if (fabs(dot(containerIt.Value(), origninalGradentcontainer->ElementAt(wntIndex)))  > 0.9998)
        {
          directionExist = true;
          break;
        }
        containerIt++;
      }
      if(!directionExist)
      {
        GradientDirectionType dir(origninalGradentcontainer->ElementAt(wntIndex));
        directioncontainer->push_back(dir.normalize());
      }
    }
  }

  return directioncontainer;
}
<|endoftext|>


<commit_before>#include "stdsneezy.h"
#include "database.h"
#include "lowtools.h"
#include <unistd.h>

int txt2dir(sstring txt)
{
  for(int i=0;strcmp(dirs[i], "\n");++i){
    if(txt==dirs[i]){
      return i;
    }
  }
  return convertTo<int>(txt);
}

int main(int argc, char **argv)
{
  TDatabase db(DB_SNEEZYBETA);
  vector<int>vnums;
  map<sstring,sstring>val;
  char file[]="/tmp/sqledwldXXXXXX";
  FILE *tmpfile;
  sstring buf, sbuf;
  int answer;

  toggleInfo.loadToggles();
  if(argc<=1){
    printf("Usage: sqledwld <vnum list>\n");
    printf("Example: sqledwld 13700-13780 13791 13798\n");
    exit(0);
  }

  if(!parse_num_args(argc-1, argv+1, vnums))
    exit(0);

  for(unsigned int i=0;i<vnums.size();++i){
    printf("Fetching data for room %i\n", vnums[i]);

    db.query("select * from room where vnum=%i", vnums[i]);
    if(db.fetchRow()){
      buf = fmt("- room\n"); sbuf+=buf;
      buf = fmt("vnum: %s\n") % db["vnum"];  sbuf+=buf;
      buf = fmt("x:    %s\n") % db["x"];  sbuf+=buf;
      buf = fmt("y:    %s\n") % db["y"];  sbuf+=buf;
      buf = fmt("z:    %s\n") % db["z"];  sbuf+=buf;
      buf = fmt("name: %s\n") % db["name"];  sbuf+=buf;
      buf = fmt("description~:\n%s~\n") % db["description"];  sbuf+=buf;
      buf = fmt("room_flag: %s\n") % db["room_flag"];  sbuf+=buf;
      buf = fmt("sector:    %s\n") % db["sector"];  sbuf+=buf;
      buf = fmt("teletime:  %s\n") % db["teletime"];  sbuf+=buf;
      buf = fmt("teletarg:  %s\n") % db["teletarg"];  sbuf+=buf;
      buf = fmt("telelook:  %s\n") % db["telelook"];  sbuf+=buf;
      buf = fmt("river_speed: %s\n") % db["river_speed"];  sbuf+=buf;
      buf = fmt("river_dir: %s\n") % db["river_dir"];  sbuf+=buf;
      buf = fmt("capacity:  %s\n") % db["capacity"];  sbuf+=buf;
      buf = fmt("height:    %s\n") % db["height"];  sbuf+=buf;
      buf = fmt("\n"); sbuf+=buf;
    }

    db.query("select * from roomextra where vnum=%i", vnums[i]);
    while(db.fetchRow()){
      buf = fmt("- roomextra\n"); sbuf+=buf;
      buf = fmt("vnum: %s\n") % db["vnum"];  sbuf+=buf;
      buf = fmt("name: %s\n") % db["name"];  sbuf+=buf;
      buf = fmt("description~:\n%s~\n") % db["description"];  sbuf+=buf;
      buf = fmt("\n"); sbuf+=buf;
    }

    db.query("select * from roomexit where vnum=%i", vnums[i]);
    while(db.fetchRow()){
      buf = fmt("- roomexit\n"); sbuf+=buf;
      buf = fmt("vnum:      %s\n") % db["vnum"];  sbuf+=buf;
      buf = fmt("direction: %s\n") % dirs[convertTo<int>(db["direction"])];
      sbuf+=buf;
      buf = fmt("name:      %s\n") % db["name"];  sbuf+=buf;
      buf = fmt("description~:\n%s~\n") % db["description"];  sbuf+=buf;
      buf = fmt("type:      %s\n") % db["type"];  sbuf+=buf;
      buf = fmt("condition_flag: %s\n") % db["condition_flag"]; sbuf+=buf;
      buf = fmt("lock_difficulty: %s\n") % db["lock_difficulty"]; sbuf+=buf;
      buf = fmt("weight:    %s\n") % db["weight"];  sbuf+=buf;
      buf = fmt("key_num:   %s\n") % db["key_num"];  sbuf+=buf;
      buf = fmt("destination:      %s\n") % db["destination"];  sbuf+=buf;
      buf = fmt("\n"); sbuf+=buf;
    }
  }

  mkstemp(file);
  tmpfile=fopen(file, "w");
  fprintf(tmpfile, "%s", sbuf.c_str());
  fclose(tmpfile);

  printf("Opening editor.\n");
  buf = fmt("$EDITOR %s") % file;
  system(buf.c_str());

  printf("Insert room%s? [y/n] ", vnums.size()>1?"s":"");
  while(1){
    answer=getc(stdin);
    if(answer=='n'){
      printf("Room%s not inserted.\n", vnums.size()>1?"s":"");
      unlink(file);
      exit(0);
    } else if(answer=='y'){
      break;
    } else {
      printf("Insert room%s? [y/n] ", vnums.size()>1?"s":"");
    }
  }

  buf = fmt("/bin/cp -f %s %s.backup") % file % file;
  system(buf.c_str());

  int i=0;

  while(++i){
    val=parse_data_file(file, i);
    if(val["vnum"]=="EOM")
      break;

    if(val["DATATYPE"]=="room"){
      printf("replacing room %s\n", val["vnum"].c_str());
      db.query("delete from room where vnum=%s",
	       val["vnum"].c_str());
      db.query("delete from roomextra where vnum=%s",
	       val["vnum"].c_str());
      db.query("delete from roomexit where vnum=%s",
	       val["vnum"].c_str());

      db.query("insert into room (vnum,x,y,z,name,description,room_flag,sector,teletime,teletarg,telelook,river_speed,river_dir,capacity,height,zone) values (%s,%s,%s,%s,'%s','%s',%s,%s,%s,%s,%s,%s,%s,%s,%s,-1)",
	       val["vnum"].c_str(),val["x"].c_str(),val["y"].c_str(),val["z"].c_str(),val["name"].c_str(),val["description"].c_str(),val["room_flag"].c_str(),val["sector"].c_str(),val["teletime"].c_str(),val["teletarg"].c_str(),val["telelook"].c_str(),val["river_speed"].c_str(),val["river_dir"].c_str(),val["capacity"].c_str(),val["height"].c_str());
    } else if(val["DATATYPE"]=="roomextra"){
      printf("replacing roomextra %s\n", val["vnum"].c_str());

      db.query("insert into roomextra (vnum, name, description) values (%s,'%s','%s')", val["vnum"].c_str(), val["name"].c_str(), val["description"].c_str());

    } else if(val["DATATYPE"]=="roomexit"){
      printf("replacing roomexit %s\n", val["vnum"].c_str());

      db.query("insert into roomexit (vnum,direction,name,description,type,condition_flag,lock_difficulty,weight,key_num,destination) values (%s,%i,'%s','%s',%s,%s,%s,%s,%s,%s)",
	       val["vnum"].c_str(),txt2dir(val["direction"]),val["name"].c_str(),val["description"].c_str(),val["type"].c_str(),val["condition_flag"].c_str(),val["lock_difficulty"].c_str(),val["weight"].c_str(),val["key_num"].c_str(),val["destination"].c_str());
    }
    printf("\n");

  }

  unlink(file);

  printf("Done.\n\r");
  printf("Your backup file is %s.backup\n", file);
}
<commit_msg>added spec editing<commit_after>#include "stdsneezy.h"
#include "database.h"
#include "lowtools.h"
#include <unistd.h>

int txt2dir(sstring txt)
{
  for(int i=0;strcmp(dirs[i], "\n");++i){
    if(txt==dirs[i]){
      return i;
    }
  }
  return convertTo<int>(txt);
}

int main(int argc, char **argv)
{
  TDatabase db(DB_SNEEZYBETA);
  vector<int>vnums;
  map<sstring,sstring>val;
  char file[]="/tmp/sqledwldXXXXXX";
  FILE *tmpfile;
  sstring buf, sbuf;
  int answer;

  toggleInfo.loadToggles();
  if(argc<=1){
    printf("Usage: sqledwld <vnum list>\n");
    printf("Example: sqledwld 13700-13780 13791 13798\n");
    exit(0);
  }

  if(!parse_num_args(argc-1, argv+1, vnums))
    exit(0);

  for(unsigned int i=0;i<vnums.size();++i){
    printf("Fetching data for room %i\n", vnums[i]);

    db.query("select * from room where vnum=%i", vnums[i]);
    if(db.fetchRow()){
      buf = fmt("- room\n"); sbuf+=buf;
      buf = fmt("vnum: %s\n") % db["vnum"];  sbuf+=buf;
      buf = fmt("x:    %s\n") % db["x"];  sbuf+=buf;
      buf = fmt("y:    %s\n") % db["y"];  sbuf+=buf;
      buf = fmt("z:    %s\n") % db["z"];  sbuf+=buf;
      buf = fmt("name: %s\n") % db["name"];  sbuf+=buf;
      buf = fmt("description~:\n%s~\n") % db["description"];  sbuf+=buf;
      buf = fmt("room_flag: %s\n") % db["room_flag"];  sbuf+=buf;
      buf = fmt("sector:    %s\n") % db["sector"];  sbuf+=buf;
      buf = fmt("teletime:  %s\n") % db["teletime"];  sbuf+=buf;
      buf = fmt("teletarg:  %s\n") % db["teletarg"];  sbuf+=buf;
      buf = fmt("telelook:  %s\n") % db["telelook"];  sbuf+=buf;
      buf = fmt("river_speed: %s\n") % db["river_speed"];  sbuf+=buf;
      buf = fmt("river_dir: %s\n") % db["river_dir"];  sbuf+=buf;
      buf = fmt("capacity:  %s\n") % db["capacity"];  sbuf+=buf;
      buf = fmt("height:    %s\n") % db["height"];  sbuf+=buf;
      buf = fmt("spec:    %s\n") % db["spec"];  sbuf+=buf;
      buf = fmt("\n"); sbuf+=buf;
    }

    db.query("select * from roomextra where vnum=%i", vnums[i]);
    while(db.fetchRow()){
      buf = fmt("- roomextra\n"); sbuf+=buf;
      buf = fmt("vnum: %s\n") % db["vnum"];  sbuf+=buf;
      buf = fmt("name: %s\n") % db["name"];  sbuf+=buf;
      buf = fmt("description~:\n%s~\n") % db["description"];  sbuf+=buf;
      buf = fmt("\n"); sbuf+=buf;
    }

    db.query("select * from roomexit where vnum=%i", vnums[i]);
    while(db.fetchRow()){
      buf = fmt("- roomexit\n"); sbuf+=buf;
      buf = fmt("vnum:      %s\n") % db["vnum"];  sbuf+=buf;
      buf = fmt("direction: %s\n") % dirs[convertTo<int>(db["direction"])];
      sbuf+=buf;
      buf = fmt("name:      %s\n") % db["name"];  sbuf+=buf;
      buf = fmt("description~:\n%s~\n") % db["description"];  sbuf+=buf;
      buf = fmt("type:      %s\n") % db["type"];  sbuf+=buf;
      buf = fmt("condition_flag: %s\n") % db["condition_flag"]; sbuf+=buf;
      buf = fmt("lock_difficulty: %s\n") % db["lock_difficulty"]; sbuf+=buf;
      buf = fmt("weight:    %s\n") % db["weight"];  sbuf+=buf;
      buf = fmt("key_num:   %s\n") % db["key_num"];  sbuf+=buf;
      buf = fmt("destination:      %s\n") % db["destination"];  sbuf+=buf;
      buf = fmt("\n"); sbuf+=buf;
    }
  }

  mkstemp(file);
  tmpfile=fopen(file, "w");
  fprintf(tmpfile, "%s", sbuf.c_str());
  fclose(tmpfile);

  printf("Opening editor.\n");
  buf = fmt("$EDITOR %s") % file;
  system(buf.c_str());

  printf("Insert room%s? [y/n] ", vnums.size()>1?"s":"");
  while(1){
    answer=getc(stdin);
    if(answer=='n'){
      printf("Room%s not inserted.\n", vnums.size()>1?"s":"");
      unlink(file);
      exit(0);
    } else if(answer=='y'){
      break;
    } else {
      printf("Insert room%s? [y/n] ", vnums.size()>1?"s":"");
    }
  }

  buf = fmt("/bin/cp -f %s %s.backup") % file % file;
  system(buf.c_str());

  int i=0;

  while(++i){
    val=parse_data_file(file, i);
    if(val["vnum"]=="EOM")
      break;

    if(val["DATATYPE"]=="room"){
      printf("replacing room %s\n", val["vnum"].c_str());
      db.query("delete from room where vnum=%s",
	       val["vnum"].c_str());
      db.query("delete from roomextra where vnum=%s",
	       val["vnum"].c_str());
      db.query("delete from roomexit where vnum=%s",
	       val["vnum"].c_str());

      db.query("insert into room (vnum,x,y,z,name,description,room_flag,sector,teletime,teletarg,telelook,river_speed,river_dir,capacity,height,spec) values (%s,%s,%s,%s,'%s','%s',%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)",
	       val["vnum"].c_str(),val["x"].c_str(),val["y"].c_str(),val["z"].c_str(),val["name"].c_str(),val["description"].c_str(),val["room_flag"].c_str(),val["sector"].c_str(),val["teletime"].c_str(),val["teletarg"].c_str(),val["telelook"].c_str(),val["river_speed"].c_str(),val["river_dir"].c_str(),val["capacity"].c_str(),val["height"].c_str(),val["spec"].c_str());
    } else if(val["DATATYPE"]=="roomextra"){
      printf("replacing roomextra %s\n", val["vnum"].c_str());

      db.query("insert into roomextra (vnum, name, description) values (%s,'%s','%s')", val["vnum"].c_str(), val["name"].c_str(), val["description"].c_str());

    } else if(val["DATATYPE"]=="roomexit"){
      printf("replacing roomexit %s\n", val["vnum"].c_str());

      db.query("insert into roomexit (vnum,direction,name,description,type,condition_flag,lock_difficulty,weight,key_num,destination) values (%s,%i,'%s','%s',%s,%s,%s,%s,%s,%s)",
	       val["vnum"].c_str(),txt2dir(val["direction"]),val["name"].c_str(),val["description"].c_str(),val["type"].c_str(),val["condition_flag"].c_str(),val["lock_difficulty"].c_str(),val["weight"].c_str(),val["key_num"].c_str(),val["destination"].c_str());
    }
    printf("\n");

  }

  unlink(file);

  printf("Done.\n\r");
  printf("Your backup file is %s.backup\n", file);
}
<|endoftext|>


<commit_before>///
/// @file  StatusS2.hpp
///
/// Copyright (C) 2021 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef STATUS_HPP
#define STATUS_HPP

#include <int128_t.hpp>

namespace primecount {

class StatusS2
{
public:
  StatusS2(maxint_t x);
  void print(int64_t b, int64_t max_b);
  void print(int64_t low, int64_t limit, maxint_t sum, maxint_t sum_approx);
  static double getPercent(int64_t low, int64_t limit, maxint_t sum, maxint_t sum_approx);
private:
  bool isPrint(double time) const;
  void print(double percent);
  double epsilon_ = 0;
  double percent_ = -1;
  double time_ = 0;
  // Only print status if 0.1 seconds have elapsed
  // since last printing the status.
  double threshold_ = 0.1;
  int precision_ = 0;
};

} // namespace

#endif
<commit_msg>Fix filename<commit_after>///
/// @file  StatusS2.hpp
///
/// Copyright (C) 2021 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef STATUSS2_HPP
#define STATUSS2_HPP

#include <int128_t.hpp>

namespace primecount {

class StatusS2
{
public:
  StatusS2(maxint_t x);
  void print(int64_t b, int64_t max_b);
  void print(int64_t low, int64_t limit, maxint_t sum, maxint_t sum_approx);
  static double getPercent(int64_t low, int64_t limit, maxint_t sum, maxint_t sum_approx);
private:
  bool isPrint(double time) const;
  void print(double percent);
  double epsilon_ = 0;
  double percent_ = -1;
  double time_ = 0;
  // Only print status if 0.1 seconds have elapsed
  // since last printing the status.
  double threshold_ = 0.1;
  int precision_ = 0;
};

} // namespace

#endif
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include <cmath>

namespace etl {

namespace math {

/*!
 * \brief Return the logistic sigmoid of x
 * \param x The value
 * \return The logistic sigmoid of x
 */
inline float logistic_sigmoid(float x) {
    return 1.0f / (1.0f + std::exp(-x));
}

/*!
 * \brief Return the logistic sigmoid of x
 * \param x The value
 * \return The logistic sigmoid of x
 */
inline double logistic_sigmoid(double x) {
    return 1.0 / (1.0 + std::exp(-x));
}

/*!
 * \brief Return the softplus of x
 * \param x The value
 * \return The softplus of x
 */
inline float softplus(float x) {
    return std::log1p(std::exp(x));
}

/*!
 * \brief Return the softplus of x
 * \param x The value
 * \return The softplus of x
 */
inline double softplus(double x) {
    return std::log1p(std::exp(x));
}

/*!
 * \brief Return the sign of x
 * \param v The value
 * \return The sign of x
 */
template <typename W>
inline constexpr double sign(W v) noexcept {
    return v == W(0) ? W(0) : (v > W(0) ? W(1) : W(-1));
}

/*!
 * \brief Test if the given number is a power of two
 * \param n The number to test
 * \return true if the number is a power of two, false otherwise
 */
inline constexpr bool is_power_of_two(long n) {
    return (n & (n - 1)) == 0;
}

} //end of namespace math

} //end of namespace etl
<commit_msg>Fix is_power_of_two signature<commit_after>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include <cmath>

namespace etl {

namespace math {

/*!
 * \brief Return the logistic sigmoid of x
 * \param x The value
 * \return The logistic sigmoid of x
 */
inline float logistic_sigmoid(float x) {
    return 1.0f / (1.0f + std::exp(-x));
}

/*!
 * \brief Return the logistic sigmoid of x
 * \param x The value
 * \return The logistic sigmoid of x
 */
inline double logistic_sigmoid(double x) {
    return 1.0 / (1.0 + std::exp(-x));
}

/*!
 * \brief Return the softplus of x
 * \param x The value
 * \return The softplus of x
 */
inline float softplus(float x) {
    return std::log1p(std::exp(x));
}

/*!
 * \brief Return the softplus of x
 * \param x The value
 * \return The softplus of x
 */
inline double softplus(double x) {
    return std::log1p(std::exp(x));
}

/*!
 * \brief Return the sign of x
 * \param v The value
 * \return The sign of x
 */
template <typename W>
inline constexpr double sign(W v) noexcept {
    return v == W(0) ? W(0) : (v > W(0) ? W(1) : W(-1));
}

/*!
 * \brief Test if the given number is a power of two
 * \param n The number to test
 * \return true if the number is a power of two, false otherwise
 */
inline constexpr bool is_power_of_two(int64_t n) {
    return (n & (n - 1)) == 0;
}

} //end of namespace math

} //end of namespace etl
<|endoftext|>


<commit_before>#include <object/global.hh>
#include <object/server.hh>
#include <object/symbols.hh>

namespace object
{
  Server::Server()
  : libport::Socket(Socket::get_io_service())
  {
    proto_add(Object::proto);
//    initialize();
  }

  Server::Server(rServer model)
  : libport::Socket(Socket::get_io_service())
  {
    proto_add(model);
    initialize();
  }

  void
  Server::initialize()
  {
    CAPTURE_GLOBAL(Event);
    connection_ = Event->call(SYMBOL(new));
    slot_set(SYMBOL(connection), connection_);
  }

#define BOUNCE(Type, From, To)                  \
  Type                                          \
  Server::From() const                          \
  {                                             \
    if (base_)                                  \
      return To();                              \
    else                                        \
      RAISE("server not listening");            \
  }
  BOUNCE(std::string, host, getLocalHost);
  BOUNCE(unsigned short, port, getLocalPort);
#undef BOUNCE

  libport::Socket*
  Server::make_socket()
  {
    rSocket sock = new object::Socket(this);
    sockets_.push_back(sock);
    return sock.get();
  }

  void
  Server::listen(const std::string& host, const std::string& port)
  {
    libport::Socket::listen(boost::bind(&Server::make_socket, this),
                            host, port);
  }

  void
  Server::socket_ready(rSocket socket)
  {
    connection_->call(SYMBOL(syncEmit), socket);
  }

  const Server::sockets_type&
  Server::sockets() const
  {
    return sockets_;
  }

  URBI_CXX_OBJECT_REGISTER(Server);

  void Server::initialize(CxxObject::Binder<Server>& bind)
  {
    bind(SYMBOL(host),    &Server::host);
    bind(SYMBOL(listen),  &Server::listen);
    bind(SYMBOL(port),    &Server::port);
    bind(SYMBOL(sockets), &Server::sockets);
  }

  rObject
  Server::proto_make()
  {
    return new Server();
  }

}
<commit_msg>socket: Use the correct io_service for server socket.<commit_after>#include <object/global.hh>
#include <object/server.hh>
#include <object/symbols.hh>

namespace object
{
  Server::Server()
  : libport::Socket(object::Socket::get_io_service())
  {
    proto_add(Object::proto);
//    initialize();
  }

  Server::Server(rServer model)
  : libport::Socket(object::Socket::get_io_service())
  {
    proto_add(model);
    initialize();
  }

  void
  Server::initialize()
  {
    CAPTURE_GLOBAL(Event);
    connection_ = Event->call(SYMBOL(new));
    slot_set(SYMBOL(connection), connection_);
  }

#define BOUNCE(Type, From, To)                  \
  Type                                          \
  Server::From() const                          \
  {                                             \
    if (base_)                                  \
      return To();                              \
    else                                        \
      RAISE("server not listening");            \
  }
  BOUNCE(std::string, host, getLocalHost);
  BOUNCE(unsigned short, port, getLocalPort);
#undef BOUNCE

  libport::Socket*
  Server::make_socket()
  {
    rSocket sock = new object::Socket(this);
    sockets_.push_back(sock);
    return sock.get();
  }

  void
  Server::listen(const std::string& host, const std::string& port)
  {
    libport::Socket::listen(boost::bind(&Server::make_socket, this),
                            host, port);
  }

  void
  Server::socket_ready(rSocket socket)
  {
    connection_->call(SYMBOL(syncEmit), socket);
  }

  const Server::sockets_type&
  Server::sockets() const
  {
    return sockets_;
  }

  URBI_CXX_OBJECT_REGISTER(Server);

  void Server::initialize(CxxObject::Binder<Server>& bind)
  {
    bind(SYMBOL(host),    &Server::host);
    bind(SYMBOL(listen),  &Server::listen);
    bind(SYMBOL(port),    &Server::port);
    bind(SYMBOL(sockets), &Server::sockets);
  }

  rObject
  Server::proto_make()
  {
    return new Server();
  }

}
<|endoftext|>


<commit_before>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "VideoWidget.h"

#include <QApplication>
#include <QDebug>
#include <QPainter>
#include <QThread>
#include <QVariant>
#include <QObject>
#include <QDebug>

#include <gst/interfaces/xoverlay.h>

#ifdef Q_WS_X11
extern void qt_x11_set_global_double_buffer(bool);
#endif

namespace TelepathyIM
{
    VideoWidget::VideoWidget(GstBus *bus,  QWidget *parent, const QString &name)
        : Communication::VideoWidgetInterface(parent),
          bus_((GstBus *) gst_object_ref(bus)),
          video_overlay_(0),
          video_playback_element_(0),
          video_bin_(0),
          name_(name),
          window_id_(0)
    {
        qDebug() << "VideoWidget " << name << " INIT STARTED";
        setWindowTitle(name);

        // Element notifier init
        notifier_ = fs_element_added_notifier_new();
        g_signal_connect(notifier_, "element-added", G_CALLBACK(&VideoWidget::OnElementAdded), this);

// UNIX -> autovideosink
#ifdef Q_WS_X11
        qt_x11_set_global_double_buffer(false);

        video_playback_element_ = gst_element_factory_make("autovideosink", name.toStdString().c_str());
        gst_object_ref(video_playback_element_);
        gst_object_sink(video_playback_element_);

        fs_element_added_notifier_add(notifier_, GST_BIN(video_playback_element_));
#endif

// WINDOWS -> glimagesink (best), directdrawsink (possible buffer errors), dshowvideosink (possible buffer errors)
// With glimagesink on windows we need to add it to a new bin and make the proper connections to bin.
// This is because gimagesink does not inherit GstBin and there for the GST_BIN() typecheck in fs_element_added_notifier_add will fail
#ifdef Q_WS_WIN
        video_playback_element_ = gst_element_factory_make("glimagesink", name.toStdString().c_str());
        if (!video_playback_element_)
        {
            qDebug() << "VideoWidget " << name << " CANNOT CREATE video_playback_element_";
            return;
        }

//        gst_object_ref(video_playback_element_);
//        gst_object_sink(video_playback_element_);

        // Video bin init
        const QString video_bin_name = "video_bin_for_" + name;
        video_bin_ = gst_bin_new(video_bin_name.toStdString().c_str());
        if (!video_bin_)
        {
            qDebug() << "VideoWidget " << name << " CANNOT CREATE video_bin_";
            return;
        }

        // Add playback element to video bin
        gst_bin_add(GST_BIN(video_bin_), video_playback_element_);

        // Pad inits
        GstPad *static_sink_pad = gst_element_get_static_pad(video_playback_element_, "sink");
        GstPad *sink_ghost_pad = gst_ghost_pad_new("sink", static_sink_pad);

        // Add bad to video bin
        gst_element_add_pad(GST_ELEMENT(video_bin_), sink_ghost_pad);
        gst_object_unref(G_OBJECT(static_sink_pad));
        gst_object_ref(video_bin_);
        gst_object_sink(video_bin_);

        fs_element_added_notifier_add(notifier_, GST_BIN(video_bin_));
#endif

        gst_bus_enable_sync_message_emission(bus_);
        g_signal_connect(bus_, "sync-message", G_CALLBACK(&VideoWidget::OnSyncMessage), this);

        qDebug() << "VideoWidget " << name << " INIT COMPLETE";

        // QWidget properties
        QPalette palette;
        palette.setColor(QPalette::Background, Qt::black);
        palette.setColor(QPalette::Window, Qt::black);
        setPalette(palette);
        setAutoFillBackground(true);
        setAttribute(Qt::WA_NoSystemBackground, true);
        setAttribute(Qt::WA_PaintOnScreen, true);
        resize(322, 240);
        setMinimumSize(322, 240);
    }

    VideoWidget::~VideoWidget()
    {
        if (bus_)
        {
            g_object_unref(bus_);
            bus_ = 0;
        }
        if (video_playback_element_)
        {
//            g_object_unref(video_playback_element_);
            video_playback_element_ = 0;
        }
        if (video_bin_)
        {
            g_object_unref(video_bin_);
            video_bin_ = 0;
        }
        // todo unconnect signals ?
    }

    void VideoWidget::OnElementAdded(FsElementAddedNotifier *notifier, GstBin *bin, GstElement *element, VideoWidget *self)
    {
        // If element implements GST_X_OVERLAY interface, set local video_overlay_ to element
        // If true element = the current video sink
        if (!self->video_overlay_ && GST_IS_X_OVERLAY(element))
        {
            qDebug() << self->name_ << " >> element-added CALLBACK >> Got overlay element, storing";
            self->video_overlay_ = element;
            QMetaObject::invokeMethod(self, "WindowExposed", Qt::QueuedConnection);
        }

        // If element has property force-aspect-ratio set it to true
        // If true element = the current video sink
        if (g_object_class_find_property(G_OBJECT_GET_CLASS(element), "force-aspect-ratio"))
        {
            qDebug() << self->name_ << " >> element-added CALLBACK >> found 'force-aspect-ratio' from element";
            g_object_set(G_OBJECT(element), "force-aspect-ratio", TRUE, NULL);
        }
    }

    void VideoWidget::OnSyncMessage(GstBus *bus, GstMessage *message, VideoWidget *self)
    {
        // Return if we are not interested in the message content
        if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_ELEMENT)
            return;
        if (GST_MESSAGE_SRC(message) != (GstObject *)self->video_overlay_)
            return;

        // If message is about preparing xwindow id its from the current video sink
        // and we want to set our own qt widget window id where we want to render video
        const GstStructure *s = gst_message_get_structure(message);
        if (gst_structure_has_name(s, "prepare-xwindow-id") && self->video_overlay_)
        {
            qDebug() << self->name_ << " >> sync-message CALLBACK >> found 'prepare-xwindow-id' from GstMessage";
            QMetaObject::invokeMethod(self, "SetOverlay", Qt::QueuedConnection);
        }
    }

    void VideoWidget::showEvent(QShowEvent *showEvent)
    {
        // Override showEvent so we can set QWidget attributes and set overlay
        qDebug() << name_ << " >> QWidget::showEvent() override called";
        QWidget::showEvent(showEvent);
        SetOverlay();
    }

    void VideoWidget::SetOverlay()
    {
        if (video_overlay_ && GST_IS_X_OVERLAY(video_overlay_))
        {
            // Get window id from this widget and set it for video sink
            // so it renders to our widget id and does not open separate window (that is the default behaviour)
            qDebug() << name_ << " >> SetOverlay() called";
			window_id_ = winId();
            if (window_id_)
            {
                qDebug() << name_ << " >> Giving x overlay widgets window id " << window_id_;
                #ifdef Q_WS_X11
                    QApplication::syncX();
                #endif
                gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(video_overlay_), (gulong)window_id_);
            }
        }
        WindowExposed();
    }

    void VideoWidget::WindowExposed()
    {
        if (video_overlay_ && GST_IS_X_OVERLAY(video_overlay_))
        {
            // Expose the overlay (some sort of update)
            qDebug() << name_ << " >> WindowExposed() called";
            #ifdef Q_WS_X11
                QApplication::syncX();
            #endif
            gst_x_overlay_expose(GST_X_OVERLAY(video_overlay_));
        }
    }

	GstElement *VideoWidget::GetVideoPlaybackElement() const
	{
		if (video_bin_)
			return video_bin_;
		else if (video_playback_element_)
			return video_playback_element_;
		else
			return 0;
	}

    bool VideoWidget::VideoAvailable()
    {
        if (video_overlay_)
            return true;
        else
            return false;
    }

}
<commit_msg>* Video overlay to autovideosink, wee<commit_after>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "VideoWidget.h"

#include <QApplication>
#include <QDebug>
#include <QPainter>
#include <QThread>
#include <QVariant>
#include <QObject>
#include <QDebug>

#include <gst/interfaces/xoverlay.h>

#ifdef Q_WS_X11
extern void qt_x11_set_global_double_buffer(bool);
#endif

namespace TelepathyIM
{
    VideoWidget::VideoWidget(GstBus *bus,  QWidget *parent, const QString &name)
        : Communication::VideoWidgetInterface(parent),
          bus_((GstBus *) gst_object_ref(bus)),
          video_overlay_(0),
          video_playback_element_(0),
          video_bin_(0),
          name_(name),
          window_id_(0)
    {
        qDebug() << "VideoWidget " << name << " INIT STARTED";
        setWindowTitle(name);

        // Element notifier init
        notifier_ = fs_element_added_notifier_new();
        g_signal_connect(notifier_, "element-added", G_CALLBACK(&VideoWidget::OnElementAdded), this);

// UNIX -> autovideosink
#ifdef Q_WS_X11
        qt_x11_set_global_double_buffer(false);

        video_playback_element_ = gst_element_factory_make("autovideosink", name.toStdString().c_str());
        gst_object_ref(video_playback_element_);
        gst_object_sink(video_playback_element_);

        fs_element_added_notifier_add(notifier_, GST_BIN(video_playback_element_));
#endif

// WINDOWS -> autovideosink will chose one of there: glimagesink (best), directdrawsink (possible buffer errors), dshowvideosink (possible buffer errors)
#ifdef Q_WS_WIN
        video_playback_element_ = gst_element_factory_make("autovideosink", name.toStdString().c_str());
        if (!video_playback_element_)
        {
            qDebug() << "VideoWidget " << name << " CANNOT CREATE video_playback_element_";
            return;
        }

		if (GST_BIN(video_playback_element_))
		{
			fs_element_added_notifier_add(notifier_, GST_BIN(video_playback_element_));
		}
		else
		{
			// Video bin init
			const QString video_bin_name = "video_bin_for_" + name;
			video_bin_ = gst_bin_new(video_bin_name.toStdString().c_str());
			if (!video_bin_)
			{
				qDebug() << "VideoWidget " << name << " CANNOT CREATE video_bin_";
				return;
			}

			// Add playback element to video bin
			gst_bin_add(GST_BIN(video_bin_), video_playback_element_);

			// Pad inits
			GstPad *static_sink_pad = gst_element_get_static_pad(video_playback_element_, "sink");
			GstPad *sink_ghost_pad = gst_ghost_pad_new("sink", static_sink_pad);

			// Add bad to video bin
			gst_element_add_pad(GST_ELEMENT(video_bin_), sink_ghost_pad);
			gst_object_unref(G_OBJECT(static_sink_pad));
			gst_object_ref(video_bin_);
			gst_object_sink(video_bin_);

			fs_element_added_notifier_add(notifier_, GST_BIN(video_bin_));
		}
#endif

        gst_bus_enable_sync_message_emission(bus_);
        g_signal_connect(bus_, "sync-message", G_CALLBACK(&VideoWidget::OnSyncMessage), this);

        qDebug() << "VideoWidget " << name << " INIT COMPLETE";

        // QWidget properties
        QPalette palette;
        palette.setColor(QPalette::Background, Qt::black);
        palette.setColor(QPalette::Window, Qt::black);
        setPalette(palette);
        setAutoFillBackground(true);
        setAttribute(Qt::WA_NoSystemBackground, true);
        setAttribute(Qt::WA_PaintOnScreen, true);
        resize(322, 240);
        setMinimumSize(322, 240);
    }

    VideoWidget::~VideoWidget()
    {
        if (bus_)
        {
            g_object_unref(bus_);
            bus_ = 0;
        }
        if (video_playback_element_)
        {
//            g_object_unref(video_playback_element_);
            video_playback_element_ = 0;
        }
        if (video_bin_)
        {
            g_object_unref(video_bin_);
            video_bin_ = 0;
        }
        // todo unconnect signals ?
    }

    void VideoWidget::OnElementAdded(FsElementAddedNotifier *notifier, GstBin *bin, GstElement *element, VideoWidget *self)
    {
        // If element implements GST_X_OVERLAY interface, set local video_overlay_ to element
        // If true element = the current video sink
		if (GST_IS_X_OVERLAY(element))
			qDebug() << "GST_IS_X_OVERLAY(element) == true";

        if (!self->video_overlay_ && GST_IS_X_OVERLAY(element))
        {
            qDebug() << self->name_ << " >> element-added CALLBACK >> Got overlay element, storing";
            self->video_overlay_ = element;
            QMetaObject::invokeMethod(self, "WindowExposed", Qt::QueuedConnection);
        }

        // If element has property force-aspect-ratio set it to true
        // If true element = the current video sink
        if (g_object_class_find_property(G_OBJECT_GET_CLASS(element), "force-aspect-ratio"))
        {
            qDebug() << self->name_ << " >> element-added CALLBACK >> found 'force-aspect-ratio' from element";
            g_object_set(G_OBJECT(element), "force-aspect-ratio", TRUE, NULL);
        }
    }

    void VideoWidget::OnSyncMessage(GstBus *bus, GstMessage *message, VideoWidget *self)
    {
        // Return if we are not interested in the message content
        if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_ELEMENT)
            return;
        if (GST_MESSAGE_SRC(message) != (GstObject *)self->video_overlay_)
            return;

        // If message is about preparing xwindow id its from the current video sink
        // and we want to set our own qt widget window id where we want to render video
        const GstStructure *s = gst_message_get_structure(message);
        if (gst_structure_has_name(s, "prepare-xwindow-id") && self->video_overlay_)
        {
            qDebug() << self->name_ << " >> sync-message CALLBACK >> found 'prepare-xwindow-id' from GstMessage";
            QMetaObject::invokeMethod(self, "SetOverlay", Qt::QueuedConnection);
        }
    }

    void VideoWidget::showEvent(QShowEvent *showEvent)
    {
        // Override showEvent so we can set QWidget attributes and set overlay
        qDebug() << name_ << " >> QWidget::showEvent() override called";
        QWidget::showEvent(showEvent);
        SetOverlay();
    }

    void VideoWidget::SetOverlay()
    {
        if (video_overlay_ && GST_IS_X_OVERLAY(video_overlay_))
        {
            // Get window id from this widget and set it for video sink
            // so it renders to our widget id and does not open separate window (that is the default behaviour)
            qDebug() << name_ << " >> SetOverlay() called";
			window_id_ = winId();
            if (window_id_)
            {
                qDebug() << name_ << " >> Giving x overlay widgets window id " << window_id_;
                #ifdef Q_WS_X11
                    QApplication::syncX();
                #endif
                gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(video_overlay_), (gulong)window_id_);
            }
        }
        WindowExposed();
    }

    void VideoWidget::WindowExposed()
    {
        if (video_overlay_ && GST_IS_X_OVERLAY(video_overlay_))
        {
            // Expose the overlay (some sort of update)
            qDebug() << name_ << " >> WindowExposed() called";
            #ifdef Q_WS_X11
                QApplication::syncX();
            #endif
            gst_x_overlay_expose(GST_X_OVERLAY(video_overlay_));
        }
    }

	GstElement *VideoWidget::GetVideoPlaybackElement() const
	{
		if (video_bin_)
			return video_bin_;
		else if (video_playback_element_)
			return video_playback_element_;
		else
			return 0;
	}

    bool VideoWidget::VideoAvailable()
    {
        if (video_overlay_)
            return true;
        else
            return false;
    }

}
<|endoftext|>


<commit_before>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "VideoWidget.h"

#include <QApplication>
#include <QDebug>
#include <QPainter>
#include <QThread>
#include <QVariant>
#include <QObject>
#include <QDebug>

#include <gst/interfaces/xoverlay.h>

#ifdef Q_WS_X11
extern void qt_x11_set_global_double_buffer(bool);
#endif

namespace TelepathyIM
{
    VideoWidget::VideoWidget(GstBus *bus,  QWidget *parent, const QString &name)
        : Communication::VideoWidgetInterface(parent),
          bus_((GstBus *) gst_object_ref(bus)),
          video_overlay_(0),
          video_playback_element_(0),
          video_bin_(0),
          name_(name),
          window_id_(0),
          on_element_added_g_signal_(0),
          on_sync_message_g_signal_(0)

    {
        qDebug() << "VideoWidget " << name << " INIT STARTED";
        setWindowTitle(name);

        // Element notifier init
        notifier_ = fs_element_added_notifier_new();
        on_element_added_g_signal_ = g_signal_connect(notifier_, "element-added", G_CALLBACK(&VideoWidget::OnElementAdded), this);

// UNIX -> autovideosink
#ifdef Q_WS_X11

        qt_x11_set_global_double_buffer(false);

        video_playback_element_ = gst_element_factory_make("autovideosink", name.toStdString().c_str());
        gst_object_ref(video_playback_element_);
        gst_object_sink(video_playback_element_);

        fs_element_added_notifier_add(notifier_, GST_BIN(video_playback_element_));

#endif

// WINDOWS -> autovideosink will chose one of there: glimagesink (best), directdrawsink (possible buffer errors), dshowvideosink (possible buffer errors)
#ifdef Q_WS_WIN

        video_playback_element_ = gst_element_factory_make("glimagesink", 0);
        if (!video_playback_element_)
        {
            qDebug() << "VideoWidget " << name << " CANNOT CREATE video_playback_element_";
            return;
        }

		if (!video_playback_element_)
		{
			fs_element_added_notifier_add(notifier_, GST_BIN(video_playback_element_));
			gst_object_ref(video_playback_element_);
			gst_object_sink(video_playback_element_);
		}
		else
		{
			// Video bin init
			const QString video_bin_name = "video_bin_for_" + name;
			video_bin_ = gst_bin_new(video_bin_name.toStdString().c_str());
			if (!video_bin_)
			{
				qDebug() << "VideoWidget " << name << " CANNOT CREATE video_bin_";
				return;
			}

			// Add playback element to video bin
			gst_bin_add(GST_BIN(video_bin_), video_playback_element_);

			// Pad inits
			GstPad *static_sink_pad = gst_element_get_static_pad(video_playback_element_, "sink");
			GstPad *sink_ghost_pad = gst_ghost_pad_new("sink", static_sink_pad);

			// Add bad to video bin
			gst_element_add_pad(GST_ELEMENT(video_bin_), sink_ghost_pad);
			gst_object_unref(G_OBJECT(static_sink_pad));
			gst_object_ref(video_bin_);
			gst_object_sink(video_bin_);

			fs_element_added_notifier_add(notifier_, GST_BIN(video_bin_));
		}

#endif

        gst_bus_enable_sync_message_emission(bus_);
        on_sync_message_g_signal_ = g_signal_connect(bus_, "sync-message", G_CALLBACK(&VideoWidget::OnSyncMessage), this);

        qDebug() << "VideoWidget " << name << " INIT COMPLETE";

        // QWidget properties
        QPalette palette;
        palette.setColor(QPalette::Background, Qt::black);
        palette.setColor(QPalette::Window, Qt::black);
        setPalette(palette);
        setAutoFillBackground(true);
        setAttribute(Qt::WA_NoSystemBackground, true);
        setAttribute(Qt::WA_PaintOnScreen, true);
        resize(322, 240);
        setMinimumSize(322, 240);
    }

    VideoWidget::~VideoWidget()
    {
        if (notifier_)
        {
            fs_element_added_notifier_remove(notifier_, GST_BIN(video_playback_element_));
            g_signal_handler_disconnect(notifier_, on_element_added_g_signal_);
        }
        if (bus_)
            g_signal_handler_disconnect(bus_, on_sync_message_g_signal_);

        if (bus_)
        {
            g_object_unref(bus_);
            bus_ = 0;
        }
        if (video_playback_element_)
        {
            if (GST_BIN(video_playback_element_))
                g_object_unref(video_playback_element_);
            video_playback_element_ = 0;
        }
        if (video_bin_)
        {
            g_object_unref(video_bin_);
            video_bin_ = 0;
        }
        // todo unconnect signals ?
    }

    void VideoWidget::OnElementAdded(FsElementAddedNotifier *notifier, GstBin *bin, GstElement *element, VideoWidget *self)
    {
        // If element implements GST_X_OVERLAY interface, set local video_overlay_ to element
        // If true element = the current video sink
        if (!self->video_overlay_ && GST_IS_X_OVERLAY(element))
        {
            qDebug() << self->name_ << " >> element-added CALLBACK >> Got overlay element, storing";
            self->video_overlay_ = element;
            QMetaObject::invokeMethod(self, "WindowExposed", Qt::QueuedConnection);
        }

        // If element has property force-aspect-ratio set it to true
        // If true element = the current video sink
        if (g_object_class_find_property(G_OBJECT_GET_CLASS(element), "force-aspect-ratio"))
        {
            qDebug() << self->name_ << " >> element-added CALLBACK >> found 'force-aspect-ratio' from element";
            g_object_set(G_OBJECT(element), "force-aspect-ratio", TRUE, NULL);
        }
    }

    void VideoWidget::OnSyncMessage(GstBus *bus, GstMessage *message, VideoWidget *self)
    {
        // Return if we are not interested in the message content
        if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_ELEMENT)
            return;
        if (GST_MESSAGE_SRC(message) != (GstObject *)self->video_overlay_)
            return;

        // If message is about preparing xwindow id its from the current video sink
        // and we want to set our own qt widget window id where we want to render video
        const GstStructure *s = gst_message_get_structure(message);
        if (gst_structure_has_name(s, "prepare-xwindow-id") && self->video_overlay_)
        {
            qDebug() << self->name_ << " >> sync-message CALLBACK >> found 'prepare-xwindow-id' from GstMessage";
            QMetaObject::invokeMethod(self, "SetOverlay", Qt::QueuedConnection);
        }
    }

    void VideoWidget::showEvent(QShowEvent *showEvent)
    {
        // Override showEvent so we can set QWidget attributes and set overlay
        qDebug() << name_ << " >> QWidget::showEvent() override called";
        QWidget::showEvent(showEvent);
        SetOverlay();
    }

    void VideoWidget::SetOverlay()
    {
        if (video_overlay_ && GST_IS_X_OVERLAY(video_overlay_))
        {
            // Get window id from this widget and set it for video sink
            // so it renders to our widget id and does not open separate window (that is the default behaviour)
            qDebug() << name_ << " >> SetOverlay() called";
			window_id_ = winId();
            if (window_id_)
            {
                qDebug() << name_ << " >> Giving x overlay widgets window id " << window_id_;
                #ifdef Q_WS_X11
                    QApplication::syncX();
                #endif
                gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(video_overlay_), (gulong)window_id_);
            }
        }
        WindowExposed();
    }

    void VideoWidget::WindowExposed()
    {
        if (video_overlay_ && GST_IS_X_OVERLAY(video_overlay_))
        {
            // Expose the overlay (some sort of update)
            qDebug() << name_ << " >> WindowExposed() called";
            #ifdef Q_WS_X11
                QApplication::syncX();
            #endif
            gst_x_overlay_expose(GST_X_OVERLAY(video_overlay_));
        }
    }

	GstElement *VideoWidget::GetVideoPlaybackElement() const
	{
		if (video_bin_)
			return video_bin_;
		else if (video_playback_element_)
			return video_playback_element_;
		else
			return 0;
	}

    bool VideoWidget::VideoAvailable()
    {
        if (video_overlay_)
            return true;
        else
            return false;
    }

}
<commit_msg>* glimagesink small fix<commit_after>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "VideoWidget.h"

#include <QApplication>
#include <QDebug>
#include <QPainter>
#include <QThread>
#include <QVariant>
#include <QObject>
#include <QDebug>

#include <gst/interfaces/xoverlay.h>

#ifdef Q_WS_X11
extern void qt_x11_set_global_double_buffer(bool);
#endif

namespace TelepathyIM
{
    VideoWidget::VideoWidget(GstBus *bus,  QWidget *parent, const QString &name)
        : Communication::VideoWidgetInterface(parent),
          bus_((GstBus *) gst_object_ref(bus)),
          video_overlay_(0),
          video_playback_element_(0),
          video_bin_(0),
          name_(name),
          window_id_(0),
          on_element_added_g_signal_(0),
          on_sync_message_g_signal_(0)

    {
        qDebug() << "VideoWidget " << name << " INIT STARTED";
        setWindowTitle(name);

        // Element notifier init
        notifier_ = fs_element_added_notifier_new();
        on_element_added_g_signal_ = g_signal_connect(notifier_, "element-added", G_CALLBACK(&VideoWidget::OnElementAdded), this);

// UNIX -> autovideosink
#ifdef Q_WS_X11

        qt_x11_set_global_double_buffer(false);

        video_playback_element_ = gst_element_factory_make("autovideosink", name.toStdString().c_str());
        gst_object_ref(video_playback_element_);
        gst_object_sink(video_playback_element_);

        fs_element_added_notifier_add(notifier_, GST_BIN(video_playback_element_));

#endif

// WINDOWS -> autovideosink will chose one of there: glimagesink (best), directdrawsink (possible buffer errors), dshowvideosink (possible buffer errors)
#ifdef Q_WS_WIN

        video_playback_element_ = gst_element_factory_make("glimagesink", 0);
        if (!video_playback_element_)
        {
            qDebug() << "VideoWidget " << name << " CANNOT CREATE video_playback_element_";
            return;
        }

		//if (!video_playback_element_)
		//{
		//	fs_element_added_notifier_add(notifier_, GST_BIN(video_playback_element_));
		//	gst_object_ref(video_playback_element_);
		//	gst_object_sink(video_playback_element_);
		//}
		//else
		//{
			// Video bin init
			const QString video_bin_name = "video_bin_for_" + name;
			video_bin_ = gst_bin_new(video_bin_name.toStdString().c_str());
			if (!video_bin_)
			{
				qDebug() << "VideoWidget " << name << " CANNOT CREATE video_bin_";
				return;
			}

			// Add playback element to video bin
			gst_bin_add(GST_BIN(video_bin_), video_playback_element_);

			// Pad inits
			GstPad *static_sink_pad = gst_element_get_static_pad(video_playback_element_, "sink");
			GstPad *sink_ghost_pad = gst_ghost_pad_new("sink", static_sink_pad);

			// Add bad to video bin
			gst_element_add_pad(GST_ELEMENT(video_bin_), sink_ghost_pad);
			gst_object_unref(G_OBJECT(static_sink_pad));
			gst_object_ref(video_bin_);
			gst_object_sink(video_bin_);

			fs_element_added_notifier_add(notifier_, GST_BIN(video_bin_));
		//}

#endif

        gst_bus_enable_sync_message_emission(bus_);
        on_sync_message_g_signal_ = g_signal_connect(bus_, "sync-message", G_CALLBACK(&VideoWidget::OnSyncMessage), this);

        qDebug() << "VideoWidget " << name << " INIT COMPLETE";

        // QWidget properties
        QPalette palette;
        palette.setColor(QPalette::Background, Qt::black);
        palette.setColor(QPalette::Window, Qt::black);
        setPalette(palette);
        setAutoFillBackground(true);
        setAttribute(Qt::WA_NoSystemBackground, true);
        setAttribute(Qt::WA_PaintOnScreen, true);
        resize(322, 240);
        setMinimumSize(322, 240);
    }

    VideoWidget::~VideoWidget()
    {
        if (notifier_)
        {
            fs_element_added_notifier_remove(notifier_, GST_BIN(video_playback_element_));
            g_signal_handler_disconnect(notifier_, on_element_added_g_signal_);
        }
        if (bus_)
            g_signal_handler_disconnect(bus_, on_sync_message_g_signal_);

        if (bus_)
        {
            g_object_unref(bus_);
            bus_ = 0;
        }
        if (video_playback_element_)
        {
            if (GST_BIN(video_playback_element_))
                g_object_unref(video_playback_element_);
            video_playback_element_ = 0;
        }
        if (video_bin_)
        {
            g_object_unref(video_bin_);
            video_bin_ = 0;
        }
        // todo unconnect signals ?
    }

    void VideoWidget::OnElementAdded(FsElementAddedNotifier *notifier, GstBin *bin, GstElement *element, VideoWidget *self)
    {
        // If element implements GST_X_OVERLAY interface, set local video_overlay_ to element
        // If true element = the current video sink
        if (!self->video_overlay_ && GST_IS_X_OVERLAY(element))
        {
            qDebug() << self->name_ << " >> element-added CALLBACK >> Got overlay element, storing";
            self->video_overlay_ = element;
            QMetaObject::invokeMethod(self, "WindowExposed", Qt::QueuedConnection);
        }

        // If element has property force-aspect-ratio set it to true
        // If true element = the current video sink
        if (g_object_class_find_property(G_OBJECT_GET_CLASS(element), "force-aspect-ratio"))
        {
            qDebug() << self->name_ << " >> element-added CALLBACK >> found 'force-aspect-ratio' from element";
            g_object_set(G_OBJECT(element), "force-aspect-ratio", TRUE, NULL);
        }
    }

    void VideoWidget::OnSyncMessage(GstBus *bus, GstMessage *message, VideoWidget *self)
    {
        // Return if we are not interested in the message content
        if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_ELEMENT)
            return;
        if (GST_MESSAGE_SRC(message) != (GstObject *)self->video_overlay_)
            return;

        // If message is about preparing xwindow id its from the current video sink
        // and we want to set our own qt widget window id where we want to render video
        const GstStructure *s = gst_message_get_structure(message);
        if (gst_structure_has_name(s, "prepare-xwindow-id") && self->video_overlay_)
        {
            qDebug() << self->name_ << " >> sync-message CALLBACK >> found 'prepare-xwindow-id' from GstMessage";
            QMetaObject::invokeMethod(self, "SetOverlay", Qt::QueuedConnection);
        }
    }

    void VideoWidget::showEvent(QShowEvent *showEvent)
    {
        // Override showEvent so we can set QWidget attributes and set overlay
        qDebug() << name_ << " >> QWidget::showEvent() override called";
        QWidget::showEvent(showEvent);
        SetOverlay();
    }

    void VideoWidget::SetOverlay()
    {
        if (video_overlay_ && GST_IS_X_OVERLAY(video_overlay_))
        {
            // Get window id from this widget and set it for video sink
            // so it renders to our widget id and does not open separate window (that is the default behaviour)
            qDebug() << name_ << " >> SetOverlay() called";
			window_id_ = winId();
            if (window_id_)
            {
                qDebug() << name_ << " >> Giving x overlay widgets window id " << window_id_;
                #ifdef Q_WS_X11
                    QApplication::syncX();
                #endif
                gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(video_overlay_), (gulong)window_id_);
            }
        }
        WindowExposed();
    }

    void VideoWidget::WindowExposed()
    {
        if (video_overlay_ && GST_IS_X_OVERLAY(video_overlay_))
        {
            // Expose the overlay (some sort of update)
            qDebug() << name_ << " >> WindowExposed() called";
            #ifdef Q_WS_X11
                QApplication::syncX();
            #endif
            gst_x_overlay_expose(GST_X_OVERLAY(video_overlay_));
        }
    }

	GstElement *VideoWidget::GetVideoPlaybackElement() const
	{
		if (video_bin_)
			return video_bin_;
		else if (video_playback_element_)
			return video_playback_element_;
		else
			return 0;
	}

    bool VideoWidget::VideoAvailable()
    {
        if (video_overlay_)
            return true;
        else
            return false;
    }

}
<|endoftext|>