⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mifreader.cs

📁 实现SHP
💻 CS
📖 第 1 页 / 共 2 页
字号:
			}
			else
			{
				int tuplesNum=int.Parse(token);
				gml.LineStringType _ls = new gml.LineStringType(new gml.CoordinatesType(ReadCoordinates(tuplesNum)));
				fgeo.Add(new gml.LineStringPropertyType(_ls));
				_ls=null;
			}
		}
	
		#endregion

		#region read region stuff
		/// <summary>
		/// Reads Region
		/// </summary>
		/// <param name="fgeo">The GeometryField to store the new gml type</param>
		private void ReadFeatureRegion(ref GeometryField fgeo)
		{
			int partsNum=int.Parse(tokenizer.nextToken());
			if(partsNum==1)
			{
				int tuplesnum =int.Parse(fReader.ReadLine());
				gml.PolygonType _pt=new PolygonType(new gml.CoordinatesType(ReadCoordinates(tuplesnum)));
				fgeo.Add(new gml.PolygonPropertyType(_pt));
				_pt=null;
			}
			else if(partsNum==2)
			{
				ReadFeatureRegionDouble(ref fgeo);
			}
			else
			{
				ReadFeatureRegionMulti(ref fgeo,partsNum);
			}
		}
		/// <summary>
		/// Read Region with two part.
		/// </summary>
		/// <param name="fgeo">The GeometryField to store the new gml type</param>
		private void ReadFeatureRegionDouble(ref GeometryField fgeo)
		{
			int tuplesNum1 = int.Parse(fReader.ReadLine());
			gml.BoxType box1 = new BoxType();
			double[] dbl1 = ReadCoordinatesBox(tuplesNum1,ref box1);

			int tuplesNum2 = int.Parse(fReader.ReadLine());
			gml.BoxType box2 = new BoxType();
			double[] dbl2 = ReadCoordinatesBox(tuplesNum2,ref box2);

			if(box1.isContains(box2))
			{
				gml.PolygonType pg = new gml.PolygonType(new gml.CoordinatesType(dbl1),new gml.CoordinatesType(dbl2));
				fgeo.Add(new gml.PolygonPropertyType(pg)); 
				pg=null;
			}
			else if(box1.isContainedIn(box2)) 
			{
				gml.PolygonType pg = new gml.PolygonType(new gml.CoordinatesType(dbl2),new gml.CoordinatesType(dbl1));
				fgeo.Add(new gml.PolygonPropertyType(pg)); 
				pg=null;
			}
			else //not fully overlap
			{
				gml.PolygonType[] pgs = new PolygonType[2];
				pgs[0]=new PolygonType(new gml.CoordinatesType(dbl1));
				pgs[1]=new PolygonType(new gml.CoordinatesType(dbl2));
				gml.MultiPolygonType mpg=new MultiPolygonType(defaultsrs,pgs);
				fgeo.Add(new gml.MultiPolygonPropertyType(mpg)); 
				mpg=null;
				pgs=null;
			}

			box1 = null;
			box2 = null;
			dbl1 = null;
			dbl2 = null;
		}
		/// <summary>
		/// Reads Region with 3 or more parts.
		/// </summary>
		/// <param name="fgeo">The GeometryField to store the new gml type</param>
		/// <param name="partsNum">number or parts</param>
		private void ReadFeatureRegionMulti(ref GeometryField fgeo,int partsNum)
		{
			gml.BoxType[] boxes = new BoxType[partsNum];
			double[][] dbls = new double[partsNum][];

			for(int j=0;j<partsNum;j++)
			{
				int tuplesNum = int.Parse(fReader.ReadLine());
				boxes[j]=new BoxType();
				dbls[j]=ReadCoordinatesBox(tuplesNum,ref boxes[j]);
			}

			mbox[] ms = matchBoxes(boxes);
			int polycount=0;
			for(int i=0;i<ms.Length;i++)
			{
				if(ms[i].container!=-1) continue;
				polycount++;
				for(int j=0;j<ms.Length;j++)
				{
					if(ms[j].container==i) ms[i].innerCount++;
				}
			}
			gml.PolygonType[] pgs = new PolygonType[polycount];

			int polyindex=-1;
			for(int i=0;i<ms.Length;i++)
			{
				if(ms[i].container!=-1) continue;
				gml.CoordinatesType oct = new CoordinatesType(dbls[ms[i].index]);
				polyindex++;
				pgs[polyindex] = new PolygonType(oct); 
				gml.PolygonTypeInnerBoundaryIs[] ibs = new PolygonTypeInnerBoundaryIs[ms[i].innerCount];
				int innerindex=-1;
				for(int j=0;j<ms.Length;j++)
				{
					if(ms[j].container!=i) continue;
					gml.CoordinatesType ict = new CoordinatesType(dbls[ms[j].index]);
					innerindex++;
					ibs[innerindex]=new PolygonTypeInnerBoundaryIs(ict);
					ict=null;
				}
				pgs[polyindex].innerBoundaryIs = ibs;
				ibs=null;
			}

			if(polycount==1)
			{
				fgeo.Add(new gml.PolygonPropertyType(pgs[0]));
			}
			else 
			{
				fgeo.Add(new gml.MultiPolygonPropertyType(new MultiPolygonType(defaultsrs,pgs)));
			}

			ms  = null;
			pgs = null;
			boxes = null;
			dbls = null;
		}

		/// <summary>
		/// Updating bounding box whenever new coordinates read; 
		/// Called if bounding box not supplied.
		/// </summary>
		/// <param name="left">Bounding box left boundary</param>
		/// <param name="top"></param>
		/// <param name="right"></param>
		/// <param name="bottom"></param>
		private void updateBoundingBox(double left,double top, double right, double bottom)
		{
			//check bounding box if not supplied
			fHeader.coordSys.left=Math.Min(fHeader.coordSys.left,left);  
			fHeader.coordSys.top=Math.Max(fHeader.coordSys.top,top);
			fHeader.coordSys.right=Math.Max(fHeader.coordSys.right,right);
			fHeader.coordSys.bottom=Math.Min(fHeader.coordSys.bottom,bottom);
		}
		/// <summary>
		/// Read coordinate tuples
		/// </summary>
		/// <param name="tuplesNum">number of tuples to read</param>
		/// <returns>array of doubles [x0,y0,...,xn,yn]</returns>
		private double[] ReadCoordinates(int tuplesNum)
		{
			double[] da=new double[tuplesNum*2];
			for(int j=0;j<tuplesNum;j++)
			{
				tokenizer.str=fReader.ReadLine();
				tokenizer.reset();
				if(tokenizer.hasMoreTokens()) da[2*j] = double.Parse(tokenizer.nextToken());
				if(tokenizer.hasMoreTokens()) da[2*j+1] = double.Parse(tokenizer.nextToken());
				if(hasBBox==false) updateBoundingBox(da[2*j],da[2*j+1],da[2*j],da[2*j+1]);
			}
			return da;
		}
		/// <summary>
		/// Read coordinate tuples, while updating its bounding box.
		/// </summary>
		/// <param name="tuplesNum">number of tuples to read</param>
		/// <param name="box">the bounding box to update</param>
		/// <returns>array of doubles [x0,y0,...,xn,yn]</returns>
		private double[] ReadCoordinatesBox(int tuplesNum, ref BoxType box)
		{
			box.Left  = double.MaxValue;
			box.Top = -double.MaxValue;
			box.Right = -double.MaxValue;
			box.Bottom = double.MaxValue;

			double[] da=new double[tuplesNum*2];
			for(int j=0;j<tuplesNum;j++)
			{
				tokenizer.str=fReader.ReadLine();
				tokenizer.reset();
				int xi=2*j;
				int yi=2*j+1;
				if(tokenizer.hasMoreTokens()) 
				{
					da[xi]  = double.Parse(tokenizer.nextToken());
					if(da[xi]<box.Left) {box.Left=da[xi];}
					else if(da[xi]>box.Right) {box.Right=da[xi];}
				}
				if(tokenizer.hasMoreTokens()) 
				{
					da[yi]= double.Parse(tokenizer.nextToken());
					if(da[yi]<box.Bottom) {box.Bottom=da[yi];}
					else if(da[yi]>box.Top) {box.Top=da[yi];}
				}
			}
			if(hasBBox==false) updateBoundingBox(box.Left,box.Top,box.Right,box.Bottom);
			return da;
		}

		/// <summary>
		/// calculate relationships between boxes
		/// </summary>
		/// <param name="boxes">array of bounding box to examine</param>
		/// <returns>array of box relationship</returns>
		private mbox[] matchBoxes(gml.BoxType[] boxes)
		{
			mbox[] ms = new mbox[boxes.Length];
			for(int i=0;i<boxes.Length;i++)
			{ 
				ms[i]=new mbox();
				ms[i].index=i; 
				ms[i].container=-1;
				ms[i].innerCount=0;
			}
			for(int i=0;i<boxes.Length-1;i++)
			{
				for(int j=i+1;j<boxes.Length;j++)
				{
					if(boxes[i].isContainedIn(boxes[j]))
					{
						if(ms[i].container==-1)
						{
							ms[i].container=j;
						}
						else
						{
							if(j==ms[i].container) continue;
							if(boxes[j].isContainedIn(boxes[ms[i].container]))	//nested part
							{
								ms[j].container = ms[i].container; //immediate container
								ms[i].container = -1; //set the container's container to nothing --> new polygon;
							}
						}
					}
				}
			}
			return ms;
		}
		/// <summary>
		/// Struct to store relationship between boxes
		/// </summary>
		private struct mbox
		{
			public int index; //index of current box
			public int container; //index of the container of the box, -1 if not contained
			public int innerCount; //number of boxes contained by this box
		}

		#endregion

		#region read feature data
		/// <summary>
		/// Read attribute data values for a map
		/// </summary>
		/// <param name="mapdata">map to add attribute value</param>
		private void ReadFeatureData(ref MapData mapdata)
		{
			if(mReader==null) return;
			string dancuk = mReader.ReadLine();
			dancuk = dancuk.Trim();
			string[] stra = dancuk.Split(fHeader.delimiter.ToCharArray());

			if(dancuk.IndexOf("\"")>-1 && stra.Length!=mapdata.Fields.Count)
			{
				//there's at least one delimiter inside quotation
				Regex r = new Regex("\".*,.*\"");
				MatchCollection ms = r.Matches(dancuk);
				foreach (Match m in ms)
				{
					dancuk=dancuk.Replace(m.Value,m.Value.Replace(fHeader.delimiter," "));
				}
				stra = dancuk.Split(fHeader.delimiter.ToCharArray());
				r=null;
				ms=null;
			}

			//now it's okay to split, yes?
			for(int k=0;k<stra.Length;k++)
			{
				string strval =stra[k].Trim(new char[2]{' ','\0'});
				AddParsedValue(mapdata.Fields[k],strval);
				strval=null;
			}
			stra=null;
			dancuk=null;
		}

		/// <summary>
		/// Parse and add value to a Field
		/// </summary>
		/// <param name="field">Field object to add value</param>
		/// <param name="val">characters represent the value</param>
		private void AddParsedValue(Field field, string val)
		{
			if(field.Type == typeof(string))
			{
				field.Add(val.Trim(' ','"'));
			}
			else if(field.Type == typeof(int))
			{
				field.Add(int.Parse(val));
			}
			else if(field.Type == typeof(double))
			{
				field.Add(double.Parse(val));
			}
			else if(field.Type == typeof(bool))
			{
				if(val.ToUpper()=="T")
				{
					field.Add(true);
				}
				else if(val.ToUpper()=="F")
				{
					field.Add(false);
				}
				else
				{
					field.Add(field.NullSymbol);
				}
			}
			else if(field.Type == typeof(DateTime))
			{
				if(val.Length<8) 
				{
					field.Add(field.NullSymbol);
					return;
				}
				int iyear	= int.Parse(val.Substring(0,4));
				int imonth	= int.Parse(val.Substring(4,2));
				int iday	= int.Parse(val.Substring(6,2));

				if(    iyear<System.DateTime.MinValue.Year || iyear>System.DateTime.MaxValue.Year
					|| imonth<System.DateTime.MinValue.Month || imonth>System.DateTime.MaxValue.Month
					|| iday<System.DateTime.MinValue.Day || iday>System.DateTime.DaysInMonth(iyear,imonth)
					)
				{
					field.Add(field.NullSymbol);
				}
				else
				{
					field.Add(new DateTime(iyear,imonth,iday));
				}			
			}
			else
			{
				throw new FormatException("MifReader : unable to parse value "+val); 
			}
		}
		#endregion

		#region coordinate system, projection, and bbox
		/// <summary>
		/// Reads Coordinates System 
		/// </summary>
		/// <param name="stoken">string tokenizer contains the coordsys line.</param>
		private void ReadCoordSys(util.StringTokenizer stoken)
		{ 
			if(stoken.hasMoreTokens()) fHeader.coordSys.Name = stoken.nextToken(); //projection Name
			//beware : different syntax in different version!
			while(stoken.hasMoreTokens()) 
			{
				string token=stoken.nextToken(); 
				switch (token.ToLower())
				{
					case "units": //for version 300
						fHeader.coordSys.ProjUnits = stoken.nextToken();
						break;
					case "projection":	//for version 450
						ReadProjection(stoken);
						break;
					case "bounds":
						ReadBoundingBox(stoken);
						break;
					default:
						//find other mif keywords
						break;
				}
			}
		}
		/// <summary>
		/// Read projection in a coodsys
		/// </summary>
		/// <param name="stoken">string tokenizer containing projection data</param>
		private void ReadProjection(util.StringTokenizer stoken)
		{
			//FORMAT (usually 8 tokens) : projNumber(int),DATUM(int),unitsname(string),ORG_LNG(int),ORG_LAT(int),SCL_RED(double),X_OFF(double),Y_OFF(double)
			//ex. : Projection 8, 104, "m", 111, 0, 0.9996, 500000, 10000000
			//TODO : check different format for different projection (see : MapInfoProj.db in mapinfo distribution)
			//ex. other format :  Projection 1, 0

			string token=null;
			if(stoken.hasMoreTokens()) 
			{
				token=stoken.nextToken();
				string[] stra=token.Split(fHeader.delimiter.ToCharArray());
				if(stra.Length>0) fHeader.coordSys.ProjNumber =int.Parse(stra[0]);
				if(stra.Length>1) fHeader.coordSys.ProjDatum = int.Parse(stra[1]);
				if(stra.Length>2) fHeader.coordSys.ProjUnits=stra[2];
				if(stra.Length>3) fHeader.coordSys.ProjOrgLng=double.Parse(stra[3]);
				if(stra.Length>4) fHeader.coordSys.ProjOrgLat=double.Parse(stra[4]);
				if(stra.Length>5) fHeader.coordSys.ProjSclRed=double.Parse(stra[5]);
				if(stra.Length>6) fHeader.coordSys.ProjOffsetX=double.Parse(stra[6]);
				if(stra.Length>7) fHeader.coordSys.ProjOffsetY=double.Parse(stra[7]);
			}
		}

		/// <summary>
		/// Reads bounding box of a coordsys
		/// </summary>
		/// <param name="stoken">string tokenizer containing bounding box data</param>
		private void ReadBoundingBox(util.StringTokenizer stoken)
		{
			if(stoken.hasMoreTokens()) 
			{
				string token = stoken.nextToken();
				string[] stra = token.Trim(new char[2]{'(',')'}).Split(fHeader.delimiter.ToCharArray());
				fHeader.coordSys.left = double.Parse(stra[0]); 
				fHeader.coordSys.bottom = double.Parse(stra[1]);
			}
			if(stoken.hasMoreTokens()) 
			{
				string token = stoken.nextToken();
				string[] stra = token.Trim(new char[2]{'(',')'}).Split(fHeader.delimiter.ToCharArray());
				fHeader.coordSys.right = double.Parse(stra[0]);
				fHeader.coordSys.top = double.Parse(stra[1]); 
			}
			hasBBox=true; //if not , then we must find bbox manually..
		}
		#endregion

		#region style stuffs
		private void ReadFeatureStyle(string line)
		{
			//do nothing : why concerned with style?
		}
		private bool isShadingClause(string line) 
		{
			line = line.ToUpper();
			bool ret = (line.IndexOf(CLAUSE_PEN)!=-1 ||
				line.IndexOf(CLAUSE_SYMBOL)!=-1 ||
				line.IndexOf(CLAUSE_SMOOTH)!=-1 ||
				line.IndexOf(CLAUSE_CENTER)!=-1 ||
				line.IndexOf(CLAUSE_BRUSH)!=-1 );
			return ret;
		}

		private string Clause(string line)
		{
			return Clause(line,' ');
		}
		private string Clause(string line,char delim)
		{
			int index = line.IndexOf(delim);
			if (index == -1) return line;
			return line.Substring(0,index).Trim();
		}
		#endregion

		private void UpdateStatus(string message, int progressvalue)
		{
			if(progressvalue>0 && progressvalue-StatusArgs.statusValue<5) return;
			StatusArgs.setCurrentStatus(message, progressvalue);
			StatusChange(this,StatusArgs);
		}
	}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -