<tooltip>
Source:
Format: 35mm (1.6 Crop, 3:2 Aspect Ratio, Portrait orientation)
Focal Length: 100mm lens, overlap: 25%, Horizontal FOV: 6.4, Vertical FOV: 10.7
Rows: 17, Columns: 57
Target:
For 360/180, Horizontal Size: 119880, Vertical Size: 59940
Mosaic Horizontal FOV: 368.0, Vertical FOV: 184.0
Mosaic Horizontal Size: 122544, Vertical Size: 61272
</tooltip>
<!--
! This program is to generate preset for the Papywizard
! program. This program can be used for commercial and/or
! non-commercial use for free.
!
! Author: Jones Henry Subbiah (C) 2009.
!
! Disclaimer: The user assumes the responsibility of any
! any demage using the preset. The author is not responsible
! for anything.
!
! The preset generated assumes top-center (zenith) corner of the pano
! is the home position that is yaw = 0, and pitch = 0. The
! name of the preset will be 35mmformat_focallength_rows_columns
!
! History of changes:
! ====================
! 0.1 Initial public version
! 0.2 Fixed a bug in yaw_skip_pos, pitch_skip_pos
! (affected only when Portrait as source orientation)
! 0.3 Fixed a bug in calculating the vertical shots required
! 0.4 Added history of changes
! 0.5 Removed the base exclusion logic for the 180 degrees
!
-->
<html>
<head>
<title>Papywizard 360 Preset Generator</title>
<script language="Javascript">
var FRAME_WIDTH = 36.0;
var FRAME_HEIGHT = 24.0;
var OPTIMUM_DEGREES = 10.0;
var BASE_EXCLUSION = 0.0;
var DEBUG = false;
var pval = "";
/*
* This function appends the message to the text box.
*/
function write ( message )
{
pval += message + "\n";
}
/*
* This function appends debug messages to the text box.
*/
function debug ( message )
{
if ( DEBUG )
write ( message );
}
/*
* This function calculates the angular field of view.
*/
function calculate_fov ( frame_length, focal_length )
{
return ( 2 * Math.atan ( frame_length / ( 2 * focal_length ) ) * 180 / Math.PI );
}
/*
* This function validates the input.
* Input validation is done only for text box fields.
*/
function validate_input()
{
if ( isNaN ( parseFloat ( document.main.fl.value ) ) )
{
alert ( "Enter a valid focal length" );
document.main.fl.focus();
return false;
}
return true;
}
/*
* This function rounds a number to a single decimal precision.
* The trick to is to add 0.05 to the number and truncate at the first
* decimal position.
*/
function round21 ( number )
{
nnum = number + 0.05;
nums = nnum.toString();
numa = nums.split('.');
return ( numa[0] + '.' + numa[1].charAt(0) );
}
/*
* This function finds the number of yaw positions to skip.
*/
function yaw_skip_pos ( hfov, vfov )
{
var yaw = 0.0;
var ydiff = 0;
while ( 1 )
{
if ( yaw > OPTIMUM_DEGREES )
{
break;
}
ydiff++;
yaw += hfov;
}
debug ( "ydiff: " + ydiff );
if ( ydiff < 1 )
ydiff = 1;
debug ( "ydiff: " + ydiff );
return ( ydiff );
}
/*
* This function finds the number of pitch positions to skip.
*/
function pitch_skip_pos ( hfov, vfov )
{
var pitch = 0.0;
var pdiff = 0;
while ( 1 )
{
if ( pitch > OPTIMUM_DEGREES )
{
break;
}
pdiff++;
pitch += vfov;
}
debug ( "pdiff: " + pdiff );
if ( pdiff < 1 )
pdiff = 1;
debug ( "pdiff: " + pdiff );
return ( pdiff );
}
/*
* This function initializes all the position of the pano.
* The position is of the form "row,col,pitch,yaw".
* Each position of the pano is represented here in the String array.
*/
function initialize_positions ( hfov, vfov, prows, pcols )
{
var pos = new Array ( prows * pcols );
var yaw = 0.0;
var pitch = Number ( round21 ( vfov / 2 ) );
for ( ctr1 = 0; ctr1 < prows; ctr1++ )
{
for ( ctr2 = 0; ctr2 < pcols; ctr2++ )
{
pos[ctr1 * pcols + ctr2] = ( ctr1 + 1 ) + "," + ( ctr2 + 1 ) + "," + round21 ( pitch, 1 ) + "," + round21 ( yaw, 1 );
yaw += hfov;
}
pitch += vfov;
yaw = 0;
}
for ( ctr1 = 0; ctr1 < pos.length; ctr1++ )
{
debug ( "pos[" + ctr1 + "]: " + pos[ctr1] );
}
return ( pos );
}
/*
* This function initializes the row, paired row values.
* The array index is the row number and the array value is the paired row number.
*/
function initialize_rows ( prows )
{
var prs = new Array ( prows );
for ( ctr1 = 0; ctr1 < prows; ctr1++ )
{
prs[ctr1] = -1;
debug ( "prs[" + ctr1 + "]: " + prs[ctr1] );
}
return ( prs );
}
/*
* This function finds the row used already as a paired row.
*/
function find_paired_row ( prs, prow )
{
for ( var ctr = 0; ctr < prs.length; ctr++ )
{
if ( prs[ctr] == prow )
{
return ( ctr );
}
}
return ( -1 );
}
/*
* This function finds the row and its corresponding paired row.
*/
function calculate_paired_row ( prs, pdiff )
{
var prows = prs.length;
for ( var ctr = 0; ctr < prows; ctr++ )
{
if ( ctr + pdiff < prows )
{
prs[ctr] = ctr + pdiff;
}
var prw = find_paired_row ( prs, ctr );
debug ( 'prw: ' + prw );
if ( prw != -1 )
{
debug ( 'here' );
prs[ctr] = -2;
}
}
for ( ctr1 = 0; ctr1 < prows; ctr1++ )
{
debug ( "prs[" + ctr1 + "]: " + prs[ctr1] );
}
return ( prs );
}
/*
* This function writes the "pict" element of the preset XML.
*/
function print_shoot ( pos )
{
var val = pos.split(',');
write ( ' <pict yaw="' + Number ( val[3] ).toFixed(1) + '" pitch="-' + Number ( val[2] ).toFixed(1) + '"/> <!-- ' + Number ( val[0] ).toFixed(0) + ',' + Number ( val[1] ).toFixed(0) + ' -->' );
}
/*
* This function creates the normal move of the head.
* The normal move is defined as
* row 1 as left-to-right
* row 2 as right-to-left
* row 3 as left-to-right
* ...
*/
function do_normal_move ( prows, pcols, pos )
{
for ( var ridx = 0; ridx < prows; ridx++ )
{
if ( ( ridx + 1 ) % 2 == 1 )
{
var cidx = 0;
write ( " <!-- arrange columns left to right in row " + ( ridx + 1 ) + " starting from column " + ( cidx + 1 ) + " -->" );
for ( ; cidx < pcols; cidx++ )
{
print_shoot ( pos[ridx*pcols+cidx] );
}
}
else
{
var cidx = pcols - 1;
write ( " <!-- arrange columns right to left in row " + ( ridx + 1 ) + " starting from column " + ( cidx + 1 ) + " -->" );
for ( ; cidx >= 0; cidx-- )
{
print_shoot ( pos[ridx*pcols+cidx] );
}
}
}
}
/*
* This function creates the special move of the head.
* The special move is done by moving the head around 10.0 degrees like
* row1 columns that have around 10.0 move
* row3(paired row) columns that are reverse from the initial row
* row2 (non-paired row) columns that are 10.0 degrees apart in the repeating order
*/
function do_special_move ( prows, pcols, pos, prs, ydiff, pdiff )
{
var c = new Array ( pcols );
var cnt = 0;
for ( var ridx = 0; ridx < prows; ridx++ )
{
if ( prs[ridx] == -2 )
{
continue;
}
else if ( prs[ridx] == -1 )
{
write ( " <!-- columns in row " + ( ridx + 1 ) + " is not paired -->" );
for ( var ctr = 0; ctr <= ( ydiff + 1 ); ctr++ )
{
if ( ( ydiff + 1 ) >= ( ctr + 1 ) )
{
cnt = 0;
for ( var cidx = ctr; cidx < pcols; cidx += ydiff + 1 )
{
c[cnt++] = ridx * pcols + cidx;
}
if ( ( ctr + 1 ) % 2 == 0 && pcols > 10 )
{
write ( " <!-- arrange columns right to left in row " + ( ridx + 1 ) + " starting from column " + ( ctr + 1 ) + " -->" );
for ( var aidx = cnt - 1; aidx >= 0; aidx-- )
{
print_shoot ( pos[c[aidx]] );
}
}
else
{
write ( " <!-- arrange columns left to right in row " + ( ridx + 1 ) + " starting from column " + ( ctr + 1 ) + " -->" );
for ( var aidx = 0; aidx < cnt; aidx++ )
{
print_shoot ( pos[c[aidx]] );
}
}
}
}
}
else
{
write ( " <!-- columns in row " + ( ridx + 1 ) + " is paired with row " + ( prs[ridx] + 1 ) + " -->" );
for ( var ctr = 0; ctr < ydiff + 1; ctr++ )
{
if ( ctr + ydiff < pcols )
{
cnt = 0;
write ( " <!-- arrange columns left to right in row " + ( ridx + 1 ) + " starting from column " + ( ctr + 1 ) + " -->" );
for ( var cidx = ctr; cidx < pcols; cidx += ydiff + 1 )
{
print_shoot ( pos[ridx*pcols+cidx] );
c[cnt++] = cidx + 1;
}
}
if ( prs[ridx] < prows && c[cnt-1] > 0 )
{
write ( " <!-- arrange columns right to left in row " + ( prs[ridx] + 1 ) + " starting from column " + c[cnt-1] + " -->" );
for ( var cidx = cnt - 1; cidx >= 0; cidx-- )
{
print_shoot ( pos[prs[ridx]*pcols+c[cidx]-1] );
}
}
}
}
}
}
/*
* This function is the main function that creates the full preset XML.
*/
function do_preset()
{
var thfov = 0.0;
var hfov = 0.0;
var tvfov = 0.0;
var vfov = 0.0;
var focal_length = 0.0;
var crop_factor = 0.0;
var overlap = 0.0;
var ratio = 0.0;
var prows = 0;
var pcols = 0;
var ar = '';
var wip = 0;
var hip = 0;
var scan_pixel = 0;
var eff_vert = 0.0;
pval = "";
if ( validate_input() )
{
focal_length = parseFloat ( document.main.fl.value );
crop_factor = parseFloat ( document.main.cf.options[document.main.cf.selectedIndex].value );
overlap = parseFloat ( document.main.ol.options[document.main.ol.selectedIndex].value );
ar = (document.main.r.options[document.main.r.selectedIndex].value).split ( ',' );
ratio = parseFloat ( ar[1] );
orientation = document.main.or.value;
wip = parseInt ( document.main.wip.value );
hip = parseInt ( document.main.hip.value );
debug ( "focal_length: " + focal_length );
debug ( "crop_factor: " + crop_factor );
debug ( "overlap: " + overlap );
debug ( "ratio: " + ratio );
debug ( "orientation: " + orientation );
debug ( "wip: " + wip );
debug ( "hip: " + hip );
thfov = calculate_fov ( FRAME_WIDTH / crop_factor, focal_length );
hfov = thfov * ( 1.0 - overlap / ratio / 100.0 );
hfov = Number ( round21 ( hfov ) );
tvfov = calculate_fov ( FRAME_HEIGHT / crop_factor, focal_length );
vfov = tvfov * ( 1.0 - overlap / 100.0 );
vfov = Number ( round21 ( vfov ) );
if ( orientation == 'P' )
{
var tmp = hfov;
hfov = vfov;
vfov = tmp;
}
debug ( "hfov: " + hfov );
debug ( "vfov: " + vfov );
//eff_vert = ( 180.0 - BASE_EXCLUSION - vfov / 2 );
eff_vert = 180.0;
prows = Math.ceil ( eff_vert / vfov );
pcols = Math.ceil ( 360.0 / hfov );
debug ( "eff_vert: " + eff_vert );
debug ( "prows: " + prows );
debug ( "pcols: " + pcols );
scan_pixel = Math.round ( wip / thfov );
debug ( "scan_pixel: " + scan_pixel );
var pos = initialize_positions ( hfov, vfov, prows, pcols );
var prs = initialize_rows ( prows );
var ydiff = yaw_skip_pos ( hfov, vfov );
var pdiff = pitch_skip_pos ( hfov, vfov );
prs = calculate_paired_row ( prs, pdiff );
write ( '<?xml version="1.0" encoding="utf-8"?>\n' );
write ( '<papywizard>\n' );
write ( ' <preset name="35' + ( crop_factor * 10 ) + orientation + '_' + focal_length + '_' + prows + '_' + pcols + '">' );
write ( ' <tooltip>' );
write ( ' Source:' );
write ( ' Format: 35mm (' + crop_factor + ' Crop, ' + ar[0] + ' Aspect Ratio' + ', ' + ( orientation == 'L' ? 'Landscape' : 'Portrait' ) + ' orientation)' );
write ( ' Focal Length: ' + focal_length + 'mm lens, overlap: ' + overlap + '%, Horizontal FOV: ' + hfov + ', Vertical FOV: ' + vfov );
write ( ' Rows: ' + prows + ', Columns: ' + pcols );
var target_hfov = ( hfov * pcols + thfov * overlap / 100.0 ).toFixed(1);
var target_vfov = ( vfov * prows + tvfov * overlap / 100.0 ).toFixed(1);
write ( ' Target:' );
write ( ' For 360/180, Horizontal Size: ' + Math.round ( 360 * scan_pixel ) + ', Vertical Size: ' + Math.round ( 180 * scan_pixel ) );
write ( ' Mosaic Horizontal FOV: ' + target_hfov + ', Vertical FOV: ' + target_vfov );
write ( ' Mosaic Horizontal Size: ' + Math.round ( target_hfov * scan_pixel ) + ', Vertical Size: ' + Math.round ( target_vfov * scan_pixel ) );
write ( ' </tooltip>' );
write ( ' <shoot>' );
if ( hfov > OPTIMUM_DEGREES )
{
do_normal_move ( prows, pcols, pos );
}
else
{
do_special_move ( prows, pcols, pos, prs, ydiff, pdiff );
}
write ( ' </shoot>' );
write ( ' </preset>\n' );
write ( '</papywizard>' );
document.main.preset.value = pval;
}
}
</script>
</head>
<body onload="document.main.preset.value = '';document.main.fl.focus();" bgcolor="#cccccc">
<form name="main">
<table border="0" cellpadding="2" cellspacing="2" width="800">
<tr>
<td>Crop Factor</td>
<td>
<select name="cf" style="width:100px">
<option value="1.0">1.0</option>
<option value="1.3">1.3</option>
<option value="1.5">1.5</option>
<option value="1.6" selected>1.6</option>
<option value="1.7">1.7</option>
<option value="1.8">1.8</option>
<option value="2.0">2.0</option>
</select>
</td>
<td>Aspect Ratio</td>
<td>
<select name="r" style="width:100px">
<option value="3:2,1.500000" selected>3:2</option>
<option value="4:3,1.333333">4:3</option>
<option value="5:4,1.250000">5:4</option>
<option value="16:9,1.777778">16:9</option>
</select>
</td>
<td>
Overlap
</td>
<td>
<select name="ol" style="width:100px">
<option value="20">20</option>
<option value="25" selected>25</option>
<option value="30">30</option>
<option value="35">35</option>
<option value="40">40</option>
<option value="45">45</option>
<option value="50">50</option>
</select>
%
</td>
</tr>
<tr>
<td>Orientation</td>
<td>
<select name="or" style="width:100px">
<option value="L">Landscape</option>
<option value="P" selected>Portrait</option>
</select>
</td>
<td>Focal Length</td>
<td>
<input type="text" name="fl" style="width:100px" value="100">
</td>
<td>Width in Pixels</td>
<td>
<input type="text" name="wip" style="width:100px" value="4272">
</td>
</tr>
<tr>
<td>Preset</td>
<td> </td>
<td>Height in Pixels</td>
<td>
<input type="text" name="hip" style="width:100px" value="2848">
</td>
<td> </td>
<td>
<input type="button" value="Generate" style="width:100px" onClick="do_preset();">
</td>
</tr>
<tr>
<td colspan="6">
<textarea name="preset" rows="18" cols="95"></textarea>
</td>
</tr>
</table>
</form>
</body>
</html>
sjhenry wrote:Paul,
I updated the script to generate correct number of pictures for the 360/180. The current script shows me 2X8 pictures in portrait or 3X5 for landscape mode with crop factor 2 and 9mm lens.
Let me know if the generated preset works for you.
Jones
fma38 wrote:But what if it is not possible to go to zenith position?
Details zum Fehler auf der Webseite
Benutzer-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)
Zeitstempel: Sun, 26 Jul 2009 09:53:51 UTC
Meldung: 'numa.1' ist Null oder kein Objekt
Zeile: 90
Zeichen: 9
Code: 0
URI: file://192.168.0.200/georg/downloads/papywizzard/pw_preset/pw_360_preset.html
Users browsing this forum: No registered users and 1 guest