--- a/APSCpp/APSCpp_main.c
+++ b/APSCpp/APSCpp_main.c
@@ -1,20 +1,21 @@
 
-/* APSCpp_main.c  18 Feb2008 TKSharpless
-
- enhanced version of APSC for Hugin 0.7 that can transform images to
- stereographic projection for better keypoint matching.
-
- The enhanced mode is invoked by giving it a project file in place
- of the image files.  The project file 'i' lines supply information
- about the images' projections, as well as their file names.  This
- info is stored in DIlist.  The keypoint generator (and the refine
- keypoints step if used) converts intensity maps to stereographic 
- projection using info from DIlist. At tne final output-to-pto stage 
- the control point coordinates get projected back to image space.
-
- The projections are "ideal" (no lens or center point corrections), but
- the reprojection machinery could handle those if available.
-
+/* APSCpp_main.c  original 18 Feb2008 TKSharpless
+				  revised  27 July 2009 TKSharpless
+
+ Enhanced version of autopano-sift-c.  Notable enchancements:
+ - All-in-one, runs as a plugin under Hugin, no bulky XML files.
+ - Uses ANN k-d tree implementation, far faster than original,
+   and float instead of double feature vectors.
+ - Can read image specifications from Hugin, PTStitcher, PTGui or
+   PTAssembler project files.  Specs include lens type, field of
+   view, lens correction coefficients and image alignment angles
+   as well as the file name and dimensions.  These are copied to
+   the output Hugin project file along with the keypoints.
+ - When able to compute image angular scale, can reproject: to
+   stereographic for keypoint finding; to spherical for control
+   point validation; to aligned stereographic for fine keypoint
+   adjustment.
+ 
  * (C) Copyright 2004 -- Sebastian Nowozin (nowozin@cs.tu-berlin.de)
  *
  * "The University of British Columbia has applied for a patent on the SIFT
@@ -74,10 +75,10 @@
 	WriteLine ("Options that affect image processing");
 	WriteLine ("  --maxdim <n>            Make largest image dimension <= n (default: 1600).");
 	WriteLine ("  --projection <n>,<d>    n = PT format code, d = hfov in degrees, for all images.");
-	WriteLine ("  --equal-angle-fisheye   lens type for format codes 2,3. Default is equal-area.");
+	WriteLine ("  --equal-angle-fisheye   change assumed type for format codes 2,3 from equal-area.");
 	WriteLine ("  --lens-type <1|2|3>     set lens type 1: rectlinear ('normal'), 2: equal-area");
 	WriteLine ("                          fisheye (common), 3: equal-angle fisheye (uncommon).");
-	WriteLine ("                          Used instead of format code, for all images.");
+	WriteLine ("                          Used instead of format code default, for all images.");
 	WriteLine ("  --focal-length <mm>,<cf> mm = lens focal length in mm, cf = camera crop factor.");
 	WriteLine ("                          Used instead of hfov, for all images.");
 	WriteLine ("  --stereographic <on|off|1|0> reprojection on (if enabled) or off. Default on.");
@@ -96,11 +97,6 @@
 	WriteLine ("  --absolute-pathnames <on|off|1|0>   Use the absolute pathname of the image");
 	WriteLine ("                          file in the PTO output file. Disabled by default.");
 	WriteLine ("  --disable-areafilter    Do not use max-area filtration, which is default.");
-	WriteLine ("                          See manpage for details.");
-	WriteLine ("  --refine                Refine control points using the original images.");
-	WriteLine ("  --refine-by-middle      Use the best middle point to refine (default).");
-	WriteLine ("  --refine-by-mean        Use the mean of the patches control points.");
-	WriteLine ("  --keep-unrefinable <on|off|1|0>  Keep unrefinable CPs (default: on).");
 	WriteLine ("");
 }
 
@@ -139,263 +135,6 @@
 		return (0);
 	
 	return (1);
-}
-
-
-
-
-// The maximum radius to consider around a keypoint that is refined.  That
-// is, at most a patch of a maximum size of twice this value in both
-// horizontal and vertical direction is extracted.
-int RefinementRadiusMaximum = 96;
-int (*refineHandler)(int index, int total);
-
-
-void RefineKeypoints (ArrayList* msList,
-		      bool selectMiddlePoint, bool neverLosePoints);
-DisplayImage* ExtractPatch (DisplayImage* large,
-			    int px, int py, double scale, int* radius);
-ArrayList* ExtractKeypoints (DisplayImage* pic);
-bool YesNoOption (char* optionName, char* val, int * nerr);
-
-// selectMiddlePoint: if true, select the middle point in the patch,
-//   otherwise build the mean
-// neverLosePoints: if true, and if we cannot do the refinement, still use
-//   the control point.
-void RefineKeypoints (ArrayList* msList,
-		bool selectMiddlePoint, bool neverLosePoints)
-{
-	DisplayImage* pic1 = NULL;
-	DisplayImage* pic2 = NULL;
-	char* pic1Name = NULL;
-	char* pic2Name = NULL;
-
-	/* Keep stats for the refineHandler delegate
-	 */
-	int totalRefines = 0;
-	int doneRefines = 0;
-	int i;
-	for(i=0; i<ArrayList_Count(msList); i++) {
-		MatchSet* ms = (MatchSet*) ArrayList_GetItem(msList, i);
-		int j;
-		for(j=0; j<ArrayList_Count(ms->matches); j++) {
-			ArrayList_GetItem(ms->matches, j);
-			totalRefines += 1;
-		}
-	}
-
- 
-	for(i=0; i<ArrayList_Count(msList); i++) {
-		MatchSet* ms = (MatchSet*) ArrayList_GetItem(msList, i);
-		WriteLine ("  between \"%s\" and \"%s\"",
-			   ms->file1, ms->file2);
-		
-		if (pic1Name != ms->file1) {
-			pic1Name = ms->file1;
-			pic1 = DisplayImage_new (ms->file1);
-		}
-		if (pic2Name != ms->file2) {
-			pic2Name = ms->file2;
-			pic2 = DisplayImage_new (ms->file2);
-		}
-		/*WriteLine ("pair: %s, %s, %d keypoint matches",
-		  ms->file1, ms->file2, ArrayList_Count(ms->Matches));*/
-		
-		ArrayList* refinedMatches = ArrayList_new0 (NULL);
-
-		int j;
-		for(j=0; j<ArrayList_Count(ms->matches); j++) {
-			Match* m = (Match*) ArrayList_GetItem(ms->matches, j);
-
-			int p1x = (int) (m->kp1->x + 0.5);
-			int p1y = (int) (m->kp1->y + 0.5);
-			int p1radius;
-			DisplayImage* patch1 = ExtractPatch (pic1, p1x, p1y,
-							    m->kp1->scale, &p1radius);
-
-			int p2x = (int) (m->kp2->x + 0.5);
-			int p2y = (int) (m->kp2->y + 0.5);
-			int p2radius;
-			DisplayImage* patch2 = ExtractPatch (pic2, p2x, p2y,
-							     m->kp2->scale, &p2radius);
-
-			/* Call the refine handler delegate in case there is one to
-			 * inform the callee of a single refining step (for progress
-			 * bar displays and such).
-			 */
-			doneRefines += 1;
-			if (refineHandler != NULL)
-				refineHandler (doneRefines, totalRefines);
-
-			// Skip over keypoint matches we cannot refine as part of the
-			// image lies outside.
-			if (patch1 == NULL || patch2 == NULL) {
-				if (neverLosePoints)
-					ArrayList_AddItem(refinedMatches, m);
-                                DisplayImage_delete(patch1);
-                                DisplayImage_delete(patch2);
-				continue;
-			}
-
-			// Otherwise, run the SIFT algorithm on both small patches.
-			ArrayList* p1kp = ExtractKeypoints (patch1);
-			ArrayList* p2kp = ExtractKeypoints (patch2);
-			/*WriteLine ("p1kp = %d, p2kp = %d", ArrayList_Count(p1kp),
-			  ArrayList_Count(p2kp));*/
-			
-			// Apply the matching, RANSAC enabled.
-			MultiMatch* mm = MultiMatch_new0 ();
-			mm->verbose = false;
-
-			ArrayList* matches = NULL;
-			matches = MultiMatch_TwoPatchMatch (mm, p1kp,
-							    patch1->width, patch1->height, p2kp, patch2->width,
-							    patch2->height, true);
-                        DisplayImage_delete(patch1);
-                        DisplayImage_delete(patch2);
-
-			/* In case there are less than three keypoints in the
-			 * two patches, we ignore them all.
-			 */
-			if (0 /*was exception ???*/ ) { 
-				matches = NULL;
-			}
-
-			if (matches == NULL || ArrayList_Count(matches) != 1) {
-				if (neverLosePoints)
-					ArrayList_AddItem(refinedMatches, m);
-
-				continue;
-			}
-
-			MatchSet* pSet = (MatchSet*) ArrayList_GetItem(matches, 0);
-
-			// Now get the real new control point coordinates from the
-			// patches.  We have two options and assume all points are
-			// equal quality-wise:
-			//   a) Select the one that is most in the middle
-			//      (selectMiddlePoint == true)
-			//   b) Build the mean of all the control point matches in the
-			//      patches (selectMiddlePoint == false).
-			double kp1X = 0.0;
-			double kp1Y = 0.0;
-			double kp2X = 0.0;
-			double kp2Y = 0.0;
-			double kpMidDist = Double_PositiveInfinity;
-
-			int k;
-			for(k=0; k<ArrayList_Count(pSet->matches); k++) {
-				Match* pM = (Match*) ArrayList_GetItem(pSet->matches, k);
-				if (selectMiddlePoint) {
-					double dist = sqrt (
-						pow (pM->kp1->x - p1radius, 2.0) +
-						pow (pM->kp1->y - p1radius, 2.0));
-					
-					if (dist < kpMidDist) {
-						kpMidDist = dist;
-						
-						kp1X = pM->kp1->x;
-						kp1Y = pM->kp1->y;
-						
-						kp2X = pM->kp2->x;
-						kp2Y = pM->kp2->y;
-					}
-				} else {
-					kp1X += pM->kp1->x;
-					kp1Y += pM->kp1->y;
-					
-					kp2X += pM->kp2->x;
-					kp2Y += pM->kp2->y;
-				}
-
-				/*WriteLine ("(%g, %g) matches (%g, %g)",
-				  pM->kp1->x, pM->kp1->y, pM->kp2->x, pM->kp2->y);*/
-			}
-
-			if (selectMiddlePoint == false) {
-				kp1X /= (double) ArrayList_Count(pSet->matches);
-				kp1Y /= (double) ArrayList_Count(pSet->matches);
-				kp2X /= (double) ArrayList_Count(pSet->matches);
-				kp2Y /= (double) ArrayList_Count(pSet->matches);
-			}
-
-			kp1X += p1x - p1radius;
-			kp1Y += p1y - p1radius;
-
-			kp2X += p2x - p2radius;
-			kp2Y += p2y - p2radius;
-
-			Match* mn = Match_clone (m);
-
-			// Adjust the original keypoints location to be the mean of
-			// all the highly precise superresolution points.
-			mn->kp1->x = kp1X;
-			mn->kp1->y = kp1Y;
-
-			mn->kp2->x = kp2X;
-			mn->kp2->y = kp2Y;
-
-			/*WriteLine ("MASTER POINT MATCH: (%g,%g) to (%g,%g)",
-			  kp1X, kp1Y, kp2X, kp2Y);*/
-
-			ArrayList_AddItem(refinedMatches, mn);
-			/*
-			  DisplayImage_Save (patch1, "patch-1.jpg");
-			  DisplayImage_Save (patch2, "patch-2.jpg");
-			  exit (0);
-			*/
-		}
-
-		ms->matches = refinedMatches;
-	}
-}
-
-/** Extract a small image patch from a larger image, centered at the given
- * coordinates.
- */
-DisplayImage* ExtractPatch (DisplayImage* large,
-			    int px, int py, double scale, int* radius)
-{
-	*radius = (int) (9.0 * scale + 0.5);
-	if (*radius > RefinementRadiusMaximum)
-		*radius = RefinementRadiusMaximum;
-
-	/*WriteLine ("patch centered at (%d,%d), scale %g, radius = %d",
-	  px, py, scale, *radius);*/
-
-	int pxe = px + *radius;
-	int pye = py + *radius;
-	px -= *radius;
-	py -= *radius;
-
-	if (px < 0 || py < 0 || pxe >= large->width || pye >= large->height) {
-		/*WriteLine ("   (%d,%d)-(%d,%d) out of (0,0)-(%d,%d)",
-		  px, py, pxe, pye, large->width, large->height);*/
-
-		return (NULL);
-	} else {
-		//WriteLine ("   extracting patch");
-	}
-	DisplayImage* patch = DisplayImage_Carve (large, px, py, *radius*2, *radius*2);
-
-	return (patch);
-}
-
-/** Produce keypoints for a small image patch.
- */
-ArrayList* ExtractKeypoints (DisplayImage* pic)
-{
-	ImageMap* picMap = DisplayImage_ConvertToImageMap (pic);
-	
-	LoweFeatureDetector* lf = LoweFeatureDetector_new0 ();
-	LoweFeatureDetector_SetPrintWarning(false);
-	LoweFeatureDetector_SetVerbose(false);
-	LoweFeatureDetector_DetectFeatures (lf, picMap);
-	
-        ArrayList* res = LoweFeatureDetector_GlobalNaturalKeypoints(lf);
-        lf->globalNaturalKeypoints = NULL; // Make sure res won't get deleted.
-        LoweFeatureDetector_delete(lf);
-        return res;
 }
 
 // check a commandline truth value
@@ -590,11 +329,6 @@
 	// Use "keep-best" filtration, keep the maxMatches best.
 	int maxMatches = 25;	// default
   
-	// Refinement options
-	bool refine = false;
-	bool refineMiddle = true;
-	bool keepUnrefinable = true;
-  
 	int optionCount = 0;
 	int optionN = 1;
 	int i;
@@ -638,13 +372,13 @@
 				joptN = 2;
 				char *p = argv[optionN + 1];
 				if(sscanf( p, "%g", &FLmm ) != 1 ){
-					WriteLine ("Invalid focal-length parameter");
+					WriteLine ("Invalid focal length");
 					++Nerr;
 				}
 				p = strchr(p,',');
 				if( !p || sscanf( p, "%g", &cropFactor ) != 1 )
 				{
-					WriteLine ("Invalid focal-length parameter");
+					WriteLine ("Invalid crop factor");
 					++Nerr;
 				}
 			} else if (strcmp (optionStr, "--ransac") == 0) {
@@ -662,10 +396,17 @@
 			} else if (strcmp (optionStr, "--lens-correction") == 0) {
 				joptN = 2;
 				lensCorrection = YesNoOption ("--lens-correction", argv[optionN + 1], &Nerr );
+			} else if (strcmp (optionStr, "--lens-type") == 0) {
+				joptN = 2;
+				if( sscanf( argv[optionN + 1], "%d", &lensType) != 1
+					|| lensType < 1 || lensType > 3 ){
+					WriteLine ("Invalid --lens-type.");
+					++Nerr;
+				}
 			} else if (strcmp (optionStr, "--maxmatches") == 0) {
 				joptN = 2;
 				if (sscanf(argv[optionN + 1], "%d",  &maxMatches) != 1) {
-					WriteLine ("Parameter to maxmatches option invalid. See the usage help.");
+					WriteLine ("Invalid --maxmatches.");
 					++Nerr;
 				}
 				if (maxMatches < 0) {
@@ -681,15 +422,6 @@
 			} else if (strcmp (optionStr, "--absolute-pathnames") == 0) {
 				joptN = 2;
 				useAbsolutePathnames = YesNoOption ("--absolute-pathnames", argv[optionN + 1], &Nerr);
-			} else if (strcmp (optionStr, "--refine") == 0) {
-				refine = true;
-			} else if (strcmp (optionStr, "--refine-by-middle") == 0) {
-				refineMiddle = true;
-			} else if (strcmp (optionStr, "--refine-by-mean") == 0) {
-				refineMiddle = false;
-			} else if (strcmp (optionStr, "--keep-unrefinable") == 0) {
-				joptN = 2;
-				keepUnrefinable = YesNoOption ("--keep-unrefinable", argv[optionN + 1], &Nerr);
 			} else {
 				WriteLine ("Bad option \"%s\"", optionStr);
 				++Nerr;
@@ -869,11 +601,6 @@
 	} else
 		WriteLine ("");
 
-	if (refine) {
-		WriteLine ("Refining keypoints");
-		RefineKeypoints (msList, refineMiddle, keepUnrefinable);
-	}
-
 	FILE* pto;
 	if ( streamout ) {
 		pto = stdout;