📄 mifreader.cs
字号:
}
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 + -