<commit_before>#include "Geometry3D.h"
#include "PlaneGeometry.h"
#include <vecmath.h>

#ifdef MITK_DICOM_ENABLED
extern "C"
{
#include "ipDicom.h"
}
#endif

//##ModelId=3DCBF3AD0110
const unsigned int *mitk::Geometry3D::GetDimensions() const
{
	return m_Dimensions;
}

//##ModelId=3DDE649E00A3
unsigned int mitk::Geometry3D::GetDataDimension() const
{
	return m_Dimension;
}

//##ModelId=3DCBF50C0377
mitk::Geometry2D::ConstPointer mitk::Geometry3D::GetGeometry2D(int s, int t) const
{
    mitk::Geometry2D::ConstPointer geometry2d = NULL;

    if(IsValidSlice(s, t))
    {
        int pos=s+t*m_Dimensions[2];
	    geometry2d = m_Geometry2Ds[pos];
        //if (a) we don't have a Geometry2D stored for the requested slice,
        //(b) m_EvenlySpaced is activated and (c) the first slice (s=0,t=0)
        //is a PlaneGeometry instance, then we calculate geometry of the requested
        //as the plane of the first slice shifted by m_Spacing*s.
        if((m_EvenlySpaced) && (geometry2d==NULL))
        {
            Vector3D zStep(0,0,m_Spacing.z);
            const PlaneGeometry* firstslice=dynamic_cast<const PlaneGeometry*> (m_Geometry2Ds[0].GetPointer());
            if(firstslice!=NULL)
            {
                mitk::PlaneView view=firstslice->GetPlaneView();
                mitk::PlaneGeometry::Pointer requestedslice;
                requestedslice = mitk::PlaneGeometry::New();
                view.point+=zStep*s;
                requestedslice->SetPlaneView(view);
                geometry2d = requestedslice;
                m_Geometry2Ds[pos] = geometry2d;
            }
        }
    }
    return geometry2d;
}

//##ModelId=3DCBF5D40253
mitk::BoundingBox::ConstPointer mitk::Geometry3D::GetBoundingBox(int t) const
{
    mitk::BoundingBox::Pointer m_BoundingBox=mitk::BoundingBox::New();

    mitk::BoundingBox::PointsContainer::Pointer pointscontainer=mitk::BoundingBox::PointsContainer::New();
    float nullpoint[]={0,0,0};
    mitk::BoundingBox::PointType p(nullpoint);

    assert(m_EvenlySpaced);

    int s, slices;
    mitk::BoundingBox::PointIdentifier pointid=0;

    slices=( GetDataDimension()<=2 ? 1 : GetDimensions()[2] );

    for(s=0;s<slices;++s)
    {
        const PlaneGeometry* planegeometry =
            dynamic_cast<const PlaneGeometry *>(GetGeometry2D(s,t).GetPointer());
        assert(planegeometry!=NULL);

        const PlaneView& planeview=planegeometry->GetPlaneView();
        Point3D pt;

        //add the four edge points of the plane geometry to the bounding box calculator.
        pt=planeview.point;
        p[0]=pt.x; p[1]=pt.y; p[2]=pt.z;
        pointscontainer->InsertElement(pointid++, p);

        pt=planeview.point+planeview.getOrientation1();
        p[0]=pt.x; p[1]=pt.y; p[2]=pt.z;
        pointscontainer->InsertElement(pointid++, p);

        pt+=planeview.getOrientation2();
        p[0]=pt.x; p[1]=pt.y; p[2]=pt.z;
        pointscontainer->InsertElement(pointid++, p);

        pt=planeview.point+planeview.getOrientation2();
        p[0]=pt.x; p[1]=pt.y; p[2]=pt.z;
        pointscontainer->InsertElement(pointid++, p);
    }

    m_BoundingBox->SetPoints(pointscontainer);

    m_BoundingBox->ComputeBoundingBox();

    return m_BoundingBox;
}

//##ModelId=3DCBF5E9037F
double mitk::Geometry3D::GetTime(int t) const
{
	itkExceptionMacro("GetTime not yet supported.");
	return 0;
}

//##ModelId=3DE763C500C4
mitk::Geometry3D::TransformPointer mitk::Geometry3D::GetTransfrom() const
{
	itkExceptionMacro("Transform not yet supported.");
	return NULL;
}

//##ModelId=3DDE65D1028A
void mitk::Geometry3D::MMToUnits(const mitk::Point3D &pt_mm, mitk::Point3D &pt_units, float t) const
{
    m_TransformMMToUnits.transform(pt_mm, &pt_units);
}

//##ModelId=3DDE65DC0151
void mitk::Geometry3D::UnitsToMM(const mitk::Point3D &pt_units, mitk::Point3D &pt_mm, float t) const
{
    m_TransformUnitsToMM.transform(pt_units, &pt_mm);
}

//##ModelId=3E3B986602CF
void mitk::Geometry3D::MMToUnits(const mitk::Vector3D &vec_mm, mitk::Vector3D &vec_units, float t) const
{
    m_TransformMMToUnits.transform(vec_mm, &vec_units);
}

//##ModelId=3E3B987503A3
void mitk::Geometry3D::UnitsToMM(const mitk::Vector3D &vec_units, mitk::Vector3D &vec_mm, float t) const
{
    m_TransformUnitsToMM.transform(vec_units, &vec_mm);
}

//##ModelId=3DCBC65C017C
const float* mitk::Geometry3D::GetSpacing() const
{
	return &m_Spacing.x;
}

//##ModelId=3E15578402BD
bool mitk::Geometry3D::SetGeometry2D(const mitk::Geometry2D* geometry2D, int s, int t)
{
    if(IsValidSlice(s,t))
    {
        m_Geometry2Ds[s*m_Dimensions[2]+t*m_Dimensions[3]]=geometry2D;
        return true;
    }
	return false;
}

//##ModelId=3E155839024F
bool mitk::Geometry3D::SetGeometry2D(ipPicDescriptor* pic, int s, int t)
{
    if((pic!=NULL) && (IsValidSlice(s,t)))
    {
        itkWarningMacro("SetGeometry2D by pic assumes a plane geometry starting at (0,0,0).");

        //construct standard view
        mitk::Point3D origin, right, bottom; bool rightHanded=true;
	    mitk::Vector2D viewport(0,0);
        origin.set(0,0,s);               UnitsToMM(origin, origin);
        right.set(m_Dimensions[0],0,0);  UnitsToMM(right, right);
        bottom.set(0,m_Dimensions[1],0); UnitsToMM(bottom, bottom);

        PlaneView view_std(origin, right, bottom, viewport, viewport, rightHanded);

        mitk::PlaneGeometry::Pointer planegeometry=mitk::PlaneGeometry::New();
        planegeometry->SetPlaneView(view_std);
        planegeometry->SetSizeInUnits(m_Dimensions[0], m_Dimensions[1]);
        SetGeometry2D(planegeometry, s, t);
        return true;
    }
    return false;
}

//##ModelId=3E3453C703AF
void mitk::Geometry3D::Initialize(unsigned int dimension, const unsigned int* dimensions)
{
	m_Dimension=dimension;
	if(m_Dimensions!=NULL)
		delete m_Dimensions;
	m_Dimensions=new unsigned int[m_Dimension>4?m_Dimension:4];
	memcpy(m_Dimensions, dimensions, sizeof(unsigned int)*m_Dimension);
	if(m_Dimension<4)
	{
		unsigned int i, *p;
		for(i=0,p=m_Dimensions+m_Dimension;i<4-m_Dimension;++i, ++p)
			*p=1;
	}

	unsigned int i;
	for(i=0;i<4;++i)
	{
		m_LargestPossibleRegion.SetIndex(i, 0);
		m_LargestPossibleRegion.SetSize (i, m_Dimensions[i]);
	}

    m_Geometry2Ds.clear();

    Geometry2D::ConstPointer gnull=NULL;
    int num=m_Dimensions[2]*m_Dimensions[3];

    m_Geometry2Ds.reserve(num);
    m_Geometry2Ds.assign(num, gnull);

    //initialize m_TransformOfOrigin and m_Spacing (and m_TransformUnitsToMM/m_TransformMMToUnits).
    m_TransformOfOrigin.setIdentity();
    SetSpacing(Vector3D(1.0,1.0,1.0));

    //construct standard view
    mitk::Point3D right, bottom; bool rightHanded=true;
	mitk::Vector2D viewport(0,0);
    right.set(m_Dimensions[0],0,0); UnitsToMM(right, right);
    bottom.set(0,m_Dimensions[1],0); UnitsToMM(bottom, bottom);
    PlaneView view_std(mitk::Point3D(0,0,0), right, bottom, viewport, viewport, rightHanded);

    mitk::PlaneGeometry::Pointer planegeometry=mitk::PlaneGeometry::New();
    m_Geometry2Ds[0]=planegeometry;
    planegeometry->SetPlaneView(view_std);
    planegeometry->SetSizeInUnits(m_Dimensions[0], m_Dimensions[1]);
}

//##ModelId=3E15572E0269
mitk::Geometry3D::Geometry3D(unsigned int dimension, const unsigned int* dimensions) : m_Dimension(0), m_Dimensions(NULL), m_EvenlySpaced(true)
{
    Initialize(dimension, dimensions);
}

//##ModelId=3E3452F10253
mitk::Geometry3D::Geometry3D(const mitk::Geometry3D& right) : m_Dimensions(NULL)
{
    Initialize(right.GetDataDimension(),right.GetDimensions());
}

//##ModelId=3E3452F10393
// mitk::Geometry3D& mitk::Geometry3D::operator=(const mitk::Geometry3D& right)
// {
//     return Geometry3D(right);
// }

//##ModelId=3E3456C50067
mitk::Geometry3D::~Geometry3D()
{
    if(m_Dimensions!=NULL)
        delete m_Dimensions;
}

//##ModelId=3E3BE1F10106
bool mitk::Geometry3D::IsValidSlice(int s, int t) const
{
	return ((s>=0) && (s<m_Dimensions[2]) && (t>=0) && (t<m_Dimensions[3]));
}

//##ModelId=3E3BE1F8000C
bool mitk::Geometry3D::IsValidTime(int t) const
{
	return IsValidSlice(0, t);
}

//##ModelId=3E3BE8CF010E
void mitk::Geometry3D::SetSpacing(mitk::Vector3D aSpacing)
{
    m_Spacing = aSpacing;

    m_TransformUnitsToMM=m_TransformOfOrigin;

    mitk::Vector4D col;
    m_TransformUnitsToMM.getColumn(0, &col); col*=aSpacing.x; m_TransformUnitsToMM.setColumn(0, col);
    m_TransformUnitsToMM.getColumn(1, &col); col*=aSpacing.x; m_TransformUnitsToMM.setColumn(1, col);
    m_TransformUnitsToMM.getColumn(2, &col); col*=aSpacing.x; m_TransformUnitsToMM.setColumn(2, col);

    m_TransformMMToUnits.invert(m_TransformUnitsToMM);

    Modified();
}

//##ModelId=3E3C13F802A6
void mitk::Geometry3D::SetEvenlySpaced(bool on)
{
    m_EvenlySpaced=on;
    Modified();
}

//##ModelId=3E3C2C37031B
void mitk::Geometry3D::SetSpacing(ipPicDescriptor* pic)
{
    Vector3D spacing(m_Spacing);

    ipPicTSV_t *tsv;

    tsv = ipPicQueryTag( pic, "PIXEL SIZE" );
	if(tsv)
	{
		if((tsv->dim*tsv->n[0]>=3) && (tsv->type==ipPicFloat))
		{
			if(tsv->bpe==32)
				spacing.set(((ipFloat4_t*)tsv->value)[0], ((ipFloat4_t*)tsv->value)[1],((ipFloat4_t*)tsv->value)[2]);
			else
			if(tsv->bpe==64)
				spacing.set(((ipFloat8_t*)tsv->value)[0], ((ipFloat8_t*)tsv->value)[1],((ipFloat8_t*)tsv->value)[2]);
		}
	}
#ifdef MITK_DICOM_ENABLED
	else
	{
		tsv = ipPicQueryTag( pic, "SOURCE HEADER" );
		if( tsv )
		{
			ipFloat8_t spacing = 0;
			ipFloat8_t thickness = 1;
			ipFloat8_t fx = 1;
			ipFloat8_t fy = 1;

			if( dicomFindElement( (unsigned char *) tsv->value, 0x0018, 0x0088, &data, &len ) )
			{
				sscanf( (char *) data, "%lf", &spacing );
				itkDebugMacro( "spacing:   %5.2f mm\n" << spacing );
			}
			if( dicomFindElement( (unsigned char *) tsv->value, 0x0018, 0x0050, &data, &len ) )
			{
				sscanf( (char *) data, "%lf", &thickness );
				itkDebugMacro( "thickness: %5.2f mm\n" << thickness );

				if( thickness == 0 )
					thickness = 1;
			}
			if( dicomFindElement( (unsigned char *) tsv->value, 0x0028, 0x0030, &data, &len )
				&& len>0 && ((char *)data)[0] )
			{
				sscanf( (char *) data, "%lf\\%lf", &fy, &fx );    // row / column value
				itkDebugMacro( "fx, fy:    %5.2f/%5.2f mm\n" << fx << fy );
			}

            spacing.set(fx, fy,( spacing > 0 ? spacing : thickness));
		}
	}
#endif
	 // FIXME:
	 // nur fuer Testdatensatz
	 // spacing = Vector3D(1/3.0,1/4.0,1/5.0);
    SetSpacing(spacing);
}
<commit_msg>fixed return type in GetBoundingBox()<commit_after>#include "Geometry3D.h"
#include "PlaneGeometry.h"
#include <vecmath.h>

#ifdef MITK_DICOM_ENABLED
extern "C"
{
#include "ipDicom.h"
}
#endif

//##ModelId=3DCBF3AD0110
const unsigned int *mitk::Geometry3D::GetDimensions() const
{
	return m_Dimensions;
}

//##ModelId=3DDE649E00A3
unsigned int mitk::Geometry3D::GetDataDimension() const
{
	return m_Dimension;
}

//##ModelId=3DCBF50C0377
mitk::Geometry2D::ConstPointer mitk::Geometry3D::GetGeometry2D(int s, int t) const
{
    mitk::Geometry2D::ConstPointer geometry2d = NULL;

    if(IsValidSlice(s, t))
    {
        int pos=s+t*m_Dimensions[2];
	    geometry2d = m_Geometry2Ds[pos];
        //if (a) we don't have a Geometry2D stored for the requested slice,
        //(b) m_EvenlySpaced is activated and (c) the first slice (s=0,t=0)
        //is a PlaneGeometry instance, then we calculate geometry of the requested
        //as the plane of the first slice shifted by m_Spacing*s.
        if((m_EvenlySpaced) && (geometry2d==NULL))
        {
            Vector3D zStep(0,0,m_Spacing.z);
            const PlaneGeometry* firstslice=dynamic_cast<const PlaneGeometry*> (m_Geometry2Ds[0].GetPointer());
            if(firstslice!=NULL)
            {
                mitk::PlaneView view=firstslice->GetPlaneView();
                mitk::PlaneGeometry::Pointer requestedslice;
                requestedslice = mitk::PlaneGeometry::New();
                view.point+=zStep*s;
                requestedslice->SetPlaneView(view);
                geometry2d = requestedslice;
                m_Geometry2Ds[pos] = geometry2d;
            }
        }
    }
    return geometry2d;
}

//##ModelId=3DCBF5D40253
mitk::BoundingBox::ConstPointer mitk::Geometry3D::GetBoundingBox(int t) const
{
    mitk::BoundingBox::Pointer m_BoundingBox=mitk::BoundingBox::New();

    mitk::BoundingBox::PointsContainer::Pointer pointscontainer=mitk::BoundingBox::PointsContainer::New();
    float nullpoint[]={0,0,0};
    mitk::BoundingBox::PointType p(nullpoint);

    assert(m_EvenlySpaced);

    int s, slices;
    mitk::BoundingBox::PointIdentifier pointid=0;

    slices=( GetDataDimension()<=2 ? 1 : GetDimensions()[2] );

    for(s=0;s<slices;++s)
    {
        const PlaneGeometry* planegeometry =
            dynamic_cast<const PlaneGeometry *>(GetGeometry2D(s,t).GetPointer());
        assert(planegeometry!=NULL);

        const PlaneView& planeview=planegeometry->GetPlaneView();
        Point3D pt;

        //add the four edge points of the plane geometry to the bounding box calculator.
        pt=planeview.point;
        p[0]=pt.x; p[1]=pt.y; p[2]=pt.z;
        pointscontainer->InsertElement(pointid++, p);

        pt=planeview.point+planeview.getOrientation1();
        p[0]=pt.x; p[1]=pt.y; p[2]=pt.z;
        pointscontainer->InsertElement(pointid++, p);

        pt+=planeview.getOrientation2();
        p[0]=pt.x; p[1]=pt.y; p[2]=pt.z;
        pointscontainer->InsertElement(pointid++, p);

        pt=planeview.point+planeview.getOrientation2();
        p[0]=pt.x; p[1]=pt.y; p[2]=pt.z;
        pointscontainer->InsertElement(pointid++, p);
    }

    m_BoundingBox->SetPoints(pointscontainer);

    m_BoundingBox->ComputeBoundingBox();

    return m_BoundingBox.GetPointer();
}

//##ModelId=3DCBF5E9037F
double mitk::Geometry3D::GetTime(int t) const
{
	itkExceptionMacro("GetTime not yet supported.");
	return 0;
}

//##ModelId=3DE763C500C4
mitk::Geometry3D::TransformPointer mitk::Geometry3D::GetTransfrom() const
{
	itkExceptionMacro("Transform not yet supported.");
	return NULL;
}

//##ModelId=3DDE65D1028A
void mitk::Geometry3D::MMToUnits(const mitk::Point3D &pt_mm, mitk::Point3D &pt_units, float t) const
{
    m_TransformMMToUnits.transform(pt_mm, &pt_units);
}

//##ModelId=3DDE65DC0151
void mitk::Geometry3D::UnitsToMM(const mitk::Point3D &pt_units, mitk::Point3D &pt_mm, float t) const
{
    m_TransformUnitsToMM.transform(pt_units, &pt_mm);
}

//##ModelId=3E3B986602CF
void mitk::Geometry3D::MMToUnits(const mitk::Vector3D &vec_mm, mitk::Vector3D &vec_units, float t) const
{
    m_TransformMMToUnits.transform(vec_mm, &vec_units);
}

//##ModelId=3E3B987503A3
void mitk::Geometry3D::UnitsToMM(const mitk::Vector3D &vec_units, mitk::Vector3D &vec_mm, float t) const
{
    m_TransformUnitsToMM.transform(vec_units, &vec_mm);
}

//##ModelId=3DCBC65C017C
const float* mitk::Geometry3D::GetSpacing() const
{
	return &m_Spacing.x;
}

//##ModelId=3E15578402BD
bool mitk::Geometry3D::SetGeometry2D(const mitk::Geometry2D* geometry2D, int s, int t)
{
    if(IsValidSlice(s,t))
    {
        m_Geometry2Ds[s*m_Dimensions[2]+t*m_Dimensions[3]]=geometry2D;
        return true;
    }
	return false;
}

//##ModelId=3E155839024F
bool mitk::Geometry3D::SetGeometry2D(ipPicDescriptor* pic, int s, int t)
{
    if((pic!=NULL) && (IsValidSlice(s,t)))
    {
        itkWarningMacro("SetGeometry2D by pic assumes a plane geometry starting at (0,0,0).");

        //construct standard view
        mitk::Point3D origin, right, bottom; bool rightHanded=true;
	    mitk::Vector2D viewport(0,0);
        origin.set(0,0,s);               UnitsToMM(origin, origin);
        right.set(m_Dimensions[0],0,0);  UnitsToMM(right, right);
        bottom.set(0,m_Dimensions[1],0); UnitsToMM(bottom, bottom);

        PlaneView view_std(origin, right, bottom, viewport, viewport, rightHanded);

        mitk::PlaneGeometry::Pointer planegeometry=mitk::PlaneGeometry::New();
        planegeometry->SetPlaneView(view_std);
        planegeometry->SetSizeInUnits(m_Dimensions[0], m_Dimensions[1]);
        SetGeometry2D(planegeometry, s, t);
        return true;
    }
    return false;
}

//##ModelId=3E3453C703AF
void mitk::Geometry3D::Initialize(unsigned int dimension, const unsigned int* dimensions)
{
	m_Dimension=dimension;
	if(m_Dimensions!=NULL)
		delete m_Dimensions;
	m_Dimensions=new unsigned int[m_Dimension>4?m_Dimension:4];
	memcpy(m_Dimensions, dimensions, sizeof(unsigned int)*m_Dimension);
	if(m_Dimension<4)
	{
		unsigned int i, *p;
		for(i=0,p=m_Dimensions+m_Dimension;i<4-m_Dimension;++i, ++p)
			*p=1;
	}

	unsigned int i;
	for(i=0;i<4;++i)
	{
		m_LargestPossibleRegion.SetIndex(i, 0);
		m_LargestPossibleRegion.SetSize (i, m_Dimensions[i]);
	}

    m_Geometry2Ds.clear();

    Geometry2D::ConstPointer gnull=NULL;
    int num=m_Dimensions[2]*m_Dimensions[3];

    m_Geometry2Ds.reserve(num);
    m_Geometry2Ds.assign(num, gnull);

    //initialize m_TransformOfOrigin and m_Spacing (and m_TransformUnitsToMM/m_TransformMMToUnits).
    m_TransformOfOrigin.setIdentity();
    SetSpacing(Vector3D(1.0,1.0,1.0));

    //construct standard view
    mitk::Point3D right, bottom; bool rightHanded=true;
	mitk::Vector2D viewport(0,0);
    right.set(m_Dimensions[0],0,0); UnitsToMM(right, right);
    bottom.set(0,m_Dimensions[1],0); UnitsToMM(bottom, bottom);
    PlaneView view_std(mitk::Point3D(0,0,0), right, bottom, viewport, viewport, rightHanded);

    mitk::PlaneGeometry::Pointer planegeometry=mitk::PlaneGeometry::New();
    m_Geometry2Ds[0]=planegeometry;
    planegeometry->SetPlaneView(view_std);
    planegeometry->SetSizeInUnits(m_Dimensions[0], m_Dimensions[1]);
}

//##ModelId=3E15572E0269
mitk::Geometry3D::Geometry3D(unsigned int dimension, const unsigned int* dimensions) : m_Dimension(0), m_Dimensions(NULL), m_EvenlySpaced(true)
{
    Initialize(dimension, dimensions);
}

//##ModelId=3E3452F10253
mitk::Geometry3D::Geometry3D(const mitk::Geometry3D& right) : m_Dimensions(NULL)
{
    Initialize(right.GetDataDimension(),right.GetDimensions());
}

//##ModelId=3E3452F10393
// mitk::Geometry3D& mitk::Geometry3D::operator=(const mitk::Geometry3D& right)
// {
//     return Geometry3D(right);
// }

//##ModelId=3E3456C50067
mitk::Geometry3D::~Geometry3D()
{
    if(m_Dimensions!=NULL)
        delete m_Dimensions;
}

//##ModelId=3E3BE1F10106
bool mitk::Geometry3D::IsValidSlice(int s, int t) const
{
	return ((s>=0) && (s<m_Dimensions[2]) && (t>=0) && (t<m_Dimensions[3]));
}

//##ModelId=3E3BE1F8000C
bool mitk::Geometry3D::IsValidTime(int t) const
{
	return IsValidSlice(0, t);
}

//##ModelId=3E3BE8CF010E
void mitk::Geometry3D::SetSpacing(mitk::Vector3D aSpacing)
{
    m_Spacing = aSpacing;

    m_TransformUnitsToMM=m_TransformOfOrigin;

    mitk::Vector4D col;
    m_TransformUnitsToMM.getColumn(0, &col); col*=aSpacing.x; m_TransformUnitsToMM.setColumn(0, col);
    m_TransformUnitsToMM.getColumn(1, &col); col*=aSpacing.x; m_TransformUnitsToMM.setColumn(1, col);
    m_TransformUnitsToMM.getColumn(2, &col); col*=aSpacing.x; m_TransformUnitsToMM.setColumn(2, col);

    m_TransformMMToUnits.invert(m_TransformUnitsToMM);

    Modified();
}

//##ModelId=3E3C13F802A6
void mitk::Geometry3D::SetEvenlySpaced(bool on)
{
    m_EvenlySpaced=on;
    Modified();
}

//##ModelId=3E3C2C37031B
void mitk::Geometry3D::SetSpacing(ipPicDescriptor* pic)
{
    Vector3D spacing(m_Spacing);

    ipPicTSV_t *tsv;

    tsv = ipPicQueryTag( pic, "PIXEL SIZE" );
	if(tsv)
	{
		if((tsv->dim*tsv->n[0]>=3) && (tsv->type==ipPicFloat))
		{
			if(tsv->bpe==32)
				spacing.set(((ipFloat4_t*)tsv->value)[0], ((ipFloat4_t*)tsv->value)[1],((ipFloat4_t*)tsv->value)[2]);
			else
			if(tsv->bpe==64)
				spacing.set(((ipFloat8_t*)tsv->value)[0], ((ipFloat8_t*)tsv->value)[1],((ipFloat8_t*)tsv->value)[2]);
		}
	}
#ifdef MITK_DICOM_ENABLED
	else
	{
		tsv = ipPicQueryTag( pic, "SOURCE HEADER" );
		if( tsv )
		{
			ipFloat8_t spacing = 0;
			ipFloat8_t thickness = 1;
			ipFloat8_t fx = 1;
			ipFloat8_t fy = 1;

			if( dicomFindElement( (unsigned char *) tsv->value, 0x0018, 0x0088, &data, &len ) )
			{
				sscanf( (char *) data, "%lf", &spacing );
				itkDebugMacro( "spacing:   %5.2f mm\n" << spacing );
			}
			if( dicomFindElement( (unsigned char *) tsv->value, 0x0018, 0x0050, &data, &len ) )
			{
				sscanf( (char *) data, "%lf", &thickness );
				itkDebugMacro( "thickness: %5.2f mm\n" << thickness );

				if( thickness == 0 )
					thickness = 1;
			}
			if( dicomFindElement( (unsigned char *) tsv->value, 0x0028, 0x0030, &data, &len )
				&& len>0 && ((char *)data)[0] )
			{
				sscanf( (char *) data, "%lf\\%lf", &fy, &fx );    // row / column value
				itkDebugMacro( "fx, fy:    %5.2f/%5.2f mm\n" << fx << fy );
			}

            spacing.set(fx, fy,( spacing > 0 ? spacing : thickness));
		}
	}
#endif
	 // FIXME:
	 // nur fuer Testdatensatz
	 // spacing = Vector3D(1/3.0,1/4.0,1/5.0);
    SetSpacing(spacing);
}
<|endoftext|>


<commit_before>#include "MultiUnifiedObstacleLocator.h"

MultiUnifiedObstacleLocator::MultiUnifiedObstacleLocator() {
    DEBUG_REQUEST_REGISTER("MulitUnifiedObstacleLocator:debug:create_virtual_obstacle",
                           "Adds a virtual obstacle. Initial place and dimensions can be modified using DEBUGMODIFY",
                           false);
    DEBUG_REQUEST_REGISTER("MulitUnifiedObstacleLocator:debug:delete_all_obstacles",
                           "Deletes all obstacles hypotheses", false);
    DEBUG_REQUEST_REGISTER("MulitUnifiedObstacleLocator:debug:draw_obstacles",
                           "Draws all obstacles on the field", false);
}

MultiUnifiedObstacleLocator::~MultiUnifiedObstacleLocator() {

}

void MultiUnifiedObstacleLocator::execute() {
    // 0. clear obstacle model

    // 1. apply odometry
    for(Obstacle& obs : obstacles) {
        apply_odometry(obs);
    }

    // 2. predict if a motion model exists

    // 3. update using sensors
    // 3.1 Ultrasound
    // 3.2 Vision

    // 4. provide model
    provide_obstacle_model();

    // 5. remember stuff for next frame
    lastRobotOdometry = getOdometryData();

    do_debug();
}

void MultiUnifiedObstacleLocator::provide_obstacle_model() {
    getObstacleModel().obstacleList = obstacles;
}

void MultiUnifiedObstacleLocator::apply_odometry(Obstacle &obs) {
    Pose2D odometryDelta = lastRobotOdometry - getOdometryData();
    obs.center = odometryDelta * obs.center;
    obs.shape_points.transform(odometryDelta);
}

void MultiUnifiedObstacleLocator::do_debug() {
    double x = 1000;
    double y = 0;
    double size = 500;

    MODIFY("MulitUnifiedObstacleLocator:virtual_obstacle:x", x);
    MODIFY("MulitUnifiedObstacleLocator:virtual_obstacle:y", y);
    MODIFY("MulitUnifiedObstacleLocator:virtual_obstacle:size", size);

    DEBUG_REQUEST_ON_DEACTIVE("MulitUnifiedObstacleLocator:debug:create_virtual_obstacle",
        Obstacle obs;
        obs.center = Vector2d(x,y);
        obs.shape_points.add(-size/2, -size/2);
        obs.shape_points.add( size/2, -size/2);
        obs.shape_points.add( size/2,  size/2);
        obs.shape_points.add(-size/2,  size/2);
        obs.shape_points.transform(Pose2D(0.0, obs.center));

        obstacles.push_back(std::move(obs));
    );

    DEBUG_REQUEST("MulitUnifiedObstacleLocator:debug:delete_all_obstacles",
        obstacles.clear();
    );

    DEBUG_REQUEST("MulitUnifiedObstacleLocator:debug:draw_obstacles",
        FIELD_DRAWING_CONTEXT;
        for(const Obstacle& obs : obstacles) {
            auto points = obs.shape_points.getPoints();
            for(int i = 0; i+1 < points.size(); ++i) {
                LINE(points[i].x, points[i].y, points[i+1].x, points[i+1].y);
            }

            LINE(points.back().x, points.back().y, points.front().x, points.front().y);
        }
    );

}
<commit_msg>compile fix in ObstacleLocator<commit_after>#include "MultiUnifiedObstacleLocator.h"

MultiUnifiedObstacleLocator::MultiUnifiedObstacleLocator() {
    DEBUG_REQUEST_REGISTER("MulitUnifiedObstacleLocator:debug:create_virtual_obstacle",
                           "Adds a virtual obstacle. Initial place and dimensions can be modified using DEBUGMODIFY",
                           false);
    DEBUG_REQUEST_REGISTER("MulitUnifiedObstacleLocator:debug:delete_all_obstacles",
                           "Deletes all obstacles hypotheses", false);
    DEBUG_REQUEST_REGISTER("MulitUnifiedObstacleLocator:debug:draw_obstacles",
                           "Draws all obstacles on the field", false);
}

MultiUnifiedObstacleLocator::~MultiUnifiedObstacleLocator() {

}

void MultiUnifiedObstacleLocator::execute() {
    // 0. clear obstacle model

    // 1. apply odometry
    for(Obstacle& obs : obstacles) {
        apply_odometry(obs);
    }

    // 2. predict if a motion model exists

    // 3. update using sensors
    // 3.1 Ultrasound
    // 3.2 Vision

    // 4. provide model
    provide_obstacle_model();

    // 5. remember stuff for next frame
    lastRobotOdometry = getOdometryData();

    do_debug();
}

void MultiUnifiedObstacleLocator::provide_obstacle_model() {
    getObstacleModel().obstacleList = obstacles;
}

void MultiUnifiedObstacleLocator::apply_odometry(Obstacle &obs) {
    Pose2D odometryDelta = lastRobotOdometry - getOdometryData();
    obs.center = odometryDelta * obs.center;
    obs.shape_points.transform(odometryDelta);
}

void MultiUnifiedObstacleLocator::do_debug() {
    double x = 1000;
    double y = 0;
    double size = 500;

    MODIFY("MulitUnifiedObstacleLocator:virtual_obstacle:x", x);
    MODIFY("MulitUnifiedObstacleLocator:virtual_obstacle:y", y);
    MODIFY("MulitUnifiedObstacleLocator:virtual_obstacle:size", size);

    DEBUG_REQUEST_ON_DEACTIVE("MulitUnifiedObstacleLocator:debug:create_virtual_obstacle",
        Obstacle obs;
        obs.center = Vector2d(x,y);
        obs.shape_points.add(-size/2, -size/2);
        obs.shape_points.add( size/2, -size/2);
        obs.shape_points.add( size/2,  size/2);
        obs.shape_points.add(-size/2,  size/2);
        obs.shape_points.transform(Pose2D(0.0, obs.center));

        obstacles.push_back(std::move(obs));
    );

    DEBUG_REQUEST("MulitUnifiedObstacleLocator:debug:delete_all_obstacles",
        obstacles.clear();
    );

    DEBUG_REQUEST("MulitUnifiedObstacleLocator:debug:draw_obstacles",
        FIELD_DRAWING_CONTEXT;
        for(const Obstacle& obs : obstacles) {
            auto points = obs.shape_points.getPoints();
            for(size_t i = 0; i+1 < points.size(); ++i) {
                LINE(points[i].x, points[i].y, points[i+1].x, points[i+1].y);
            }

            LINE(points.back().x, points.back().y, points.front().x, points.front().y);
        }
    );

}
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright UMC Utrecht and contributors
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

// First include the header file to be tested:
#include "elastixlib.h"

// ITK header files:
#include <itkImage.h>
#include <itkImageRegionRange.h>

// GoogleTest header file:
#include <gtest/gtest.h>

#include <algorithm> // For transform.
#include <array>
#include <initializer_list>
#include <limits>
#include <vector>

namespace
{

// Converts the specified strings to an array of double.
// Assumes that each string represents a floating point number.
template <unsigned VDimension>
std::array<double, VDimension>
ConvertStringsToArrayOfDouble(const std::vector<std::string> & strings)
{
  // Wrap ASSERT_EQ in a lambda, because it returns void!
  [&strings] { ASSERT_EQ(strings.size(), VDimension); }();

  std::array<double, VDimension> result;

  for (std::size_t i{}; i < VDimension; ++i)
  {
    const auto & str = strings[i];
    std::size_t  index{};
    result[i] = std::stod(str, &index);

    // Test that all characters have been processed, by std::stod.
    [&str, index] { ASSERT_EQ(str.size(), index); }();
  }

  return result;
}

// Converts the specified array of double to itk::Offset, by rounding each element.
template <std::size_t VDimension>
itk::Offset<VDimension>
ConvertArrayOfDoubleToOffset(const std::array<double, VDimension> & doubles)
{
  itk::Offset<VDimension> result;

  for (std::size_t i{}; i < VDimension; ++i)
  {
    const auto roundedValue = std::round(doubles[i]);

    // Wrap ASSERT calls in a lambda, because they return void!
    [roundedValue] {
      ASSERT_GE(roundedValue, std::numeric_limits<itk::OffsetValueType>::min());
      ASSERT_LE(roundedValue, std::numeric_limits<itk::OffsetValueType>::max());
    }();

    result[i] = static_cast<itk::OffsetValueType>(roundedValue);
  }

  return result;
}

template <unsigned VDimension>
void
ExpectRoundedTransformParametersEqualOffset(const elastix::ELASTIX &        elastixObject,
                                            const itk::Offset<VDimension> & offset)
{
  const auto transformParameterMaps = elastixObject.GetTransformParameterMapList();

  ASSERT_TRUE(!transformParameterMaps.empty());
  EXPECT_EQ(transformParameterMaps.size(), 1);

  const auto & transformParameterMap = transformParameterMaps.front();
  const auto   found = transformParameterMap.find("TransformParameters");
  ASSERT_NE(found, transformParameterMap.cend());

  const auto transformParameters = ConvertStringsToArrayOfDouble<VDimension>(found->second);
  EXPECT_EQ(ConvertArrayOfDoubleToOffset(transformParameters), offset);
}

template <typename TPixel, unsigned int VImageDimension>
void
FillImageRegion(itk::Image<TPixel, VImageDimension> & image,
                const itk::Index<VImageDimension> &   regionIndex,
                const itk::Size<VImageDimension> &    regionSize)
{
  using ImageRegionRangeType = itk::Experimental::ImageRegionRange<itk::Image<TPixel, VImageDimension>>;
  const ImageRegionRangeType imageRegionRange{ image, itk::ImageRegion<VImageDimension>{ regionIndex, regionSize } };
  std::fill(std::begin(imageRegionRange), std::end(imageRegionRange), 1);
}

template <unsigned VImageDimension>
std::map<std::string, std::vector<std::string>>
CreateParameterMap(std::initializer_list<std::pair<std::string, std::string>> initializerList)
{
  const std::vector<std::string> imageDimensionVector = { std::to_string(VImageDimension) };

  std::map<std::string, std::vector<std::string>> result{ { "FixedImageDimension", imageDimensionVector },
                                                          { "MovingImageDimension", imageDimensionVector } };

  for (const auto & pair : initializerList)
  {
    [&pair, &result] { ASSERT_TRUE(result.insert({ pair.first, { pair.second } }).second); }();
  }
  return result;
}

} // namespace

// Tests registering two small (5x6) binary images, using the example code from
// Elastix manual paragraph "Running elastix".
GTEST_TEST(ElastixLib, ExampleFromManualRunningElastix)
{
  using elastix::ELASTIX;
  using RegistrationParametersContainerType = ELASTIX::ParameterMapListType;
  using ITKImageType = itk::Image<float>;
  constexpr auto ImageDimension = ITKImageType::ImageDimension;

  const auto parameters = CreateParameterMap<ImageDimension>({
    // Parameters with non-default values (A-Z):
    { "ImageSampler", "Full" },
    { "MaximumNumberOfIterations", "2" }, // Default value: 500
    { "Metric", "AdvancedNormalizedCorrelation" },
    { "NumberOfResolutions", "2" }, // Default value: 3
    { "Optimizer", "AdaptiveStochasticGradientDescent" },
    { "Transform", "TranslationTransform" },
    // Parameters with default values (A-Z):
    { "ASGDParameterEstimationMethod", "Original" },
    { "AutomaticParameterEstimation", "true" },
    { "AutomaticTransformInitialization", "false" },
    { "BSplineInterpolationOrder", "1" },
    { "CheckNumberOfSamples", "true" },
    { "FinalBSplineInterpolationOrder", "3" },
    { "FixedImagePyramid", "FixedSmoothingImagePyramid" },
    { "FixedInternalImagePixelType", "float" },
    { "Interpolator", "BSplineInterpolator" },
    { "MaxBandCovSize", "192" },
    { "MaximumNumberOfSamplingAttempts", "0" },
    { "MaximumStepLength", "1" },
    { "MaximumStepLengthRatio", "1" },
    { "MovingImagePyramid", "MovingSmoothingImagePyramid" },
    { "MovingInternalImagePixelType", "float" },
    { "NewSamplesEveryIteration", "false" },
    { "NumberOfBandStructureSamples", "10" },
    { "NumberOfGradientMeasurements", "0" },
    { "NumberOfJacobianMeasurements", "1000" },
    { "NumberOfSamplesForExactGradient", "100000" },
    { "Registration", "MultiResolutionRegistration" },
    { "ResampleInterpolator", "FinalBSplineInterpolator" },
    { "Resampler", "DefaultResampler" },
    { "ShowExactMetricValue", "false" },
    { "SigmoidInitialTime", "0" },
    { "SigmoidScaleFactor", "0.1" },
    { "SP_A", "20" },
    { "SubtractMean", "true" },
    { "UseAdaptiveStepSizes", "true" },
    { "UseConstantStep", "false" },
    { "UseDirectionCosines", "true" },
    { "UseMultiThreadingForMetrics", "true" },
    { "WriteResultImage", "true" },
  });

  const itk::Size<ImageDimension>   imageSize{ { 5, 6 } };
  const itk::Size<ImageDimension>   regionSize = itk::Size<ImageDimension>::Filled(2);
  const itk::Index<ImageDimension>  fixedImageRegionIndex{ { 1, 3 } };
  const itk::Offset<ImageDimension> translationOffset{ { 1, -2 } };

  const auto fixed_image = ITKImageType::New();
  fixed_image->SetRegions(imageSize);
  fixed_image->Allocate(true);
  FillImageRegion(*fixed_image, fixedImageRegionIndex, regionSize);

  const auto moving_image = ITKImageType::New();
  moving_image->SetRegions(imageSize);
  moving_image->Allocate(true);
  FillImageRegion(*moving_image, fixedImageRegionIndex + translationOffset, regionSize);

  const std::string output_directory(".");
  const bool        write_log_file{ false };
  const bool        output_to_console{ false };

  //////////////////////////////////////////////////////////////////////////
  // Code snippet from Manual paragraph "Running elastix" starts here >>>
  ELASTIX elastix;
  int     error = 0;
  try
  {
    error = elastix.RegisterImages(static_cast<typename itk::DataObject::Pointer>(fixed_image.GetPointer()),
                                   static_cast<typename itk::DataObject::Pointer>(moving_image.GetPointer()),
                                   parameters,        // Parameter map read in previous code
                                   output_directory,  // Directory where output is written, if enabled
                                   write_log_file,    // Enable/disable writing of elastix.log
                                   output_to_console, // Enable/disable output to console
                                   nullptr,           // Provide fixed image mask (optional, nullptr = no mask)
                                   nullptr            // Provide moving image mask (optional, nullptr = no mask)
    );
  }
  catch (itk::ExceptionObject & err)
  {
    // Do some error handling.
    std::cerr << err.what() << '\n';
  }

  if (error == 0)
  {
    if (elastix.GetResultImage().IsNotNull())
    {
      // Typedef the ITKImageType first...
      ITKImageType * output_image = static_cast<ITKImageType *>(elastix.GetResultImage().GetPointer());
      EXPECT_NE(output_image, nullptr);
    }
  }
  else
  {
    // Registration failure. Do some error handling.
  }

  // Get transform parameters of all registration steps.
  RegistrationParametersContainerType transform_parameters = elastix.GetTransformParameterMapList();

  // <<< Code snippet from Manual paragraph "Running elastix" ends here
  //////////////////////////////////////////////////////////////////////////

  ExpectRoundedTransformParametersEqualOffset(elastix, translationOffset);
}

// Tests that the TransformParameters of a translation are all zero when the
// fixed and the moving image are the same.
GTEST_TEST(ElastixLib, TranslationTransformParametersAreZeroWhenFixedImageIsMovingImage)
{
  using ImageType = itk::Image<float>;
  constexpr auto ImageDimension = ImageType::ImageDimension;
  using SizeType = itk::Size<ImageDimension>;

  const auto parameterMap = CreateParameterMap<ImageDimension>({ { "ImageSampler", "Full" },
                                                                 { "Metric", "AdvancedNormalizedCorrelation" },
                                                                 { "Optimizer", "AdaptiveStochasticGradientDescent" },
                                                                 { "Transform", "TranslationTransform" } });

  const auto indexValue = 1;
  const auto regionSizeValue = 2;
  const auto imageSizeValue = 4;

  const auto image = ImageType::New();
  image->SetRegions(SizeType::Filled(imageSizeValue));
  image->Allocate(true);
  FillImageRegion(*image, { { indexValue, indexValue } }, SizeType::Filled(regionSizeValue));

  elastix::ELASTIX elastixObject;
  ASSERT_EQ(elastixObject.RegisterImages(image, image, parameterMap, ".", false, false), 0);

  const auto transformParameterMaps = elastixObject.GetTransformParameterMapList();

  ASSERT_TRUE(!transformParameterMaps.empty());
  EXPECT_EQ(transformParameterMaps.size(), 1);

  const auto & transformParameterMap = transformParameterMaps.front();
  const auto   found = transformParameterMap.find("TransformParameters");
  ASSERT_NE(found, transformParameterMap.cend());

  const auto & transformParameters = found->second;
  ASSERT_EQ(transformParameters.size(), ImageDimension);

  for (const auto & transformParameter : transformParameters)
  {
    EXPECT_EQ(transformParameter, "0");
  }
}

// Tests registering two small binary images.
GTEST_TEST(ElastixLib, Translation3D)
{
  constexpr auto ImageDimension = 3;
  using ImageType = itk::Image<float, ImageDimension>;

  const auto parameterMap =
    CreateParameterMap<ImageDimension>({ { "ImageSampler", "Full" },
                                         { "MaximumNumberOfIterations", "3" },
                                         { "Metric", "AdvancedNormalizedCorrelation" },
                                         { "Optimizer", "AdaptiveStochasticGradientDescent" },
                                         { "Transform", "TranslationTransform" } });

  const itk::Size<ImageDimension>   imageSize{ { 5, 7, 9 } };
  const itk::Size<ImageDimension>   regionSize = itk::Size<ImageDimension>::Filled(2);
  const itk::Index<ImageDimension>  fixedImageRegionIndex{ { 1, 2, 3 } };
  const itk::Offset<ImageDimension> translationOffset{ { 1, 2, 3 } };

  const auto fixedImage = ImageType::New();
  fixedImage->SetRegions(imageSize);
  fixedImage->Allocate(true);
  FillImageRegion(*fixedImage, fixedImageRegionIndex, regionSize);

  const auto movingImage = ImageType::New();
  movingImage->SetRegions(imageSize);
  movingImage->Allocate(true);
  FillImageRegion(*movingImage, fixedImageRegionIndex + translationOffset, regionSize);

  elastix::ELASTIX elastixObject;

  ASSERT_EQ(elastixObject.RegisterImages(fixedImage, movingImage, parameterMap, ".", false, false), 0);
  ExpectRoundedTransformParametersEqualOffset(elastixObject, translationOffset);
}
<commit_msg>ENH: Add GoogleTest test for short pixel types<commit_after>/*=========================================================================
 *
 *  Copyright UMC Utrecht and contributors
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

// First include the header file to be tested:
#include "elastixlib.h"

// ITK header files:
#include <itkImage.h>
#include <itkImageRegionRange.h>

// GoogleTest header file:
#include <gtest/gtest.h>

#include <algorithm> // For transform.
#include <array>
#include <initializer_list>
#include <limits>
#include <vector>

namespace
{

template <typename>
constexpr const char *
GetPixelTypeName() = delete;

template <>
constexpr const char *
GetPixelTypeName<short>()
{
  return "short";
}

template <>
constexpr const char *
GetPixelTypeName<float>()
{
  return "float";
}

// Converts the specified strings to an array of double.
// Assumes that each string represents a floating point number.
template <unsigned VDimension>
std::array<double, VDimension>
ConvertStringsToArrayOfDouble(const std::vector<std::string> & strings)
{
  // Wrap ASSERT_EQ in a lambda, because it returns void!
  [&strings] { ASSERT_EQ(strings.size(), VDimension); }();

  std::array<double, VDimension> result;

  for (std::size_t i{}; i < VDimension; ++i)
  {
    const auto & str = strings[i];
    std::size_t  index{};
    result[i] = std::stod(str, &index);

    // Test that all characters have been processed, by std::stod.
    [&str, index] { ASSERT_EQ(str.size(), index); }();
  }

  return result;
}

// Converts the specified array of double to itk::Offset, by rounding each element.
template <std::size_t VDimension>
itk::Offset<VDimension>
ConvertArrayOfDoubleToOffset(const std::array<double, VDimension> & doubles)
{
  itk::Offset<VDimension> result;

  for (std::size_t i{}; i < VDimension; ++i)
  {
    const auto roundedValue = std::round(doubles[i]);

    // Wrap ASSERT calls in a lambda, because they return void!
    [roundedValue] {
      ASSERT_GE(roundedValue, std::numeric_limits<itk::OffsetValueType>::min());
      ASSERT_LE(roundedValue, std::numeric_limits<itk::OffsetValueType>::max());
    }();

    result[i] = static_cast<itk::OffsetValueType>(roundedValue);
  }

  return result;
}

template <unsigned VDimension>
void
ExpectRoundedTransformParametersEqualOffset(const elastix::ELASTIX &        elastixObject,
                                            const itk::Offset<VDimension> & offset)
{
  const auto transformParameterMaps = elastixObject.GetTransformParameterMapList();

  ASSERT_TRUE(!transformParameterMaps.empty());
  EXPECT_EQ(transformParameterMaps.size(), 1);

  const auto & transformParameterMap = transformParameterMaps.front();
  const auto   found = transformParameterMap.find("TransformParameters");
  ASSERT_NE(found, transformParameterMap.cend());

  const auto transformParameters = ConvertStringsToArrayOfDouble<VDimension>(found->second);
  EXPECT_EQ(ConvertArrayOfDoubleToOffset(transformParameters), offset);
}

template <typename TPixel, unsigned int VImageDimension>
void
FillImageRegion(itk::Image<TPixel, VImageDimension> & image,
                const itk::Index<VImageDimension> &   regionIndex,
                const itk::Size<VImageDimension> &    regionSize)
{
  using ImageRegionRangeType = itk::Experimental::ImageRegionRange<itk::Image<TPixel, VImageDimension>>;
  const ImageRegionRangeType imageRegionRange{ image, itk::ImageRegion<VImageDimension>{ regionIndex, regionSize } };
  std::fill(std::begin(imageRegionRange), std::end(imageRegionRange), 1);
}

template <unsigned VImageDimension>
std::map<std::string, std::vector<std::string>>
CreateParameterMap(std::initializer_list<std::pair<std::string, std::string>> initializerList)
{
  const std::vector<std::string> imageDimensionVector = { std::to_string(VImageDimension) };

  std::map<std::string, std::vector<std::string>> result{ { "FixedImageDimension", imageDimensionVector },
                                                          { "MovingImageDimension", imageDimensionVector } };

  for (const auto & pair : initializerList)
  {
    [&pair, &result] { ASSERT_TRUE(result.insert({ pair.first, { pair.second } }).second); }();
  }
  return result;
}

template <unsigned VImageDimension, typename TPixel = float>
void
Expect_TransformParameters_are_zero_when_fixed_image_is_moving_image()
{
  using ImageType = itk::Image<TPixel, VImageDimension>;
  using SizeType = itk::Size<VImageDimension>;

  const auto parameterMap =
    CreateParameterMap<VImageDimension>({ { "ImageSampler", "Full" },
                                          { "FixedInternalImagePixelType", GetPixelTypeName<TPixel>() },
                                          { "Metric", "AdvancedNormalizedCorrelation" },
                                          { "MovingInternalImagePixelType", GetPixelTypeName<TPixel>() },
                                          { "Optimizer", "AdaptiveStochasticGradientDescent" },
                                          { "Transform", "TranslationTransform" } });

  const auto regionSizeValue = 2;
  const auto imageSizeValue = 4;

  const auto image = ImageType::New();
  image->SetRegions(SizeType::Filled(imageSizeValue));
  image->Allocate(true);
  FillImageRegion(*image, itk::Index<VImageDimension>::Filled(1), SizeType::Filled(regionSizeValue));

  elastix::ELASTIX elastixObject;
  ASSERT_EQ(elastixObject.RegisterImages(image, image, parameterMap, ".", false, false), 0);

  const auto transformParameterMaps = elastixObject.GetTransformParameterMapList();

  ASSERT_TRUE(!transformParameterMaps.empty());
  EXPECT_EQ(transformParameterMaps.size(), 1);

  const auto & transformParameterMap = transformParameterMaps.front();
  const auto   found = transformParameterMap.find("TransformParameters");
  ASSERT_NE(found, transformParameterMap.cend());

  const auto & transformParameters = found->second;
  ASSERT_EQ(transformParameters.size(), VImageDimension);

  for (const auto & transformParameter : transformParameters)
  {
    EXPECT_EQ(transformParameter, "0");
  }
}

} // namespace

// Tests registering two small (5x6) binary images, using the example code from
// Elastix manual paragraph "Running elastix".
GTEST_TEST(ElastixLib, ExampleFromManualRunningElastix)
{
  using elastix::ELASTIX;
  using RegistrationParametersContainerType = ELASTIX::ParameterMapListType;
  using ITKImageType = itk::Image<float>;
  constexpr auto ImageDimension = ITKImageType::ImageDimension;

  const auto parameters = CreateParameterMap<ImageDimension>({
    // Parameters with non-default values (A-Z):
    { "ImageSampler", "Full" },
    { "MaximumNumberOfIterations", "2" }, // Default value: 500
    { "Metric", "AdvancedNormalizedCorrelation" },
    { "NumberOfResolutions", "2" }, // Default value: 3
    { "Optimizer", "AdaptiveStochasticGradientDescent" },
    { "Transform", "TranslationTransform" },
    // Parameters with default values (A-Z):
    { "ASGDParameterEstimationMethod", "Original" },
    { "AutomaticParameterEstimation", "true" },
    { "AutomaticTransformInitialization", "false" },
    { "BSplineInterpolationOrder", "1" },
    { "CheckNumberOfSamples", "true" },
    { "FinalBSplineInterpolationOrder", "3" },
    { "FixedImagePyramid", "FixedSmoothingImagePyramid" },
    { "FixedInternalImagePixelType", "float" },
    { "Interpolator", "BSplineInterpolator" },
    { "MaxBandCovSize", "192" },
    { "MaximumNumberOfSamplingAttempts", "0" },
    { "MaximumStepLength", "1" },
    { "MaximumStepLengthRatio", "1" },
    { "MovingImagePyramid", "MovingSmoothingImagePyramid" },
    { "MovingInternalImagePixelType", "float" },
    { "NewSamplesEveryIteration", "false" },
    { "NumberOfBandStructureSamples", "10" },
    { "NumberOfGradientMeasurements", "0" },
    { "NumberOfJacobianMeasurements", "1000" },
    { "NumberOfSamplesForExactGradient", "100000" },
    { "Registration", "MultiResolutionRegistration" },
    { "ResampleInterpolator", "FinalBSplineInterpolator" },
    { "Resampler", "DefaultResampler" },
    { "ShowExactMetricValue", "false" },
    { "SigmoidInitialTime", "0" },
    { "SigmoidScaleFactor", "0.1" },
    { "SP_A", "20" },
    { "SubtractMean", "true" },
    { "UseAdaptiveStepSizes", "true" },
    { "UseConstantStep", "false" },
    { "UseDirectionCosines", "true" },
    { "UseMultiThreadingForMetrics", "true" },
    { "WriteResultImage", "true" },
  });

  const itk::Size<ImageDimension>   imageSize{ { 5, 6 } };
  const itk::Size<ImageDimension>   regionSize = itk::Size<ImageDimension>::Filled(2);
  const itk::Index<ImageDimension>  fixedImageRegionIndex{ { 1, 3 } };
  const itk::Offset<ImageDimension> translationOffset{ { 1, -2 } };

  const auto fixed_image = ITKImageType::New();
  fixed_image->SetRegions(imageSize);
  fixed_image->Allocate(true);
  FillImageRegion(*fixed_image, fixedImageRegionIndex, regionSize);

  const auto moving_image = ITKImageType::New();
  moving_image->SetRegions(imageSize);
  moving_image->Allocate(true);
  FillImageRegion(*moving_image, fixedImageRegionIndex + translationOffset, regionSize);

  const std::string output_directory(".");
  const bool        write_log_file{ false };
  const bool        output_to_console{ false };

  //////////////////////////////////////////////////////////////////////////
  // Code snippet from Manual paragraph "Running elastix" starts here >>>
  ELASTIX elastix;
  int     error = 0;
  try
  {
    error = elastix.RegisterImages(static_cast<typename itk::DataObject::Pointer>(fixed_image.GetPointer()),
                                   static_cast<typename itk::DataObject::Pointer>(moving_image.GetPointer()),
                                   parameters,        // Parameter map read in previous code
                                   output_directory,  // Directory where output is written, if enabled
                                   write_log_file,    // Enable/disable writing of elastix.log
                                   output_to_console, // Enable/disable output to console
                                   nullptr,           // Provide fixed image mask (optional, nullptr = no mask)
                                   nullptr            // Provide moving image mask (optional, nullptr = no mask)
    );
  }
  catch (itk::ExceptionObject & err)
  {
    // Do some error handling.
    std::cerr << err.what() << '\n';
  }

  if (error == 0)
  {
    if (elastix.GetResultImage().IsNotNull())
    {
      // Typedef the ITKImageType first...
      ITKImageType * output_image = static_cast<ITKImageType *>(elastix.GetResultImage().GetPointer());
      EXPECT_NE(output_image, nullptr);
    }
  }
  else
  {
    // Registration failure. Do some error handling.
  }

  // Get transform parameters of all registration steps.
  RegistrationParametersContainerType transform_parameters = elastix.GetTransformParameterMapList();

  // <<< Code snippet from Manual paragraph "Running elastix" ends here
  //////////////////////////////////////////////////////////////////////////

  ExpectRoundedTransformParametersEqualOffset(elastix, translationOffset);
}

// Tests that the TransformParameters of a translation are all zero when the
// fixed and the moving image are the same.
GTEST_TEST(ElastixLib, TransformParametersAreZeroWhenFixedImageIsMovingImage)
{
  Expect_TransformParameters_are_zero_when_fixed_image_is_moving_image<2>();
  Expect_TransformParameters_are_zero_when_fixed_image_is_moving_image<3>();
}

// Tests specifically for pixel type short that the TransformParameters of a
// translation are all zero when the fixed and the moving image are the same.
GTEST_TEST(ElastixLib, ForShortPixelsTransformParametersAreZeroWhenFixedImageIsMovingImage)
{
  Expect_TransformParameters_are_zero_when_fixed_image_is_moving_image<3, short>();
}

// Tests registering two small binary images.
GTEST_TEST(ElastixLib, Translation3D)
{
  constexpr auto ImageDimension = 3;
  using ImageType = itk::Image<float, ImageDimension>;

  const auto parameterMap =
    CreateParameterMap<ImageDimension>({ { "ImageSampler", "Full" },
                                         { "MaximumNumberOfIterations", "3" },
                                         { "Metric", "AdvancedNormalizedCorrelation" },
                                         { "Optimizer", "AdaptiveStochasticGradientDescent" },
                                         { "Transform", "TranslationTransform" } });

  const itk::Size<ImageDimension>   imageSize{ { 5, 7, 9 } };
  const itk::Size<ImageDimension>   regionSize = itk::Size<ImageDimension>::Filled(2);
  const itk::Index<ImageDimension>  fixedImageRegionIndex{ { 1, 2, 3 } };
  const itk::Offset<ImageDimension> translationOffset{ { 1, 2, 3 } };

  const auto fixedImage = ImageType::New();
  fixedImage->SetRegions(imageSize);
  fixedImage->Allocate(true);
  FillImageRegion(*fixedImage, fixedImageRegionIndex, regionSize);

  const auto movingImage = ImageType::New();
  movingImage->SetRegions(imageSize);
  movingImage->Allocate(true);
  FillImageRegion(*movingImage, fixedImageRegionIndex + translationOffset, regionSize);

  elastix::ELASTIX elastixObject;

  ASSERT_EQ(elastixObject.RegisterImages(fixedImage, movingImage, parameterMap, ".", false, false), 0);
  ExpectRoundedTransformParametersEqualOffset(elastixObject, translationOffset);
}
<|endoftext|>


<commit_before>/***********************************************************************************************************************
 **
 ** Copyright (c) 2011, 2015 ETH Zurich
 ** All rights reserved.
 **
 ** Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
 ** following conditions are met:
 **
 **    * Redistributions of source code must retain the above copyright notice, this list of conditions and the
 **      following disclaimer.
 **    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
 **      following disclaimer in the documentation and/or other materials provided with the distribution.
 **    * Neither the name of the ETH Zurich 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 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 **
 **********************************************************************************************************************/

#include "CppExporter.h"
#include "../visitors/header_visitors/DeclarationVisitorHeader.h"
#include "../visitors/source_visitors/DeclarationVisitorSource.h"

#include "OOModel/src/declarations/Project.h"

#include "Export/src/writer/Exporter.h"
#include "Export/src/writer/FragmentLayouter.h"
#include "ModelBase/src/model/TreeManager.h"

#include "CodeUnit.h"
#include "CodeComposite.h"

namespace CppExport {

QList<ExportError> CppExporter::exportTree(Model::TreeManager* manager, const QString& pathToProjectContainerDirectory)
{
	auto project = DCast<OOModel::Project>(manager->root());
	Q_ASSERT(project);

	auto codeComposite = new CodeComposite("Composite");
	for (auto i = 0; i < project->classes()->size(); i++)
	{
		auto c = project->classes()->at(i);
		//if (c->name() == "HelloWorld" || c->name() == "Generic")
		{
			auto unit = new CodeUnit(c->name(), c);
			codeComposite->addUnit(unit);
		}
	}

	exportCodeComposite(codeComposite);

	return {};

	auto layout = layouter();

	DeclarationVisitorHeader visitor;
	auto dir = std::unique_ptr<Export::SourceDir>( visitor.visitProject(project) );
	auto map = Export::Exporter::exportToFileSystem(pathToProjectContainerDirectory + "/Headers", dir.get(), &layout);
	exportMaps().insert(project, map);

	DeclarationVisitorSource visitor2;
	auto dir2 = std::unique_ptr<Export::SourceDir>( visitor2.visitProject(project) );
	auto map2 = Export::Exporter::exportToFileSystem(pathToProjectContainerDirectory + "/Sources", dir2.get(), &layout);
	exportMaps().insert(project, map2);

	return visitor.errors();
}

void CppExporter::exportFragment(Export::SourceFragment* fragment)
{
	auto dir = new Export::SourceDir(nullptr, "src");
	auto file = &dir->file("exported.h");
	file->append(fragment);
	auto layout = layouter();
	Export::Exporter::exportToFileSystem("", dir, &layout);
}

void CppExporter::calculateSourceFragments(CodeComposite* codeComposite)
{
	DeclarationVisitorHeader visitor;
	for (auto unit : codeComposite->units())
		if (auto classs = DCast<OOModel::Class>(unit->node()))
			unit->setSourceFragment(visitor.visitTopLevelClass(classs));
		else
			Q_ASSERT(false);
}

void CppExporter::exportCodeComposite(CodeComposite* codeComposite)
{
	calculateSourceFragments(codeComposite);

	auto composite = new Export::CompositeFragment(new Model::Integer());
	for (auto unit : codeComposite->units())
		composite->append(unit->sourceFragment());

	exportFragment(composite);
}

Export::FragmentLayouter CppExporter::layouter()
{
	auto result = Export::FragmentLayouter{"\t"};
	result.addRule("enumerators", Export::FragmentLayouter::SpaceAfterSeparator, "", ",", "");
	result.addRule("vertical", Export::FragmentLayouter::NoIndentation, "", "\n", "");
	result.addRule("sections", Export::FragmentLayouter::NoIndentation, "", "\n", "");
	result.addRule("accessorSections", Export::FragmentLayouter::IndentChildFragments, "", "\n", "");
	result.addRule("bodySections", Export::FragmentLayouter::NewLineBefore
						  | Export::FragmentLayouter::IndentChildFragments | Export::FragmentLayouter::NewLineAfterPrefix
						  | Export::FragmentLayouter::NewLineBeforePostfix, "{", "\n", "}");
	result.addRule("space", Export::FragmentLayouter::SpaceAtEnd, "", " ", "");
	result.addRule("comma", Export::FragmentLayouter::SpaceAfterSeparator, "", ",", "");
	result.addRule("baseClasses", Export::FragmentLayouter::SpaceAfterSeparator, "public: ", ",", "");
	result.addRule("initializerList", Export::FragmentLayouter::SpaceAfterSeparator, "{", ",", "}");
	result.addRule("argsList", Export::FragmentLayouter::SpaceAfterSeparator, "(", ",", ")");
	result.addRule("typeArgsList", Export::FragmentLayouter::SpaceAfterSeparator, "<", ",", ">");

	result.addRule("body", Export::FragmentLayouter::NewLineBefore | Export::FragmentLayouter::IndentChildFragments
							| Export::FragmentLayouter::NewLineAfterPrefix | Export::FragmentLayouter::NewLineBeforePostfix,
							"{", "\n", "}");

	return result;
}

Export::ExportMapContainer& CppExporter::exportMaps()
{
	static Export::ExportMapContainer* container = new Export::ExportMapContainer();
	return *container;
}

}
<commit_msg>rename visitors<commit_after>/***********************************************************************************************************************
 **
 ** Copyright (c) 2011, 2015 ETH Zurich
 ** All rights reserved.
 **
 ** Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
 ** following conditions are met:
 **
 **    * Redistributions of source code must retain the above copyright notice, this list of conditions and the
 **      following disclaimer.
 **    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
 **      following disclaimer in the documentation and/or other materials provided with the distribution.
 **    * Neither the name of the ETH Zurich 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 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 **
 **********************************************************************************************************************/

#include "CppExporter.h"
#include "../visitors/header_visitors/DeclarationVisitorHeader.h"
#include "../visitors/source_visitors/DeclarationVisitorSource.h"

#include "OOModel/src/declarations/Project.h"

#include "Export/src/writer/Exporter.h"
#include "Export/src/writer/FragmentLayouter.h"
#include "ModelBase/src/model/TreeManager.h"

#include "CodeUnit.h"
#include "CodeComposite.h"

namespace CppExport {

QList<ExportError> CppExporter::exportTree(Model::TreeManager* manager, const QString& pathToProjectContainerDirectory)
{
	auto project = DCast<OOModel::Project>(manager->root());
	Q_ASSERT(project);

	auto codeComposite = new CodeComposite("Composite");
	for (auto i = 0; i < project->classes()->size(); i++)
	{
		auto c = project->classes()->at(i);
		//if (c->name() == "HelloWorld" || c->name() == "Generic")
		{
			auto unit = new CodeUnit(c->name(), c);
			codeComposite->addUnit(unit);
		}
	}

	exportCodeComposite(codeComposite);

	return {};

	auto layout = layouter();

	DeclarationVisitorHeader headerVisitor;
	auto dir = std::unique_ptr<Export::SourceDir>( headerVisitor.visitProject(project) );
	auto map = Export::Exporter::exportToFileSystem(pathToProjectContainerDirectory + "/Headers", dir.get(), &layout);
	exportMaps().insert(project, map);

	DeclarationVisitorSource sourceVisitor;
	auto dir2 = std::unique_ptr<Export::SourceDir>( sourceVisitor.visitProject(project) );
	auto map2 = Export::Exporter::exportToFileSystem(pathToProjectContainerDirectory + "/Sources", dir2.get(), &layout);
	exportMaps().insert(project, map2);

	return headerVisitor.errors();
}

void CppExporter::exportFragment(Export::SourceFragment* fragment)
{
	auto dir = new Export::SourceDir(nullptr, "src");
	auto file = &dir->file("exported.h");
	file->append(fragment);
	auto layout = layouter();
	Export::Exporter::exportToFileSystem("", dir, &layout);
}

void CppExporter::calculateSourceFragments(CodeComposite* codeComposite)
{
	DeclarationVisitorHeader visitor;
	for (auto unit : codeComposite->units())
		if (auto classs = DCast<OOModel::Class>(unit->node()))
			unit->setSourceFragment(visitor.visitTopLevelClass(classs));
		else
			Q_ASSERT(false);
}

void CppExporter::exportCodeComposite(CodeComposite* codeComposite)
{
	calculateSourceFragments(codeComposite);

	auto composite = new Export::CompositeFragment(new Model::Integer());
	for (auto unit : codeComposite->units())
		composite->append(unit->sourceFragment());

	exportFragment(composite);
}

Export::FragmentLayouter CppExporter::layouter()
{
	auto result = Export::FragmentLayouter{"\t"};
	result.addRule("enumerators", Export::FragmentLayouter::SpaceAfterSeparator, "", ",", "");
	result.addRule("vertical", Export::FragmentLayouter::NoIndentation, "", "\n", "");
	result.addRule("sections", Export::FragmentLayouter::NoIndentation, "", "\n", "");
	result.addRule("accessorSections", Export::FragmentLayouter::IndentChildFragments, "", "\n", "");
	result.addRule("bodySections", Export::FragmentLayouter::NewLineBefore
						  | Export::FragmentLayouter::IndentChildFragments | Export::FragmentLayouter::NewLineAfterPrefix
						  | Export::FragmentLayouter::NewLineBeforePostfix, "{", "\n", "}");
	result.addRule("space", Export::FragmentLayouter::SpaceAtEnd, "", " ", "");
	result.addRule("comma", Export::FragmentLayouter::SpaceAfterSeparator, "", ",", "");
	result.addRule("baseClasses", Export::FragmentLayouter::SpaceAfterSeparator, "public: ", ",", "");
	result.addRule("initializerList", Export::FragmentLayouter::SpaceAfterSeparator, "{", ",", "}");
	result.addRule("argsList", Export::FragmentLayouter::SpaceAfterSeparator, "(", ",", ")");
	result.addRule("typeArgsList", Export::FragmentLayouter::SpaceAfterSeparator, "<", ",", ">");

	result.addRule("body", Export::FragmentLayouter::NewLineBefore | Export::FragmentLayouter::IndentChildFragments
							| Export::FragmentLayouter::NewLineAfterPrefix | Export::FragmentLayouter::NewLineBeforePostfix,
							"{", "\n", "}");

	return result;
}

Export::ExportMapContainer& CppExporter::exportMaps()
{
	static Export::ExportMapContainer* container = new Export::ExportMapContainer();
	return *container;
}

}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: swfuno.cxx,v $
 *
 *  $Revision: 1.1 $
 *
 *  last change: $Author: cl $ $Date: 2002-11-21 14:58:03 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#include <stdio.h>

#include <osl/mutex.hxx>
#include <osl/thread.h>
#include <cppuhelper/factory.hxx>

#ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#endif

using namespace ::rtl;
using namespace ::cppu;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::registry;

namespace swf {
extern OUString FlashExportFilter_getImplementationName() throw ( RuntimeException );
extern sal_Bool SAL_CALL FlashExportFilter_supportsService( const OUString& ServiceName ) throw ( RuntimeException );
extern Sequence< OUString > SAL_CALL FlashExportFilter_getSupportedServiceNames()  throw ( RuntimeException );
extern Reference< XInterface > SAL_CALL FlashExportFilter_createInstance( const Reference< XMultiServiceFactory > & rSMgr) throw ( Exception );
}

extern rtl::OUString SWFDialog_getImplementationName () throw (com::sun::star::uno::RuntimeException);
extern com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL SWFDialog_getSupportedServiceNames() throw (com::sun::star::uno::RuntimeException);
extern com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL SWFDialog_createInstance( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > & rSMgr) throw( com::sun::star::uno::Exception );

using namespace ::swf;

extern "C"
{
//==================================================================================================
void SAL_CALL component_getImplementationEnvironment(
    const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}
//==================================================================================================

void singlecomponent_writeInfo( Reference< XRegistryKey >& xNewKey, const Sequence< OUString > & rSNL )
{
    const OUString * pArray = rSNL.getConstArray();
    for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
        xNewKey->createKey( pArray[nPos] );
}

sal_Bool SAL_CALL component_writeInfo(
    void * pServiceManager, void * pRegistryKey )
{
    if (pRegistryKey)
    {
        try
        {
            Reference< XRegistryKey > xNewKey(
                reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey( FlashExportFilter_getImplementationName() ) );
            xNewKey = xNewKey->createKey( OUString::createFromAscii( "/UNO/SERVICES" ) );

            singlecomponent_writeInfo( xNewKey, FlashExportFilter_getSupportedServiceNames() );

            xNewKey = reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey( SWFDialog_getImplementationName() );
            xNewKey = xNewKey->createKey( OUString::createFromAscii( "/UNO/SERVICES" ) );

            singlecomponent_writeInfo( xNewKey, SWFDialog_getSupportedServiceNames() );

            return sal_True;
        }
        catch (InvalidRegistryException &)
        {
            OSL_ENSURE( sal_False, "### InvalidRegistryException!" );
        }
    }
    return sal_False;
}
//==================================================================================================
void * SAL_CALL component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
    void * pRet = 0;

    if( pServiceManager )
    {
        Reference< XSingleServiceFactory > xFactory;

        OUString implName = OUString::createFromAscii( pImplName );
        if ( implName.equals(FlashExportFilter_getImplementationName()) )
        {
            xFactory = createSingleFactory(
                reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
                OUString::createFromAscii( pImplName ),
                FlashExportFilter_createInstance, FlashExportFilter_getSupportedServiceNames() );

        }
        else if ( implName.equals(SWFDialog_getImplementationName()) )
        {
            xFactory = createSingleFactory(
                reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
                OUString::createFromAscii( pImplName ),
                SWFDialog_createInstance, SWFDialog_getSupportedServiceNames() );
        }

        if (xFactory.is())
        {
            xFactory->acquire();
            pRet = xFactory.get();
        }
    }

    return pRet;
}
}
<commit_msg>INTEGRATION: CWS ooo19126 (1.1.552); FILE MERGED 2005/09/05 14:30:48 rt 1.1.552.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: swfuno.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 21:43:59 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#include <stdio.h>

#include <osl/mutex.hxx>
#include <osl/thread.h>
#include <cppuhelper/factory.hxx>

#ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#endif

using namespace ::rtl;
using namespace ::cppu;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::registry;

namespace swf {
extern OUString FlashExportFilter_getImplementationName() throw ( RuntimeException );
extern sal_Bool SAL_CALL FlashExportFilter_supportsService( const OUString& ServiceName ) throw ( RuntimeException );
extern Sequence< OUString > SAL_CALL FlashExportFilter_getSupportedServiceNames()  throw ( RuntimeException );
extern Reference< XInterface > SAL_CALL FlashExportFilter_createInstance( const Reference< XMultiServiceFactory > & rSMgr) throw ( Exception );
}

extern rtl::OUString SWFDialog_getImplementationName () throw (com::sun::star::uno::RuntimeException);
extern com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL SWFDialog_getSupportedServiceNames() throw (com::sun::star::uno::RuntimeException);
extern com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL SWFDialog_createInstance( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > & rSMgr) throw( com::sun::star::uno::Exception );

using namespace ::swf;

extern "C"
{
//==================================================================================================
void SAL_CALL component_getImplementationEnvironment(
    const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}
//==================================================================================================

void singlecomponent_writeInfo( Reference< XRegistryKey >& xNewKey, const Sequence< OUString > & rSNL )
{
    const OUString * pArray = rSNL.getConstArray();
    for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
        xNewKey->createKey( pArray[nPos] );
}

sal_Bool SAL_CALL component_writeInfo(
    void * pServiceManager, void * pRegistryKey )
{
    if (pRegistryKey)
    {
        try
        {
            Reference< XRegistryKey > xNewKey(
                reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey( FlashExportFilter_getImplementationName() ) );
            xNewKey = xNewKey->createKey( OUString::createFromAscii( "/UNO/SERVICES" ) );

            singlecomponent_writeInfo( xNewKey, FlashExportFilter_getSupportedServiceNames() );

            xNewKey = reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey( SWFDialog_getImplementationName() );
            xNewKey = xNewKey->createKey( OUString::createFromAscii( "/UNO/SERVICES" ) );

            singlecomponent_writeInfo( xNewKey, SWFDialog_getSupportedServiceNames() );

            return sal_True;
        }
        catch (InvalidRegistryException &)
        {
            OSL_ENSURE( sal_False, "### InvalidRegistryException!" );
        }
    }
    return sal_False;
}
//==================================================================================================
void * SAL_CALL component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
    void * pRet = 0;

    if( pServiceManager )
    {
        Reference< XSingleServiceFactory > xFactory;

        OUString implName = OUString::createFromAscii( pImplName );
        if ( implName.equals(FlashExportFilter_getImplementationName()) )
        {
            xFactory = createSingleFactory(
                reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
                OUString::createFromAscii( pImplName ),
                FlashExportFilter_createInstance, FlashExportFilter_getSupportedServiceNames() );

        }
        else if ( implName.equals(SWFDialog_getImplementationName()) )
        {
            xFactory = createSingleFactory(
                reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
                OUString::createFromAscii( pImplName ),
                SWFDialog_createInstance, SWFDialog_getSupportedServiceNames() );
        }

        if (xFactory.is())
        {
            xFactory->acquire();
            pRet = xFactory.get();
        }
    }

    return pRet;
}
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "UIAutoCompleteCombo.h"

/* ڲʹõ ֵƴĸ
bug: ֺ ޷ȡƴ.
*/

class CHzToPyIner
{
public:
	CHzToPyIner(void)
	{
		notFondMap[0xDBDA] = 'z';/* */
		notFondMap[53671] = 'x'; /* ѧ*/
		notFondMap[55792] = 'y'; /* */
	}
	~CHzToPyIner(void)
	{}
	char convert(wchar_t n)
	{
		if (In(0xB0A1, 0xB0C4, n))   return   'a';
		if (In(0XB0C5, 0XB2C0, n))   return   'b';
		if (In(0xB2C1, 0xB4ED, n))   return   'c';
		if (In(0xB4EE, 0xB6E9, n))   return   'd';
		if (In(0xB6EA, 0xB7A1, n))   return   'e';
		if (In(0xB7A2, 0xB8c0, n))   return   'f';
		if (In(0xB8C1, 0xB9FD, n))   return   'g';
		if (In(0xB9FE, 0xBBF6, n))   return   'h';
		if (In(0xBBF7, 0xBFA5, n))   return   'j';
		if (In(0xBFA6, 0xC0AB, n))   return   'k';
		if (In(0xC0AC, 0xC2E7, n))   return   'l';
		if (In(0xC2E8, 0xC4C2, n))   return   'm';
		if (In(0xC4C3, 0xC5B5, n))   return   'n';
		if (In(0xC5B6, 0xC5BD, n))   return   'o';
		if (In(0xC5BE, 0xC6D9, n))   return   'p';
		if (In(0xC6DA, 0xC8BA, n))   return   'q';
		if (In(0xC8BB, 0xC8F5, n))   return   'r';
		if (In(0xC8F6, 0xCBF0, n))   return   's';
		if (In(0xCBFA, 0xCDD9, n))   return   't';
		if (In(0xCDDA, 0xCEF3, n))   return   'w';
		if (In(0xCEF4, 0xD188, n))   return   'x';
		if (In(0xD1B9, 0xD4D0, n))   return   'y';
		if (In(0xD4D1, 0xD7F9, n))   return   'z';
		return   IsInNotFondList(n);
	}
	bool In(wchar_t start, wchar_t end, wchar_t code)
	{
		if (code >= start   &&   code <= end) {
			return   true;
		}
		return   false;
	}
	char IsInNotFondList(wchar_t n)
	{
		std::map<wchar_t, char >::iterator iter;
		for (iter = notFondMap.begin(); iter != notFondMap.end(); iter++)
		{
			if (iter->first == n)
				return iter->second;
		}
		return 'x';
	}
	std::string HzToPinYin(std::string str)
	{

		//std::string   sChinese   =   ᡱ;   //   ַ
		char *psText;
#ifdef UNICODE

		DWORD dwNum = WideCharToMultiByte(CP_OEMCP, NULL, str.GetBuffer(0), -1, NULL, 0, NULL, FALSE);

		psText = new char[dwNum];
		if (!psText)
			delete[]psText;
		WideCharToMultiByte(CP_OEMCP, NULL, str.GetBuffer(0), -1, psText, dwNum, NULL, FALSE);
		ASSERT(0); /* ֽж*/
#else
		//psText = str.c_str();
#endif
		std::string   sChinese = str;

		char   chr[3];
		wchar_t   wchr = 0;
		int leno = sChinese.length();
		int len = sChinese.length() /*/ 2*/;
		int bufLen = len * 2;
		char*   buff = new   char[bufLen];
		memset(buff, 0x00, bufLen);
		for (int i = 0, j = 0; j < (sChinese.length());)
		{
			char cChar = sChinese[j];
			if ((cChar >= 0 && cChar < 255) && isalnum(cChar)) /*ΪӢĻ 0-9 a-z A-Z*/
			{
				buff[i] = sChinese[j];
				i++;
				j++;
				continue;
			}
			memset(chr, 0x00, sizeof(chr));
			chr[0] = sChinese[j++];
			chr[1] = sChinese[j++];
			chr[2] = '\0';

			//  ַı   磺ҡ   =   0xced2
			//if (stricmp(chr, "") == 0) {
			//	buff[i] = 'z';
			//}
			//else {
			wchr = (chr[0] & 0xff) << 8;
			wchr |= (chr[1] & 0xff);
			buff[i] = convert(wchr);
			//}
			i++;
		}
		PinYin = buff;

		std::string strPy = buff;
		std::string outStr = "";
		for (size_t i = 0; i < strPy.length(); i++)
		{
			outStr += tolower(strPy[i]);
		}

		return  outStr.c_str();
	}
	std::string PinYin;
	std::map<wchar_t, char > notFondMap;
};

CAutoCompleteComboUI::CAutoCompleteComboUI()
{
	m_pEdit      = NULL;
	m_iLeftWidth = 22;/* default size*/
	m_pHzToPy = new CHzToPyIner;
	m_bInited  = false;
	OnNotify += MakeDelegate(this, &CAutoCompleteComboUI::OnComboNotify);
	OnInit += MakeDelegate(this, &CAutoCompleteComboUI::OnInitControl);
}

CAutoCompleteComboUI::~CAutoCompleteComboUI()
{
	delete m_pHzToPy;
}

void CAutoCompleteComboUI::AddItemToCombo(LPCTSTR pText, LPCTSTR pUserData)
{
	if (m_pHzToPy == NULL) ASSERT(0);

	CListLabelElementUI* pItem = new CListLabelElementUI;
	pItem->SetText(pText);
	CDuiString TextPy = (m_pHzToPy->HzToPinYin(pText)).c_str();
	//m_itemPinyin.Insert(pText, (LPVOID)TextPy.GetData());
	itemPyMap[pText] = TextPy.GetData();
	pItem->SetUserData(pUserData);
	Add(pItem);
}

bool CAutoCompleteComboUI::OnEiditNotify(void* pMsg)
{
	TNotifyUI* pNotify = (TNotifyUI*)pMsg;
	if (pNotify->sType == DUI_MSGTYPE_TEXTCHANGED) {
		CDuiString textEdit = ((CEditUI*)pNotify->pSender)->GetText();
		bool bSelect = false; /*Ĭѡ һƥѡ*/

		for (int i = 0; i < GetCount(); i++) {
			CListLabelElementUI* pItem = (CListLabelElementUI*)GetItemAt(i);
			CDuiString text = pItem->GetText();
			CDuiString textPy = itemPyMap[text.GetData()].c_str();

			pItem->SetVisible(false);
			if (textPy.Find(textEdit) != -1) {
				pItem->SetVisible(true);
				if (!bSelect) {
					//SelectItem(i);
					bSelect = true;
				}
			}
		}
		if (GetCount()>0){
			Activate(FALSE);
		}
	}
// 		int isel = m_pCombo->GetCurSel();
// 		CListLabelElementUI* pItem = (CListLabelElementUI*)m_pCombo->GetItemAt(isel);// CListLabelElementUI;
// 		CDuiString text = pItem->GetText();
// 		m_pEdit->SetText(text);
// 		m_pCombo->SelectItem(isel);
// 		m_pCombo->InActivate();
// 		::SetFocus(m_pm->GetPaintWindow());
	else if (pNotify->sType == DUI_MSGTYPE_KILLFOCUS) {
		InActivate();
	}
	return true;
}

bool CAutoCompleteComboUI::OnInitControl(void* pMsg)
{
	m_pEdit = new CEditUI();
	m_pEdit->SetFloat(true);
	CContainerUI *cont = (CContainerUI *)GetParent();
	int iMyIndex = cont->GetItemIndex(this);
	if (iMyIndex != -1){ /*while tab select focus, this ui works like a eidtui*/
		cont->AddAt(m_pEdit,iMyIndex+1);
	} else {
		cont->Add(m_pEdit);
	}

	m_pEdit->OnNotify += MakeDelegate(this, &CAutoCompleteComboUI::OnEiditNotify);

	m_bInited = true;
	return true;
}

bool CAutoCompleteComboUI::OnComboNotify(void* pMsg)
{
	TNotifyUI* pNotify = (TNotifyUI*)pMsg;
	if (pNotify->sType == DUI_MSGTYPE_KILLFOCUS) /*  ,Եitemʾ.*/
	{
		for (int i = 0; i < GetCount(); i++)
		{
			CListLabelElementUI* pItem = (CListLabelElementUI*)GetItemAt(i);
			pItem->SetVisible(true);
		}
	}
	else if (pNotify->sType == DUI_MSGTYPE_ITEMSELECT) {
		int isel = GetCurSel();
		CListLabelElementUI* pSelItem = static_cast<CListLabelElementUI*>(GetItemAt(isel));
		if (pSelItem != NULL)
		{
			CDuiString userdate = pSelItem->GetUserData().GetData();
			m_pEdit->SetUserData(userdate);
		}
		m_pEdit->SetText(pNotify->pSender->GetText());
	}
	return true;
}

void CAutoCompleteComboUI::SetPos(RECT rc, bool bNeedInvalidate)
{
	CComboUI::SetPos(rc, bNeedInvalidate);
	if (m_pEdit) {
		rc.left += 1;
		rc.right -= m_iLeftWidth;
		rc.top += 1;
		rc.bottom -= 1;
		m_pEdit->SetPos(rc, bNeedInvalidate);
	}
}

void CAutoCompleteComboUI::SetText(int iComboSel)
{
	if (iComboSel > GetCount()) {
		iComboSel = 0;
	}
	CListLabelElementUI* pItem = (CListLabelElementUI*)GetItemAt(iComboSel);// CListLabelElementUI;
	if (pItem == NULL) {
		m_pEdit->SetText("");
		return;
	}
	CDuiString text = pItem->GetText();
	m_pEdit->SetText(text);
	m_pEdit->SetFocus();

	CListLabelElementUI* pSelItem = static_cast<CListLabelElementUI*>(GetItemAt(iComboSel));
	if (pSelItem != NULL) {
		CDuiString userdate = pSelItem->GetUserData().GetData();
		m_pEdit->SetUserData(userdate);
	}
}

CDuiString CAutoCompleteComboUI::GetEditText()
{
	if (m_pEdit != NULL) {
		return m_pEdit->GetText();
	}
	return "";
}

void CAutoCompleteComboUI::SetEnabled(bool bEnable)
{
	__super::SetEnabled(bEnable);

	if (m_pEdit != NULL) {
		m_pEdit->SetEnabled(false);
	}
}
UINT CAutoCompleteComboUI::GetControlFlags() const
{
	//return UIFLAG_TABSTOP;
	return 0;
}
void CAutoCompleteComboUI::SetFocus()
{
	if (m_pEdit != NULL) {
		m_pEdit->SetFocus();
	}
}
const CDuiString& CAutoCompleteComboUI::GetUserData()
{
	if (m_pEdit != NULL) {
		return m_pEdit->GetUserData();
	}
	return "";
}<commit_msg>edit change 消息通知到 外部程序<commit_after>#include "stdafx.h"
#include "UIAutoCompleteCombo.h"

/* ڲʹõ ֵƴĸ
bug: ֺ ޷ȡƴ.
*/

class CHzToPyIner
{
public:
	CHzToPyIner(void)
	{
		notFondMap[0xDBDA] = 'z';/* */
		notFondMap[53671] = 'x'; /* ѧ*/
		notFondMap[55792] = 'y'; /* */
	}
	~CHzToPyIner(void)
	{}
	char convert(wchar_t n)
	{
		if (In(0xB0A1, 0xB0C4, n))   return   'a';
		if (In(0XB0C5, 0XB2C0, n))   return   'b';
		if (In(0xB2C1, 0xB4ED, n))   return   'c';
		if (In(0xB4EE, 0xB6E9, n))   return   'd';
		if (In(0xB6EA, 0xB7A1, n))   return   'e';
		if (In(0xB7A2, 0xB8c0, n))   return   'f';
		if (In(0xB8C1, 0xB9FD, n))   return   'g';
		if (In(0xB9FE, 0xBBF6, n))   return   'h';
		if (In(0xBBF7, 0xBFA5, n))   return   'j';
		if (In(0xBFA6, 0xC0AB, n))   return   'k';
		if (In(0xC0AC, 0xC2E7, n))   return   'l';
		if (In(0xC2E8, 0xC4C2, n))   return   'm';
		if (In(0xC4C3, 0xC5B5, n))   return   'n';
		if (In(0xC5B6, 0xC5BD, n))   return   'o';
		if (In(0xC5BE, 0xC6D9, n))   return   'p';
		if (In(0xC6DA, 0xC8BA, n))   return   'q';
		if (In(0xC8BB, 0xC8F5, n))   return   'r';
		if (In(0xC8F6, 0xCBF0, n))   return   's';
		if (In(0xCBFA, 0xCDD9, n))   return   't';
		if (In(0xCDDA, 0xCEF3, n))   return   'w';
		if (In(0xCEF4, 0xD188, n))   return   'x';
		if (In(0xD1B9, 0xD4D0, n))   return   'y';
		if (In(0xD4D1, 0xD7F9, n))   return   'z';
		return   IsInNotFondList(n);
	}
	bool In(wchar_t start, wchar_t end, wchar_t code)
	{
		if (code >= start   &&   code <= end) {
			return   true;
		}
		return   false;
	}
	char IsInNotFondList(wchar_t n)
	{
		std::map<wchar_t, char >::iterator iter;
		for (iter = notFondMap.begin(); iter != notFondMap.end(); iter++)
		{
			if (iter->first == n)
				return iter->second;
		}
		return 'x';
	}
	std::string HzToPinYin(std::string str)
	{

		//std::string   sChinese   =   ᡱ;   //   ַ
		char *psText;
#ifdef UNICODE

		DWORD dwNum = WideCharToMultiByte(CP_OEMCP, NULL, str.GetBuffer(0), -1, NULL, 0, NULL, FALSE);

		psText = new char[dwNum];
		if (!psText)
			delete[]psText;
		WideCharToMultiByte(CP_OEMCP, NULL, str.GetBuffer(0), -1, psText, dwNum, NULL, FALSE);
		ASSERT(0); /* ֽж*/
#else
		//psText = str.c_str();
#endif
		std::string   sChinese = str;

		char   chr[3];
		wchar_t   wchr = 0;
		int leno = sChinese.length();
		int len = sChinese.length() /*/ 2*/;
		int bufLen = len * 2;
		char*   buff = new   char[bufLen];
		memset(buff, 0x00, bufLen);
		for (int i = 0, j = 0; j < (sChinese.length());)
		{
			char cChar = sChinese[j];
			if ((cChar >= 0 && cChar < 255) && isalnum(cChar)) /*ΪӢĻ 0-9 a-z A-Z*/
			{
				buff[i] = sChinese[j];
				i++;
				j++;
				continue;
			}
			memset(chr, 0x00, sizeof(chr));
			chr[0] = sChinese[j++];
			chr[1] = sChinese[j++];
			chr[2] = '\0';

			//  ַı   磺ҡ   =   0xced2
			//if (stricmp(chr, "") == 0) {
			//	buff[i] = 'z';
			//}
			//else {
			wchr = (chr[0] & 0xff) << 8;
			wchr |= (chr[1] & 0xff);
			buff[i] = convert(wchr);
			//}
			i++;
		}
		PinYin = buff;

		std::string strPy = buff;
		std::string outStr = "";
		for (size_t i = 0; i < strPy.length(); i++)
		{
			outStr += tolower(strPy[i]);
		}

		return  outStr.c_str();
	}
	std::string PinYin;
	std::map<wchar_t, char > notFondMap;
};

CAutoCompleteComboUI::CAutoCompleteComboUI()
{
	m_pEdit      = NULL;
	m_iLeftWidth = 22;/* default size*/
	m_pHzToPy = new CHzToPyIner;
	m_bInited  = false;
	OnNotify += MakeDelegate(this, &CAutoCompleteComboUI::OnComboNotify);
	OnInit += MakeDelegate(this, &CAutoCompleteComboUI::OnInitControl);
}

CAutoCompleteComboUI::~CAutoCompleteComboUI()
{
	delete m_pHzToPy;
}

void CAutoCompleteComboUI::AddItemToCombo(LPCTSTR pText, LPCTSTR pUserData)
{
	if (m_pHzToPy == NULL) ASSERT(0);

	CListLabelElementUI* pItem = new CListLabelElementUI;
	pItem->SetText(pText);
	CDuiString TextPy = (m_pHzToPy->HzToPinYin(pText)).c_str();
	//m_itemPinyin.Insert(pText, (LPVOID)TextPy.GetData());
	itemPyMap[pText] = TextPy.GetData();
	pItem->SetUserData(pUserData);
	Add(pItem);
}

bool CAutoCompleteComboUI::OnEiditNotify(void* pMsg)
{
	TNotifyUI* pNotify = (TNotifyUI*)pMsg;
	if (pNotify->sType == DUI_MSGTYPE_TEXTCHANGED) {
		CDuiString textEdit = ((CEditUI*)pNotify->pSender)->GetText();
		bool bSelect = false; /*Ĭѡ һƥѡ*/

		for (int i = 0; i < GetCount(); i++) {
			CListLabelElementUI* pItem = (CListLabelElementUI*)GetItemAt(i);
			CDuiString text = pItem->GetText();
			CDuiString textPy = itemPyMap[text.GetData()].c_str();

			pItem->SetVisible(false);
			if (textPy.Find(textEdit) != -1) {
				pItem->SetVisible(true);
				if (!bSelect) {
					//SelectItem(i);
					bSelect = true;
				}
			}
		}
		if (GetCount()>0){
			Activate(FALSE);
		}

		GetManager()->SendNotify(this, DUI_MSGTYPE_TEXTCHANGED);
	}
// 		int isel = m_pCombo->GetCurSel();
// 		CListLabelElementUI* pItem = (CListLabelElementUI*)m_pCombo->GetItemAt(isel);// CListLabelElementUI;
// 		CDuiString text = pItem->GetText();
// 		m_pEdit->SetText(text);
// 		m_pCombo->SelectItem(isel);
// 		m_pCombo->InActivate();
// 		::SetFocus(m_pm->GetPaintWindow());
	else if (pNotify->sType == DUI_MSGTYPE_KILLFOCUS) {
		InActivate();
	}
	return true;
}

bool CAutoCompleteComboUI::OnInitControl(void* pMsg)
{
	m_pEdit = new CEditUI();
	m_pEdit->SetFloat(true);
	CContainerUI *cont = (CContainerUI *)GetParent();
	int iMyIndex = cont->GetItemIndex(this);
	if (iMyIndex != -1){ /*while tab select focus, this ui works like a eidtui*/
		cont->AddAt(m_pEdit,iMyIndex+1);
	} else {
		cont->Add(m_pEdit);
	}

	m_pEdit->OnNotify += MakeDelegate(this, &CAutoCompleteComboUI::OnEiditNotify);

	m_bInited = true;
	return true;
}

bool CAutoCompleteComboUI::OnComboNotify(void* pMsg)
{
	TNotifyUI* pNotify = (TNotifyUI*)pMsg;
	if (pNotify->sType == DUI_MSGTYPE_KILLFOCUS) /*  ,Եitemʾ.*/
	{
		for (int i = 0; i < GetCount(); i++)
		{
			CListLabelElementUI* pItem = (CListLabelElementUI*)GetItemAt(i);
			pItem->SetVisible(true);
		}
	}
	else if (pNotify->sType == DUI_MSGTYPE_ITEMSELECT) {
		int isel = GetCurSel();
		CListLabelElementUI* pSelItem = static_cast<CListLabelElementUI*>(GetItemAt(isel));
		if (pSelItem != NULL)
		{
			CDuiString userdate = pSelItem->GetUserData().GetData();
			m_pEdit->SetUserData(userdate);
		}
		m_pEdit->SetText(pNotify->pSender->GetText());
	}
	return true;
}

void CAutoCompleteComboUI::SetPos(RECT rc, bool bNeedInvalidate)
{
	CComboUI::SetPos(rc, bNeedInvalidate);
	if (m_pEdit) {
		rc.left += 1;
		rc.right -= m_iLeftWidth;
		rc.top += 1;
		rc.bottom -= 1;
		m_pEdit->SetPos(rc, bNeedInvalidate);
	}
}

void CAutoCompleteComboUI::SetText(int iComboSel)
{
	if (iComboSel > GetCount()) {
		iComboSel = 0;
	}
	CListLabelElementUI* pItem = (CListLabelElementUI*)GetItemAt(iComboSel);// CListLabelElementUI;
	if (pItem == NULL) {
		m_pEdit->SetText("");
		return;
	}
	CDuiString text = pItem->GetText();
	m_pEdit->SetText(text);
	m_pEdit->SetFocus();

	CListLabelElementUI* pSelItem = static_cast<CListLabelElementUI*>(GetItemAt(iComboSel));
	if (pSelItem != NULL) {
		CDuiString userdate = pSelItem->GetUserData().GetData();
		m_pEdit->SetUserData(userdate);
	}
}

CDuiString CAutoCompleteComboUI::GetEditText()
{
	if (m_pEdit != NULL) {
		return m_pEdit->GetText();
	}
	return "";
}

void CAutoCompleteComboUI::SetEnabled(bool bEnable)
{
	__super::SetEnabled(bEnable);

	if (m_pEdit != NULL) {
		m_pEdit->SetEnabled(false);
	}
}
UINT CAutoCompleteComboUI::GetControlFlags() const
{
	//return UIFLAG_TABSTOP;
	return 0;
}
void CAutoCompleteComboUI::SetFocus()
{
	if (m_pEdit != NULL) {
		m_pEdit->SetFocus();
	}
}
const CDuiString& CAutoCompleteComboUI::GetUserData()
{
	if (m_pEdit != NULL) {
		return m_pEdit->GetUserData();
	}
	return "";
}<|endoftext|>