Index: /issm/trunk/src/c/modules/Shp2Kmlx/Shp2Kmlx.cpp
===================================================================
--- /issm/trunk/src/c/modules/Shp2Kmlx/Shp2Kmlx.cpp	(revision 10379)
+++ /issm/trunk/src/c/modules/Shp2Kmlx/Shp2Kmlx.cpp	(revision 10380)
@@ -12,6 +12,5 @@
 
 int Shp2Kmlx(char* filshp,char* filkml,
-			 int sgn,
-			 bool holes){
+			 int sgn){
 
 	#ifdef _HAVE_SHAPELIB_ //only works if Shapelib library has been compiled in.
@@ -23,6 +22,5 @@
 
 	return(Shp2Kmlx(filshp,filkml,
-					sgn,cm,sp,
-					holes));
+					sgn,cm,sp));
 
 	#endif //ifdef _HAVE_SHAPELIB_
@@ -30,6 +28,5 @@
 
 int Shp2Kmlx(char* filshp,char* filkml,
-			 int sgn,double cm,double sp,
-			 bool holes){
+			 int sgn,double cm,double sp){
 
 	#ifdef _HAVE_SHAPELIB_ //only works if Shapelib library has been compiled in.
@@ -38,8 +35,8 @@
 	int     lwidth=1;
 	double  popac=0.50;
-	int     nshap;
+	int     nshape,ncoord;
+	double  cpsum;
 	int     *pstype=NULL,*pnpart=NULL,**ppstrt=NULL,**pptype=NULL,*pnvert=NULL;
 	double  **pshapx=NULL,**pshapy=NULL,**pshapz=NULL,**pshapm=NULL;
-	bool    *closed=NULL;
 	double  *lat=NULL,*lon=NULL;
 
@@ -97,14 +94,14 @@
 			adfMaxBound[3] );
 
-	nshap=nEntities;
-	pstype=(int *) xmalloc(nshap*sizeof(int));
-	pnpart=(int *) xmalloc(nshap*sizeof(int));
-	ppstrt=(int **) xmalloc(nshap*sizeof(int *));
-	pptype=(int **) xmalloc(nshap*sizeof(int *));
-	pnvert=(int *) xmalloc(nshap*sizeof(int));
-	pshapx=(double **) xmalloc(nshap*sizeof(double *));
-	pshapy=(double **) xmalloc(nshap*sizeof(double *));
-	pshapz=(double **) xmalloc(nshap*sizeof(double *));
-	pshapm=(double **) xmalloc(nshap*sizeof(double *));
+	nshape=nEntities;
+	pstype=(int *) xmalloc(nshape*sizeof(int));
+	pnpart=(int *) xmalloc(nshape*sizeof(int));
+	ppstrt=(int **) xmalloc(nshape*sizeof(int *));
+	pptype=(int **) xmalloc(nshape*sizeof(int *));
+	pnvert=(int *) xmalloc(nshape*sizeof(int));
+	pshapx=(double **) xmalloc(nshape*sizeof(double *));
+	pshapy=(double **) xmalloc(nshape*sizeof(double *));
+	pshapz=(double **) xmalloc(nshape*sizeof(double *));
+	pshapm=(double **) xmalloc(nshape*sizeof(double *));
 
 /*  loop over the list of shapes  */
@@ -206,9 +203,4 @@
 
 	SHPClose( hSHP );
-
-/*  read exp file  */
-
-//	if (!DomainOutlineRead(&nshap,&pnvert,&pshapx,&pshapy,&closed,filshp,false))
-//		_error_("Error reading exp file.");
 
 /*  construct kml file  */
@@ -273,5 +265,5 @@
 /*  loop over the list of shapes  */
 
-	for (i=0; i<nshap; i++) {
+	for (i=0; i<nshape; i++) {
 
 /*  null type  */
@@ -337,5 +329,9 @@
 			sprintf(kplace->styleurl  ,"#RandomLineEmptyPoly");
 
+/*  create a multigeometry to hold all the lines  */
+
 			kmulti=new KML_MultiGeometry();
+
+/*  convert to lat/lon, if necessary  */
 
 			lat=(double *) xmalloc(pnvert[i]*sizeof(double));
@@ -348,4 +344,6 @@
 				memcpy(lat,pshapy[i],pnvert[i]*sizeof(double));
 			}
+
+/*  loop over the lines  */
 
 			for (j=0; j<pnpart[i]; j++) {
@@ -378,107 +376,120 @@
 				 pstype[i] == SHPT_POLYGONZ ||
 				 pstype[i] == SHPT_POLYGONM) {
-			_printf_(true,"Warning -- Shape %d of type \"%s\" will be ignored.\n",
-					 i,SHPTypeName( pstype[i] ));
-			continue;
-
-/*  polygon with multiple holes  */
-
-	if (holes) {
-		i=0;
-		kplace=new KML_Placemark();
-		sprintf(kplace->name      ,"Polygon with Holes");
-		kplace->visibility=true;
-		sprintf(kplace->styleurl  ,"#BlackLineRandomPoly");
-
-		kpoly =new KML_Polygon();
-		kring =new KML_LinearRing();
-
-		lat=(double *) xmalloc(pnvert[i]*sizeof(double));
-		lon=(double *) xmalloc(pnvert[i]*sizeof(double));
-		Xy2llx(lat,lon,pshapx[i],pshapy[i],pnvert[i],sgn,cm,sp);
-
-		kring->ncoord    =pnvert[i];
-		kring->coords    =(double (*)[3]) xmalloc(pnvert[i]*3*sizeof(double));
-		for (j=0; j<pnvert[i]; j++) {
-			kring->coords[j][0]=lon[j];
-			kring->coords[j][1]=lat[j];
-			kring->coords[j][2]=0.;
-		}
-		xfree((void**)&lon);
-		xfree((void**)&lat);
-
-		(kpoly ->outer     )->AddObject((Object*)kring);
-		kring =NULL;
-
-		for (i=1; i<nshap; i++) {
-			if (!closed[i]) {
-				_printf_(true,"Warning -- Inner profile %d is not closed with \"holes\" specified, so it will be ignored.\n",i+1);
-				continue;
-			}
-
-			kring =new KML_LinearRing();
+
+/*  the shp format specifies that outer rings are cw, while inner rings are ccw.  there
+	may be multiple outer rings and inner rings in any order.  the kml format specifies
+	all rings are ccw (right-hand rule).  there may be only one outer ring with multiple
+	inner rings, and rings are differentiated by keyword.
+
+	at least for now, assume that each cw ring forms a new kml polygon, and each ccw
+	ring forms an inner ring for the most recent outer ring.  a more elaborate solution
+	would be for each inner ring to search in which outer ring it occurs.  */
+
+			kplace=new KML_Placemark();
+
+			sprintf(kplace->name      ,"Shape:%d (%s)  nVertices=%d, nParts=%d",
+					i,SHPTypeName(pstype[i]),pnvert[i],pnpart[i]);
+			kplace->visibility=true;
+			sprintf(kplace->styleurl  ,"#BlackLineRandomPoly");
+
+/*  create a multigeometry to hold all the polygons  */
+
+			kmulti=new KML_MultiGeometry();
+
+/*  convert to lat/lon, if necessary  */
 
 			lat=(double *) xmalloc(pnvert[i]*sizeof(double));
 			lon=(double *) xmalloc(pnvert[i]*sizeof(double));
-			Xy2llx(lat,lon,pshapx[i],pshapy[i],pnvert[i],sgn,cm,sp);
-			kring->ncoord    =pnvert[i];
-			kring->coords    =(double (*)[3]) xmalloc(pnvert[i]*3*sizeof(double));
-			for (j=0; j<pnvert[i]; j++) {
-				kring->coords[j][0]=lon[j];
-				kring->coords[j][1]=lat[j];
-				kring->coords[j][2]=0.;
-			}
+			if (sgn) {
+				Xy2llx(lat,lon,pshapx[i],pshapy[i],pnvert[i],sgn,cm,sp);
+			}
+			else  {
+				memcpy(lon,pshapx[i],pnvert[i]*sizeof(double));
+				memcpy(lat,pshapy[i],pnvert[i]*sizeof(double));
+			}
+
+/*  loop over the polygons  */
+
+			for (j=0; j<pnpart[i]; j++) {
+
+/*  check if polygon is ccw or cw by computing sum of cross products (twice the area)  */
+
+				ncoord=(j<pnpart[i]-1 ? ppstrt[i][j+1]-ppstrt[i][j] : pnvert[i]-ppstrt[i][j]);
+				cpsum =0.;
+
+				for (k=ppstrt[i][j]; k<ppstrt[i][j]+ncoord-1; k++)
+					cpsum +=pshapx[i][k]*pshapy[i][k+1         ]-pshapy[i][k]*pshapx[i][k+1         ];
+				cpsum +=pshapx[i][k]*pshapy[i][ppstrt[i][j]]-pshapy[i][k]*pshapx[i][ppstrt[i][j]];
+
+/*  outer ring (cw) (allow exception for single-part shapes)  */
+
+				if (cpsum < 0 || pnpart[i] == 1) {
+					if (kpoly) {
+						(kmulti->geometry  )->AddObject((Object*)kpoly);
+						kpoly =NULL;
+					}
+
+/*  create a new polygon from the outer ring (reversing cw to ccw)  */
+
+					kpoly =new KML_Polygon();
+					kring =new KML_LinearRing();
+
+					kring->ncoord    =(j<pnpart[i]-1 ? ppstrt[i][j+1]-ppstrt[i][j] : pnvert[i]-ppstrt[i][j]);
+					kring->coords    =(double (*)[3]) xmalloc(kring->ncoord*3*sizeof(double));
+					if (cpsum < 0)
+						for (k=0; k<kring->ncoord; k++) {
+							kring->coords[kring->ncoord-1-k][0]=lon      [ppstrt[i][j]+k];
+							kring->coords[kring->ncoord-1-k][1]=lat      [ppstrt[i][j]+k];
+							kring->coords[kring->ncoord-1-k][2]=pshapz[i][ppstrt[i][j]+k];
+						}
+					else
+						for (k=0; k<kring->ncoord; k++) {
+							kring->coords[k                ][0]=lon      [ppstrt[i][j]+k];
+							kring->coords[k                ][1]=lat      [ppstrt[i][j]+k];
+							kring->coords[k                ][2]=pshapz[i][ppstrt[i][j]+k];
+						}
+
+					(kpoly ->outer     )->AddObject((Object*)kring);
+					kring =NULL;
+				}
+
+/*  inner ring (ccw)  */
+
+				else {
+					if (!kpoly) {
+						_printf_(true,"Warning -- Shape %d of type \"%s\", part %d, expected to be outer loop (cw).\n",
+								 i,SHPTypeName( pstype[i] ),j);
+						continue;
+					}
+
+/*  add the inner ring to the current polygon  */
+
+					kring =new KML_LinearRing();
+
+					kring->ncoord    =(j<pnpart[i]-1 ? ppstrt[i][j+1]-ppstrt[i][j] : pnvert[i]-ppstrt[i][j]);
+					kring->coords    =(double (*)[3]) xmalloc(kring->ncoord*3*sizeof(double));
+					for (k=0; k<kring->ncoord; k++) {
+						kring->coords[k][0]=lon      [ppstrt[i][j]+k];
+						kring->coords[k][1]=lat      [ppstrt[i][j]+k];
+						kring->coords[k][2]=pshapz[i][ppstrt[i][j]+k];
+					}
+
+					(kpoly ->inner     )->AddObject((Object*)kring);
+					kring =NULL;
+				}
+			}
+
+			if (kpoly) {
+				(kmulti->geometry  )->AddObject((Object*)kpoly);
+				kpoly =NULL;
+			}
+
 			xfree((void**)&lon);
 			xfree((void**)&lat);
 
-			(kpoly ->inner     )->AddObject((Object*)kring);
-			kring =NULL;
-		}
-
-		(kplace->geometry  )->AddObject((Object*)kpoly);
-		kpoly =NULL;
-		(kfold ->feature   )->AddObject((Object*)kplace);
-		kplace=NULL;
-	}
-
-/*  multiple polygons or linestrings  */
-
-	else {
-		for (i=0; i<nshap; i++) {
-			kplace=new KML_Placemark();
-
-			if (closed[i]) {
-				sprintf(kplace->name      ,"Polygon %d",i+1);
-				kplace->visibility=true;
-				sprintf(kplace->styleurl  ,"#BlackLineRandomPoly");
-
-				kpoly =new KML_Polygon();
-				kring =new KML_LinearRing();
-
-				lat=(double *) xmalloc(pnvert[i]*sizeof(double));
-				lon=(double *) xmalloc(pnvert[i]*sizeof(double));
-				Xy2llx(lat,lon,pshapx[i],pshapy[i],pnvert[i],sgn,cm,sp);
-
-				kring->ncoord    =pnvert[i];
-				kring->coords    =(double (*)[3]) xmalloc(pnvert[i]*3*sizeof(double));
-				for (j=0; j<pnvert[i]; j++) {
-					kring->coords[j][0]=lon[j];
-					kring->coords[j][1]=lat[j];
-					kring->coords[j][2]=0.;
-				}
-				xfree((void**)&lon);
-				xfree((void**)&lat);
-
-				(kpoly ->outer     )->AddObject((Object*)kring);
-				kring =NULL;
-
-				(kplace->geometry  )->AddObject((Object*)kpoly);
-				kpoly =NULL;
-			}
-
+			(kplace->geometry  )->AddObject((Object*)kmulti);
+			kmulti=NULL;
 			(kfold ->feature   )->AddObject((Object*)kplace);
 			kplace=NULL;
-		}
-	}
 		}
 
@@ -499,5 +510,9 @@
 						 i,SHPTypeName( pstype[i] ),pnpart[i]);
 
+/*  create a multigeometry to hold all the points  */
+
 			kmulti=new KML_MultiGeometry();
+
+/*  convert to lat/lon, if necessary  */
 
 			lat=(double *) xmalloc(pnvert[i]*sizeof(double));
@@ -511,4 +526,6 @@
 			}
 
+/*  loop over the points  */
+
 			for (j=0; j<pnvert[i]; j++) {
 				kpoint=new KML_Point();
@@ -534,4 +551,7 @@
 
 		else if (pstype[i] == SHPT_MULTIPATCH) {
+			_printf_(true,"Warning -- Shape %d of type \"%s\" will be ignored.\n",
+					 i,SHPTypeName( pstype[i] ));
+			continue;
 		}
 
@@ -542,5 +562,4 @@
 					 i,SHPTypeName( pstype[i] ));
 		}
-
 	}
 
@@ -561,5 +580,5 @@
 
 	delete kfile;
-	for (i=nshap-1; i>=0; i--) {
+	for (i=nshape-1; i>=0; i--) {
 		xfree((void**)&(pshapm[i]));
 		xfree((void**)&(pshapz[i]));
@@ -572,5 +591,5 @@
 	xfree((void**)&pshapx);
 	xfree((void**)&pnvert);
-	for (i=nshap-1; i>=0; i--) {
+	for (i=nshape-1; i>=0; i--) {
 		xfree((void**)&(pptype[i]));
 		xfree((void**)&(ppstrt[i]));
Index: /issm/trunk/src/c/modules/Shp2Kmlx/Shp2Kmlx.h
===================================================================
--- /issm/trunk/src/c/modules/Shp2Kmlx/Shp2Kmlx.h	(revision 10379)
+++ /issm/trunk/src/c/modules/Shp2Kmlx/Shp2Kmlx.h	(revision 10380)
@@ -12,6 +12,4 @@
 #endif
 
-#include <float.h>    /*  DBL_MAX  */
-
 #ifdef _HAVE_SHAPELIB_ //only works if Shapelib library has been compiled in.
 
@@ -25,9 +23,7 @@
 /* local prototypes: */
 int Shp2Kmlx(char* filshp,char* filkml,
-			 int sgn,
-			 bool holes);
+			 int sgn);
 int Shp2Kmlx(char* filshp,char* filkml,
-			 int sgn,double cm,double sp,
-			 bool holes);
+			 int sgn,double cm,double sp);
 
 #endif  /* _SHP2KMLX_H */
Index: /issm/trunk/src/mex/Shp2Kml/Shp2Kml.cpp
===================================================================
--- /issm/trunk/src/mex/Shp2Kml/Shp2Kml.cpp	(revision 10379)
+++ /issm/trunk/src/mex/Shp2Kml/Shp2Kml.cpp	(revision 10380)
@@ -20,6 +20,4 @@
 
 	Options* options=NULL;
-	char     *choles=NULL;
-	bool     holes=false;
 	double   cm=0.,sp=0.;
 
@@ -56,7 +54,4 @@
 	options=new Options(NRHS,nrhs,prhs);
 	if (options->Size()) for(i=0;i<options->Size();i++) ((Option*)options->GetObjectByOffset(i))->DeepEcho();
-	options->Get(&choles,"holes","no");
-	if (!strncmp(choles,"y",1) || !strncmp(choles,"on",2))
-		holes=true;
 	/*  defaults are in Xy2lldef, so don't duplicate them here, and only use user values if both have been specified  */
 	if (options->GetOption("central_meridian") || options->GetOption("standard_parallel")) {
@@ -70,5 +65,5 @@
 	if (verbose) printf("Checking inputs:\n");
 
-	if (sgn != +1 && sgn != -1) _error_("Hemisphere sgn=%d must be +1 (north) or -1 (south).",sgn);
+//	if (sgn != +1 && sgn != -1) _error_("Hemisphere sgn=%d must be +1 (north) or -1 (south).",sgn);
 	if (fabs(cm)      > 180.) _error_("Central meridian cm=%g must be between -180 (west) and +180 (east) degrees.",cm);
 	if (sp < 0. || sp >  90.) _error_("Standard parallel sp=%g must be between 0 and 90 degrees (in specified hemisphere).",sp);
@@ -78,10 +73,8 @@
 	if (options->GetOption("central_meridian") && options->GetOption("standard_parallel"))
 		iret=Shp2Kmlx(filshp,filkml,
-					  sgn,cm,sp,
-					  holes);
+					  sgn,cm,sp);
 	else
 		iret=Shp2Kmlx(filshp,filkml,
-					  sgn,
-					  holes);
+					  sgn);
 	if (verbose) printf("  iret=%d\n",iret);
 
@@ -90,5 +83,4 @@
 
 	/*Clean-up*/
-	xfree((void**)&choles);
 	delete options;
 	xfree((void**)&filkml);
@@ -108,11 +100,10 @@
 	_printf_(true,"      [ret]=Shp2Kml(filshp,filkml,sgn,'param name',param,...);\n");
 	_printf_(true,"\n");
-	_printf_(true,"      filshp      file name of shp file to be read (char)\n");
+	_printf_(true,"      filshp      file name of shp file to be read (char, extension optional)\n");
 	_printf_(true,"      filkml      file name of kml file to be written (char)\n");
-	_printf_(true,"      sgn         sign for hemisphere (double, +1 (north) or -1 (south))\n");
+	_printf_(true,"      sgn         sign for hemisphere (double, +1 (north); -1 (south); 0 (no translation))\n");
 	_printf_(true,"\n");
 	_printf_(true,"      central_meridian     central meridian (double, optional, but must specify with sp)\n");
 	_printf_(true,"      standard_parallel    standard parallel (double, optional, but must specify with cm)\n");
-	_printf_(true,"      holes       flag for treatment of multiple profiles (char, optional, 'yes' for holes))\n");
 	_printf_(true,"\n");
 	_printf_(true,"      ret         return code (non-zero for warning)\n");
@@ -120,6 +111,6 @@
 	_printf_(true,"   Examples:\n");
 	_printf_(true,"      [ret]=Shp2Kml('file.shp','file.kml', 1);\n");
-	_printf_(true,"      [ret]=Shp2Kml('file.shp','file.kml', 1,'central_meridian',45,'standard_parallel',70,'holes','yes');\n");
-	_printf_(true,"      [ret]=Shp2Kml('file.shp','file.kml',-1,'central_meridian', 0,'standard_parallel',71,'holes','yes');\n");
+	_printf_(true,"      [ret]=Shp2Kml('file.shp','file.kml', 1,'central_meridian',45,'standard_parallel',70,'holes');\n");
+	_printf_(true,"      [ret]=Shp2Kml('file.shp','file.kml',-1,'central_meridian', 0,'standard_parallel',71,'holes');\n");
 	_printf_(true,"\n");
 }
