
function [maps, cameras] = create_maps(nclass, xres, yres)

    ntraj = 100;
    nanomclass = 10;
    nanom = 1;
    trlen = 128;
    randangle = 1.0;
    max_num_of_cams = 4;
    
    % discretization intervals
    gridsize = 4;   % gridsize x gridsize cells for starting position
    nangles = 5;    % divide the -90:+90 interval in nangles slices
    
    %%%
    %create a grid of all the possible trajecotry parameters
    featspace = zeros( (gridsize-1) * 4 * nangles^3, 1 );

    % choose nclass+nanomclass trajectories
    for i=1:nclass+nanomclass
        idx = find( ~featspace );  
        chosen = floor( rand() * length(idx) + 1 );
        featspace( idx( chosen ) ) = 1;  % the choose a free trajectory prototype in the tr. feature space

        tmp = ceil ( idx(chosen) / nangles^3 );   % convert the global index into startside/startcell/angle1/2/3 parameters
        startside(i) = ceil(tmp / (gridsize-1));
        startcell(i) = mod( tmp, (gridsize-1) ) + 1;
        tmp = mod( idx(chosen), nangles^3 ) + 1;
        angle1(i) = ceil(tmp / nangles^2);
        tmp = mod( tmp, nangles^2 ) + 1;
        angle2(i) = ceil( tmp / nangles);
        angle3(i) = mod(tmp, nangles) + 1;
    end
    
    % create normal trajectories
    tr = zeros( ntraj*nclass, trlen*2);
    for i=1:nclass
        tmp = create_traj( ntraj, startside(i), startcell(i), angle1(i), angle2(i), angle3(i), trlen, randangle, gridsize, nangles );
        tr(ntraj*(i-1)+1:ntraj*i, :) = tmp;
    end
    
    % create anomalies
    anom = zeros( nanom * nanomclass, trlen*2);
    for j=1:nanomclass
        tmp = create_traj( nanom, startside(j+nclass), startcell(j+nclass), angle1(j+nclass), angle2(j+nclass), angle3(j+nclass), trlen, randangle, gridsize, nangles );
        anom(nanom*(j-1)+1:nanom*j, :) = tmp;
    end
    
    %%%%%%% 
    
    % put everything together
    tr = [tr; anom];

    % CREATE THE ORIGINAL MAP!
    omap = zeros(yres,xres);
    x = tr(:,1:trlen);
    y = tr(:, trlen+1:2*trlen);
    x = reshape(x, [], 1);
    y = reshape(y, [], 1);
    x = x * xres;
    y = y * yres;
    for i=1:xres
        for j=1:yres
            omap(j,i) = length(find((x>i & x<i+1 & y>j & y<j+1)));
        end
    end

    % randomly put the cameras (always on the external border of the map)
    ncam = 1+randi(max_num_of_cams-1);
    cameras = [];
    for i=1:ncam
        side = randi(4);
        if side==1
            xcam =0; ycam = randi(yres);
        elseif side==2
            xcam = xres+1; ycam = randi(yres);
        elseif side==3
            xcam=randi(xres); ycam=0;
        else
            xcam=randi(xres); ycam=yres+1;
        end
        cameras = [cameras; ycam, xcam, ceil(yres/3)];    % height set to yres/3
        % to avoid confusion, we'll switch x and y later 
    end
     
    % creare a random occlusion
    v(1,:) = [randi(yres-1), randi(xres-1)];
    occwidth  = min(15, randi(xres - v(1,2)));
    occheight = min(15, randi(yres - v(1,1)));
    v(2,:) = v(1,:) + [0, occwidth];
    v(3,:) = v(1,:) + [occheight, 0];
    v(4,:) = v(1,:) + [occheight, occwidth];
    
    omap(v(1,1):v(4,1), v(1,2):v(4,2)) = 0;  % put the occlusion into map
    
    % for each camera, project the occlusion
    maps(ncam+1,:,:) = omap;  % save also the original map without occlusion projections (but with the occlusion itself)
    for i=1:ncam
        maps(i,:,:) = omap;
        
        a(1) = atan2(v(1,1)-cameras(i,1), v(1,2)-cameras(i,2));
        if a(1)<0 a(1)=2*pi+a(1); end
        a(2) = atan2(v(2,1)-cameras(i,1), v(2,2)-cameras(i,2));
        if a(2)<0 a(2)=2*pi+a(2); end
        a(3) = atan2(v(3,1)-cameras(i,1), v(3,2)-cameras(i,2));
        if a(3)<0 a(3)=2*pi+a(3); end
        a(4) = atan2(v(4,1)-cameras(i,1), v(4,2)-cameras(i,2));
        if a(4)<0 a(4)=2*pi+a(4); end
 
        [minangle,minidx] = min(a);
        [maxangle,maxidx] = max(a);
        minpoint = v(minidx,:);
        maxpoint = v(maxidx,:);

        % special case
        special_case = v(1,1)<=cameras(i,1) & v(3,1)>=cameras(i,1) & v(1,2)>=cameras(i,2);
        
        if ~special_case
            for y=1:yres
                for x=1:xres
                    angle = atan2(y-cameras(i,1), x-cameras(i,2));
                    if angle<0 angle = 2*pi + angle; end
                    dir = sign( cameras(i,1)-minpoint(1))/(maxpoint(1)-minpoint(1)) - (cameras(i,2)-minpoint(2))/(maxpoint(2)-minpoint(2) );
                    if angle > minangle && angle < maxangle && dir * ((y-minpoint(1))/(maxpoint(1)-minpoint(1)) - (x-minpoint(2))/(maxpoint(2)-minpoint(2))) < 0
                        maps(i,y,x) = 0;
                    end
                end
            end
        else
			% special case
            for y=1:yres
                for x=1:xres
                    angle = atan2(y-cameras(i,1), x-cameras(i,2));
                    if angle<0 angle = 2*pi + angle; end
                    dir = sign( cameras(i,1)-minpoint(1))/(maxpoint(1)-minpoint(1)) - (cameras(i,2)-minpoint(2))/(maxpoint(2)-minpoint(2) );
                    if (angle < a(3) || angle > a(1)) && dir * ((y-v(1,1))/(v(3,1)-v(1,1)) - (x-v(1,2))/(v(3,2)-v(1,2))) < 0
                        maps(i,y,x) = 0;
                    end
                end
            end         
        end
        % end loop for each camera
    end

    % switch X and Y of cameras, since em_deployment wants that format: cameras(x, y, h)
    cameras = cameras(:, [2 1 3]);
    
    % for i=1:ncam+1
    %     figure;
    %     pcolor( squeeze(maps(i,:,:)) );
    % end
    
end


% create a single trajectory with prototype number idx (startside(idx),
% startcell(idx), angle1(idx), angle2(idx), angle3(idx)) and put it in
% tr(count,:). The trajectory will have trlen length, the perturbation
% angle is randangle. Gridsize and nangles are the discretization steps of
% the trajectory prototype feature space.
function tr = create_traj( trnum, startside, startcell, angle1, angle2, angle3, trlen, randangle, gridsize, nangles )    
    
    % set the boudaries of the starting cell
    if( startside == 1) % bot
        miny = 0;
        minx = (startcell-1) / gridsize;
        dir = pi / 2;
    elseif( startside == 2) % right
        minx = (gridsize-1)/gridsize;
        miny = (startcell-1) / gridsize;
        dir = pi;
    elseif( startside == 3) % top
        miny = (gridsize-1) / gridsize;
        minx = 1/gridsize + ((startcell-1) / gridsize);
        dir = pi * 3 / 2;
    else % left
        minx = 0;
        miny = 1/gridsize + ((startcell-1) / gridsize);
        dir = 0;
    end

    % set the starting angles 
    startdir  = dir + (((angle1-1) * (pi/nangles)) + rand() * (pi/nangles) - pi/2) /2; % /2 --> smaller variance in the starting angle
    seconddir = (angle2-1) * (pi/nangles) + rand() * (pi/nangles) - pi/2;
    thirddir  = (angle3-1) * (pi/nangles) + rand() * (pi/nangles) - pi/2;

    % rotation matrices for the three angles
    mat1 = [ cos(startdir), -sin(startdir); sin(startdir), cos(startdir) ];
    mat2 = [ cos(seconddir), -sin(seconddir); sin(seconddir), cos(seconddir) ];
    mat3 = [ cos(thirddir), -sin(thirddir); sin(thirddir), cos(thirddir) ];
    
    tr = zeros(trnum, trlen*2);
    for j = 1:trnum
        % starting pos
        posx = minx + 1/(gridsize*4) + rand() / (gridsize*2);
        posy = miny + 1/(gridsize*4) + rand() / (gridsize*2);
        % starting dir
        d = mat1 * [1/trlen, 0]';
        % create the trajectory!
        for i=1:trlen
            if( i == floor(trlen/3) )
                d = mat2 * d;
            elseif ( i == floor(trlen*2/3) )
                d = mat3 * d;
            end
            theta1 = (rand()-0.5)*(randangle/10);
            theta2 = (rand()-0.5)*randangle;
            randmat1 = [ cos(theta1), -sin(theta1); sin(theta1), cos(theta1) ];
            randmat2 = [ cos(theta2), -sin(theta2); sin(theta2), cos(theta2) ];
            d = randmat1 * d;  % cumulative randomness
            d2 = randmat2 * d; % non-cumulative randomness
            % add the point
            posx = posx + d2(1) ;
            posy = posy + d2(2);
            tr(j,i) = posx;
            tr(j,i+trlen) = posy;
        end
    end
end
        
    