//------------------------------------------------------------
// $Id: objectInfoInASpace.h,v 1.2 2000/06/14 13:29:37 yamauchi Exp $
//------------------------------------------------------------
//	(M\pi)^2 : object information in a subspace
//		    (ある一つの副空間の物体の存在情報を示す)  
//	1996/7/6 start as `dataCollection.h'
//	Copyright (C) 1998 YAMAUCHI Hitoshi 山内 斉 
//	1998年8月27日(木)
// 
// 	ある空間の物体情報．通常 array3DClass の要素となり，物体の存在
// 	情報などを示す
//
// 	objectNumInASpaceClass:   ある空間に存在する物体別の数をカウントする
// 	objectExistInASpaceClass: ある空間の物体の存在の様子を示す
//------------------------------------------------------------
#ifndef _objectInfoInASpace_h
#define _objectInfoInASpace_h 1

#include <iostream.h>
#include "mpi2.h"

// 物体の存在情報の内部表現の型 (objectExistInASpaceClass)
#define OBJINSPC_IMPLEMENT_TYPE char

//------------------------------------------------------------
// ある一つの空間に存在する物体の情報
// 	数を数えるもの(host で利用)
//------------------------------------------------------------
class objectNumInASpaceClass {
public:    
    int mGeoNum;
    int mVolNum;		// volumeReader.cc ではスライス数

public:    
    objectNumInASpaceClass(void) : mGeoNum(0), mVolNum(0){}
    objectNumInASpaceClass(const objectNumInASpaceClass& rhs)
    {
	this->mGeoNum = rhs.mGeoNum;
	this->mVolNum = rhs.mVolNum;
    }
    const objectNumInASpaceClass& operator=(const objectNumInASpaceClass& rhs)
    {
	if(this != &rhs)
	{
	    this->mGeoNum = rhs.mGeoNum;
	    this->mVolNum = rhs.mVolNum;
	}
	return(*this);
    }
    YorN isObj(void)		// 物体が存在すれば YES
    {
	if((this->mGeoNum > 0) || (this->mVolNum > 0))
	{
	    return(YES);
	}else
	{
	    return(NO);
	}
    }
    friend ostream& operator<<(ostream& s, const objectNumInASpaceClass& onis)
    {
	s << onis.mGeoNum << "\t" << onis.mVolNum;
	return s;
    }

    //------------------------------
    // pretty print 部分空間にどのように物体があるかを見るためのもの
    //------------------------------
    const char * getVisualOutDescription(void) const
    {
	return(" [P]olygon, [V]olume, [B]oth");
    }
    char getVisualOut(void) const
    {
	// ここでは Polygon があれば P, Volume なら V, 両方なら B を返す
	if((this->mGeoNum > 0) && (this->mVolNum > 0))
	{
	    return('B');
	}
	else if(this->mGeoNum > 0)
	{
	    return('P');
	}
	else if(this->mVolNum > 0)
	{
	    return('V');	    
	}
	else
	{
	    return(' ');	    	    
	}
    }

    //----------------------------------------
    // SerializableIF : double の表現が同じ計算機でないと上手くいかない    
    //----------------------------------------
    int getSerializedSize(void) const
    {
	return(2);
    }
    double *newSerializedArray(void)
    {
	double *r = new double[this->getSerializedSize()];
	r[0] = this->mGeoNum;
	r[1] = this->mVolNum;
	return(r);
    }
    void deserialize(double *pBuf)
    {
	this->mGeoNum = (int)(pBuf[0]);
	this->mVolNum = (int)(pBuf[1]);
    }

    // operator ==
    friend int operator==(const objectNumInASpaceClass &a,
			  const objectNumInASpaceClass &b)
    {
	return((a.mGeoNum == b.mGeoNum) && (a.mVolNum == a.mVolNum));
    }
    friend int operator!=(const objectNumInASpaceClass &a,
			  const objectNumInASpaceClass &b)
    {
	return(!((a.mGeoNum == b.mGeoNum) && (a.mVolNum == a.mVolNum)));
    }
};


//------------------------------------------------------------
// ある空間の物体の存在の様子を示す
// 	Geometry があるか， Volume があるか
//	本来なら #include "serializable.h"
//------------------------------------------------------------
class objectExistInASpaceClass {  
protected:    
    OBJINSPC_IMPLEMENT_TYPE mObjInfo;

public:    
    enum {
	IS_GEO = 1,		// = 01b : geometry (polygon など) がある
	IS_VOL = 2		// = 10b : volume がある
    };

public:    
    objectExistInASpaceClass(void) : mObjInfo(0){}
    objectExistInASpaceClass(const objectExistInASpaceClass& rhs)
    {
	this->mObjInfo = rhs.mObjInfo;
    }
    objectExistInASpaceClass(const OBJINSPC_IMPLEMENT_TYPE& rhs)
    {
	this->mObjInfo = rhs;
    }
    const objectExistInASpaceClass operator=(const
					     objectExistInASpaceClass& rhs)
    {
	if(this != &rhs)
	{
	    this->mObjInfo = rhs.mObjInfo;
	}
	return(*this);
    }

    void set(int aGeoNum, int aVolNum) // set のみ消えない
    {
	if(aGeoNum > 0)
	{
	    this->mObjInfo |= objectExistInASpaceClass::IS_GEO;
	}
	if(aVolNum > 0)
	{
	    this->mObjInfo |= objectExistInASpaceClass::IS_VOL;
	}
    }
    void clear(void)
    {
	this->mObjInfo = 0;
    }

    YorN isObj(void) const	// 何か物体が存在すれば YES
    {
	return(((this->mObjInfo > 0)) ? YES : NO);
    }
    YorN isGeo(void) const	// geometry が存在すれば YES
    {
	if((this->mObjInfo & objectExistInASpaceClass::IS_GEO) > 0)
	{
	    return(YES);
	}else
	{
	    return(NO);
	}
    }
    YorN isVol(void) const	// volume が存在すれば YES
    {
	if((this->mObjInfo & objectExistInASpaceClass::IS_VOL) > 0)
	{
	    return(YES);
	}else
	{
	    return(NO);
	}
    }

    // for serialize (送信のために OBJINSPC_IMPLEMENT_TYPE で取り出す)
    OBJINSPC_IMPLEMENT_TYPE getObjInfo(void) const
    {
	return(this->mObjInfo);
    }
    
    friend ostream& operator<<(ostream& s, objectExistInASpaceClass& onis)
    {
	s << onis.mObjInfo;
	return s;
    }

    // for pretty print
    const char * getVisualOutDescription(void) const
    {
	return(" [P]olygon, [V]olume, [B]oth");
    }
    char getVisualOut(void) const
    {
	// Polygon があれば P, Volume なら V, 両方なら B を返す
	if(this->mObjInfo == (objectExistInASpaceClass::IS_GEO | 
			      objectExistInASpaceClass::IS_VOL))
	{
	    return('B');
	}
	else if(this->mObjInfo == objectExistInASpaceClass::IS_GEO)
	{
	    return('P');
	}
	else if(this->mObjInfo == objectExistInASpaceClass::IS_VOL)	
	{
	    return('V');
	}
	else
	{
	    return(' ');	    	    
	}
    }
    
    //----------------------------------------
    // SerializableIF : double の表現が同じ計算機でないと上手くいかない    
    //----------------------------------------
    int getSerializedSize(void) const
    {
	// OBJINSPC_IMPLEMENT_TYPE mObjInfo; 今は char 
	return(1);
    }
    double *newSerializedArray(void)
    {
	double *r = new double[this->getSerializedSize()];
	r[0] = (double)(this->mObjInfo);
	return(r);
    }
    void deserialize(double *pBuf)
    {
	this->mObjInfo = (char)(pBuf[0]);
    }


    // operator ==
    friend int operator==(const objectExistInASpaceClass &a,
			  const objectExistInASpaceClass &b)
    {
	return(a.mObjInfo == b.mObjInfo);
    }
    friend int operator!=(const objectExistInASpaceClass &a,
			  const objectExistInASpaceClass &b)
    {
	return(a.mObjInfo != b.mObjInfo);
    }
};

#endif				// #define _objectInfoInASpace_h 1





