function [outRow, outCol, outO, outS] =...
    templateAffineTransform(tScale, rScale,cScale,rotation,inRow,inCol,inO,inS,nOri)
% templateAffineTranform - Affine transform of vertices in the template.
%
% tScale: change of log-scale for the whole template
% rScale: change of log-scale for row index (small change)
% cScale: change of log-scale for column index (small change)
% rotation: rotation of template
% inX, inY, inO, inS: selected position (relative to the origin), orientation and scale of elements
% nOri: number of quantized orientations inside 0 ~ pi

A1 = eye(3); A1(1,1) = cScale * (2^(tScale/2)); A1(2,2) = rScale * (2^(tScale/2));
angle = rotation * pi/nOri;
A2 = eye(3); A2(1,1) = cos(angle); A2(1,2) = sin(angle); A2(2,1) = -A2(1,2); A2(2,2) = A2(1,1);
outRow = zeros(length(inRow),1);
outCol = zeros(length(inCol),1);
outO = zeros(length(inO),1);
outS = zeros(length(inS),1);

for iF = 1:length(inRow)
    pt = [inCol(iF), -inRow(iF), 1] * A1;
    pt = pt * A2;
    
    outCol(iF) = floor( .5 + pt(1) );
    outRow(iF) = floor( .5 - pt(2) );
    outO(iF) = inO(iF) + rotation;
    outS(iF) = inS(iF) + tScale;
    while outO(iF) < 0
        outO(iF) = outO(iF) + nOri;
    end
    while outO(iF) >= nOri
        outO(iF) = outO(iF) - nOri;
    end
end


% note: during squeezing, the orientations of some elements are changed. But
%    we assume the squeezing effect is negligible on filter orientations.

% Because of scaling, some Gabors are not applicable.
% But we still keep all Gabor elements, and will filter out these elements when
% computing S2 scores.

