function [proj, verts] = gtFwdSimBuildProjGeometry(diff_beam_dirs, gr_center, omegas, bb, parameters, stackUSize, stackVSize, selected, det_ind)
% FUNCTION proj = gtFwdSimBuildProjGeometry(diff_beam_dirs, gr_center, omegas, bb, parameters, stackUSize, stackVSize, selected, det_ind)
%
    if (~exist('det_ind', 'var') || isempty(det_ind))
        det_ind = 1;
    end

    acq = parameters.acq;
    fsim = parameters.fsim;
    labgeo = parameters.labgeo;
    samgeo = parameters.samgeo;
    recgeo = parameters.recgeo(det_ind);
    detgeo = parameters.detgeo(det_ind);

    num_projs = size(diff_beam_dirs, 1);

    spot_shifts = gtFwdSimGetStackShifts(stackUSize, stackVSize, bb, true);

    % Bouning boxes in detector coordinates!
    bbpos_det_grain = [ ...
        (bb(:, 1) - spot_shifts.u), (bb(:, 2) - spot_shifts.v), ...
        stackUSize(ones(num_projs, 1)), stackVSize(ones(num_projs, 1)) ...
        ];

    % Bouning boxes in detector coordinates!
    bbpos_det_full = repmat([1 1 acq.xdet acq.ydet], num_projs, 1);
    bbpos_det_abs = repmat(acq.bb, num_projs, 1);

    %%% Now we actually build the geometries

    % Calculate the projection geometry for the spots:
    %  - Vector used for ROI grain reconstruction in ASTRA (grain shifted
    %    to center of roi volume)
    proj_geom = gtGeoProjForReconstruction(diff_beam_dirs, ...
        omegas, gr_center, bbpos_det_grain, [], ...
        detgeo, labgeo, samgeo, recgeo, 'ASTRA_grain');

    % Calculate the projection geometry for the full images:
    %  - Vector describing full projection geometry (full images, grain at
    %    nominal position in sample volume)
    proj_geom_full = gtGeoProjForReconstruction( ...
        diff_beam_dirs, omegas, [], bbpos_det_full, ...
        [], detgeo, labgeo, samgeo, recgeo, 'ASTRA_full');

    % Geometry for extinction spots
    proj_geom_abs = gtGeoProjForReconstruction([], omegas, [], ...
        bbpos_det_abs, [], detgeo, labgeo, samgeo, recgeo,  ...
        'ASTRA_absorption');

    proj = gtFwdSimProjDefinition('fwd_sim');

    % diffraction geometry
    proj.geom      = proj_geom;
    proj.geom_full = proj_geom_full;
    proj.geom_abs  = proj_geom_abs;

    proj.num_rows  = stackVSize;
    proj.num_cols  = stackUSize;

    proj.centerpix = gtGeoSam2Sam(gr_center, samgeo, recgeo, true);

    use_polyhedron = numel(find(selected)) >= 3;
    if (use_polyhedron)
        % This should behave better with vertical detector
        % (if no bug is introduced with it :D)
        verts = gtFwdSimComputeCircumscribingPolyhedron(...
            gr_center, diff_beam_dirs(selected, :), omegas(selected), ...
            bb(selected, :), parameters, det_ind);

        vol_size = 2 * max(abs(max(verts, [], 1)), abs(min(verts, [], 1)));
    else
        verts = [];
        % We should in the future handle properly vertical detector
        % (general geometry) maybe determining a convex shape of the grain!
        vol_size = [stackUSize, stackUSize, stackVSize] / fsim.oversize;
    end

    vol_size = round(vol_size * fsim.oversizeVol);

    proj.vol_size_x = vol_size(2);
    proj.vol_size_y = vol_size(1);
    proj.vol_size_z = vol_size(3);
end

