Вернуться наверх
aco.ifmo.ru photonic
вернуться в оглавление предыдущая глава предыдущий параграф следующий параграф следующая глава


Пример 1. Генерация типовых предметов

Предмет (файлы object.h, object.cpp)

object.h

///////////////////////////////////////////////////////////////////////////////////////////////////
// object.h
// Предмет - двумерная комплексная выборка в реальных координатах. Размер выборки по x и y одинаковый.
// Генерация нескольких типовых объектов с соблюдением симметрии относительно центра выборки.
// 
// Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru
// Университет ИТМО
///////////////////////////////////////////////////////////////////////////////////////////////////
#if !defined  OBJECT_H
#define OBJECT_H

#include "sample_complex.h"
//-------------------------------------------------------------------------------------------------
class Object: public SampleComplex
{
private:
    // шаг по предмету (к.е.)
    double m_dx;

public:
    // конструктор
    // size - количество элементов, одинаковое по x и y (size*size)
    // dx - шаг по предмету (к.е.)
    Object(int size, double dx);
    ~Object();

    // создание предмета в виде бинарной периодической решетки 
    // period - период решетки (к.е.)
    // width  - ширина линии (к.е.)
    void CreateLineAndSpace(double period, double width);
    // создание предмета в виде полутоновой периодической решетки 
    // period - период решетки (к.е.)
    // width  - ширина линии (к.е.)
    void CreateLineAndSpaceAttenuaten(double period, double width);
    // создание предмета в виде чередующейся полутоновой периодической решетки 
    // period - период решетки (к.е.)
    // width  - ширина линии (к.е.)
    void CreateLineAndSpaceAlternating(double period, double width);

    // создание предмета в виде полуплоскости
    void CreateHalfPlane();

    // создание предмета в виде радиальной миры
    // count - количество секторов (линий)
    void CreateTargetStar(int count);

private:
    // универсальная функция создания предмета в виде чередующейся периодической решетки 
    // period - период решетки (к.е.)
    // width  - ширина линии (к.е.)
    // ob_module_line, ob_phase_line - модуль и фаза "линии", т.е. непрозрачной части решетки
    // ob_module_space, ob_phase_space - модуль и фаза "промежутка", т.е. прозрачной части решетки
    // ob_phase_space2 - фаза второго "промежука", для чередующейся решетки
    void CreateLineAndSpaceCommon(double period, double width,
                                  double ob_module_line=1.,  double ob_phase_line=0, 
                                  double ob_module_space=0., double ob_phase_space=0,
                                  double ob_phase_space2=0);
};
//-------------------------------------------------------------------------------------------------
#endif // OBJECT_H


object.cpp

///////////////////////////////////////////////////////////////////////////////////////////////////
// object.cpp
// Предмет - двумерная комплексная выборка в реальных координатах. Размер выборки по x и y одинаковый.
// Генерация нескольких типовых объектов с соблюдением симметрии относительно центра выборки.
// 
// Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru
// Университет ИТМО
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "Object.h"


//-------------------------------------------------------------------------------------------------
Object::Object(int size, double dx)
: SampleComplex(size)
, m_dx(dx)
{
}
//-------------------------------------------------------------------------------------------------
Object::~Object()
{

}
//-------------------------------------------------------------------------------------------------
// создание предмета в виде полуплоскости
void Object::CreateHalfPlane()
{
    for(int j=0;j<m_size;j++)
    {
        for(int i=0;i<m_size;i++)
        {
            if(i<m_size/2)
                operator()(i,j)=complex<double>(0., 0.);
            else
                operator()(i,j)=complex<double>(1., 0.);
        }
    }
}
//-------------------------------------------------------------------------------------------------
// создание предмета в виде радиальной миры
void Object::CreateTargetStar(int count)
{
    double dStep=180/count;
    for(int j=0; j<m_size; j++)
    {
        double y=CalcCoord(j, m_dx);
        for(int i=0; i<m_size; i++)
        {
            double x=CalcCoord(i, m_dx);
            double dAngle=atan2(y,x)*180/PI + 180;// вычисление угла в диапазоне 0 - 360 град.
            if(int(dAngle/dStep)%2!=0)
                operator()(i,j)=complex<double>(0., 0.);
            else
                operator()(i,j)=complex<double>(1., 0.);
        }
    }
}
//-------------------------------------------------------------------------------------------------
// создание предмета в виде бинарной периодической решетки 
void Object::CreateLineAndSpace(double period, double width)
{
    CreateLineAndSpaceCommon(period, width, 0., 0., 1., 0., 0.);
}
//-------------------------------------------------------------------------------------------------
// создание предмета в виде полутоновой периодической решетки 
void Object::CreateLineAndSpaceAttenuaten(double period, double width)
{
    CreateLineAndSpaceCommon(period, width, 0.06, PI, 1., 0., 0);
}
//-------------------------------------------------------------------------------------------------
// создание предмета в виде чередующейся полутоновой периодической решетки 
void Object::CreateLineAndSpaceAlternating(double period, double width)
{
    CreateLineAndSpaceCommon(period, width, 0., 0., 1., 0., PI);
}
//-------------------------------------------------------------------------------------------------
// создание предмета в виде периодической решетки
// period - период решетки (к.е.)
// width - ширина линии (к.е.)
void Object::CreateLineAndSpaceCommon(double period, double width, 
                                      double ob_module_line,  double ob_phase_line, 
                                      double ob_module_space, double ob_phase_space, double ob_phase_space2)
{
    // период и ширина решетки в кол-ве элементов
    int i_period=period/m_dx;
    int i_width=width/m_dx;

    // значения для соs и sin части комплексного числа (представление по формуле Эйлера)
    // для линии и промежутков
    double ob_c_line=cos(ob_phase_line);
    double ob_s_line=sin(ob_phase_line);
    double ob_c_space=cos(ob_phase_space);
    double ob_s_space=sin(ob_phase_space);
    double ob_c_space2=cos(ob_phase_space2);
    double ob_s_space2=sin(ob_phase_space2);

    // для четного кол-ва элементов в выборке ширина линии должна быть четной, для нечетного - четной
    if((m_size%2==0 && i_width%2!=0) || (m_size%2!=0 && i_width%2==0))
        i_width++;
    // ширина промежутка в кол-ве элементов
    int i_space=i_period-i_width;
    // определение, что должно быть на краю выборки - линия или промежуток
    bool bFirstline=false;
    int  i_first=(m_size/2-i_width/2)/i_period;
    i_first=m_size/2-i_width/2-i_first*i_period;
    if(i_first-i_space > 0)
    {
        i_first-=i_space;
        bFirstline=true;
    }

    // признаки, что будет следующее - линия или промежуток, и будет ли меняться фаза
    bool bPhase=true, bLine=false;
    for(int j=0; j<m_size; j++)
    {
        // промежуток
        if(( bFirstline && (j>=(i_first+i_space) && j<(i_first+i_period) || j<i_first)) ||
           (!bFirstline && (j>=(i_first)         && j<(i_first+i_width )) ) )
        {
            if(bLine)
                bPhase=!bPhase;
            for(int i=0; i<m_size; i++)
            {
                if(bPhase)
                    operator()(i,j)=ob_module_space*complex<double>(ob_c_space,ob_s_space);
                else
                    operator()(i,j)=ob_module_space*complex<double>(ob_c_space2,ob_s_space2);
            }
            bLine=false;             
        }
        // линия
        else
        {  
            for(int i=0; i<m_size; i++)
            {
                operator()(i,j)=ob_module_line*complex<double>(ob_c_line,ob_s_line);
            }
            bLine=true; 
        }
        if((j+1)>=i_first+i_period)
            i_first+=i_period;
    }
}
//-------------------------------------------------------------------------------------------------