X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FHYDROData%2FHYDROData_ShapeFile.cxx;h=2a38a86d1401211f791bddbcf949b289fb6d1c47;hb=8d4dba4a45855249f5eb022e9cc7dcff202bce3c;hp=87d9bc2e81665f4607535bd9a7cabc05fe877ea8;hpb=aaf4ecf52eae47da4da3cfa523672526787018f8;p=modules%2Fhydro.git diff --git a/src/HYDROData/HYDROData_ShapeFile.cxx b/src/HYDROData/HYDROData_ShapeFile.cxx index 87d9bc2e..2a38a86d 100644 --- a/src/HYDROData/HYDROData_ShapeFile.cxx +++ b/src/HYDROData/HYDROData_ShapeFile.cxx @@ -1,8 +1,4 @@ -// Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// +// Copyright (C) 2014-2015 EDF-R&D // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either @@ -24,9 +20,9 @@ #include #include #include -#include #include #include +#include #include #include @@ -37,10 +33,11 @@ #include #include #include +#include #include -#include -#include -#include +#include +#include +#include #include #include #include @@ -51,6 +48,26 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 + #pragma warning( disable: 4996 ) +#endif + +//SHP->TFaces (Import) +#define OSD_TIMER HYDROData_ShapeFile::HYDROData_ShapeFile() : myHSHP(NULL) { @@ -61,47 +78,74 @@ HYDROData_ShapeFile::~HYDROData_ShapeFile() Free(); } -void HYDROData_ShapeFile::Export(const QString& aFileName, - NCollection_Sequence aPolyXYSeq, - NCollection_Sequence aPoly3DSeq, - NCollection_Sequence aLCSeq, - QStringList& aNonExpList) +void HYDROData_ShapeFile::Export(Handle(HYDROData_Document) theDocument, + const QString& aFileName, + NCollection_Sequence aPolyXYSeq, + NCollection_Sequence aPoly3DSeq, + QStringList& aNonExpList) { SHPHandle hSHPHandle; if (!aPolyXYSeq.IsEmpty() && aPoly3DSeq.IsEmpty()) { - hSHPHandle = SHPCreate( aFileName.toAscii().data(), SHPT_ARC ); + hSHPHandle = SHPCreate( aFileName.toLatin1().data(), SHPT_ARC ); for (int i = 1; i <= aPolyXYSeq.Size(); i++) - if (WriteObjectPolyXY(hSHPHandle, aPolyXYSeq(i)) != 1) + if (WriteObjectPolyXY(theDocument, hSHPHandle, aPolyXYSeq(i)) != 1) aNonExpList.append(aPolyXYSeq(i)->GetName()); - } else if (aPolyXYSeq.IsEmpty() && !aPoly3DSeq.IsEmpty()) { - hSHPHandle = SHPCreate( aFileName.toAscii().data(), SHPT_ARCZ ); + hSHPHandle = SHPCreate( aFileName.toLatin1().data(), SHPT_ARCZ ); for (int i = 1; i <= aPoly3DSeq.Size(); i++) - if (WriteObjectPoly3D(hSHPHandle, aPoly3DSeq(i)) != 1) + if (WriteObjectPoly3D(theDocument, hSHPHandle, aPoly3DSeq(i)) != 1) aNonExpList.append(aPoly3DSeq(i)->GetName()); } - else if (aPolyXYSeq.IsEmpty() && aPoly3DSeq.IsEmpty() && !aLCSeq.IsEmpty()) + if (hSHPHandle->nRecords > 0) + SHPClose( hSHPHandle ); + else { - hSHPHandle = SHPCreate( aFileName.toAscii().data(), SHPT_POLYGON ); - for (int i = 1; i <= aLCSeq.Size(); i++) - if (WriteObjectLC(hSHPHandle, aLCSeq(i)) != 1) - aNonExpList.append(aLCSeq(i)->GetName()); + SHPClose( hSHPHandle ); + QString aFN = aFileName.simplified(); + remove (aFN.toStdString().c_str()); + remove ((aFN.simplified().replace( aFN.simplified().size() - 4, 4, ".shx")).toStdString().c_str()); } - if (hSHPHandle->nRecords > 0) +} + +void HYDROData_ShapeFile::Export(Handle(HYDROData_Document) theDocument, + const QString& aFileName, + const Handle(HYDROData_LandCoverMap)& aLCM, + QStringList& aNonExpList, + bool bCheckLinear, bool bUseDiscr, double theDefl) +{ + if (bCheckLinear && !aLCM->CheckLinear()) + return; + // + SHPHandle hSHPHandle = NULL; + if ( !aLCM.IsNull() && !aLCM->IsEmpty()) + { + hSHPHandle = SHPCreate( aFileName.toLatin1().data(), SHPT_POLYGON ); + HYDROData_LandCoverMap::Explorer It( aLCM ); + for( ; It.More(); It.Next()) + { + TopoDS_Face aFace = It.Face(); + if (WriteObjectPolygon(theDocument, hSHPHandle, aFace, bUseDiscr, theDefl) != 1) + aNonExpList.append(aLCM->GetName() + "_" + QString::number(It.Index())); + } + } + if (hSHPHandle && hSHPHandle->nRecords > 0) SHPClose( hSHPHandle ); else { SHPClose( hSHPHandle ); QString aFN = aFileName.simplified(); remove (aFN.toStdString().c_str()); - remove (aFN.replace( ".shp", ".shx", Qt::CaseInsensitive).toStdString().c_str()); + remove ((aFN.simplified().replace( aFN.simplified().size() - 4, 4, ".shx")).toStdString().c_str()); } } -int HYDROData_ShapeFile::WriteObjectPolyXY(SHPHandle theShpHandle, Handle_HYDROData_PolylineXY thePoly ) + +int HYDROData_ShapeFile::WriteObjectPolyXY(Handle(HYDROData_Document) theDocument, + SHPHandle theShpHandle, + Handle(HYDROData_PolylineXY) thePoly ) { SHPObject *aSHPObj; std::vector x, y; @@ -117,13 +161,17 @@ int HYDROData_ShapeFile::WriteObjectPolyXY(SHPHandle theShpHandle, Handle_HYDROD HYDROData_PolylineXY::PointsList aPointList = thePoly->GetPoints(i); for (int j = 1; j <= aPointList.Size(); j++) { - x.push_back( aPointList(j).X()); - y.push_back( aPointList(j).Y()); + gp_XY P = aPointList(j); + theDocument->Transform(P, false); + x.push_back( P.X()); + y.push_back( P.Y()); } if (thePoly->IsClosedSection(i)) { - x.push_back( aPointList(1).X()); - y.push_back( aPointList(1).Y()); + gp_XY P = aPointList(1); + theDocument->Transform(P, false); + x.push_back( P.X()); + y.push_back( P.Y()); } } @@ -133,7 +181,9 @@ int HYDROData_ShapeFile::WriteObjectPolyXY(SHPHandle theShpHandle, Handle_HYDROD return 1; } -int HYDROData_ShapeFile::WriteObjectPoly3D(SHPHandle theShpHandle, Handle_HYDROData_Polyline3D thePoly ) +int HYDROData_ShapeFile::WriteObjectPoly3D(Handle(HYDROData_Document) theDocument, + SHPHandle theShpHandle, + Handle(HYDROData_Polyline3D) thePoly ) { SHPObject *aSHPObj; std::vector x, y, z; @@ -149,14 +199,18 @@ int HYDROData_ShapeFile::WriteObjectPoly3D(SHPHandle theShpHandle, Handle_HYDROD HYDROData_PolylineXY::PointsList aPointList = thePoly->GetPolylineXY()->GetPoints(i); for (int j = 1; j <= aPointList.Size(); j++) { - x.push_back( aPointList(j).X()); - y.push_back( aPointList(j).Y()); + gp_XY P = aPointList(j); + theDocument->Transform(P, false); + x.push_back( P.X()); + y.push_back( P.Y()); z.push_back(thePoly->GetAltitudeObject()->GetAltitudeForPoint(gp_XY (aPointList(j).X(), aPointList(j).Y()))); } if ( thePoly->GetPolylineXY()->IsClosedSection(i)) { - x.push_back( aPointList(1).X()); - y.push_back( aPointList(1).Y()); + gp_XY P = aPointList(1); + theDocument->Transform(P, false); + x.push_back( P.X()); + y.push_back( P.Y()); z.push_back(thePoly->GetAltitudeObject()->GetAltitudeForPoint(gp_XY (aPointList(1).X(), aPointList(1).Y()))); } @@ -168,45 +222,27 @@ int HYDROData_ShapeFile::WriteObjectPoly3D(SHPHandle theShpHandle, Handle_HYDROD return 1; } -int HYDROData_ShapeFile::WriteObjectLC(SHPHandle theShpHandle, Handle_HYDROData_LandCover theLC ) +int HYDROData_ShapeFile::WriteObjectPolygon(Handle(HYDROData_Document) theDocument, + SHPHandle theShpHandle, + const TopoDS_Shape& theInputShape, + bool bUseDiscr, double theDefl) { - TopoDS_Shape aSh = theLC->GetShape(); - if (aSh.IsNull()) + if (theInputShape.IsNull()) return 0; - TopExp_Explorer anEdgeEx(aSh, TopAbs_EDGE); - for (; anEdgeEx.More(); anEdgeEx.Next()) - { - TopoDS_Edge E = TopoDS::Edge(anEdgeEx.Current()); - double aFP, aLP; - Handle_Geom_Curve aCur = BRep_Tool::Curve(E, aFP, aLP); - Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast(aCur); - if (aLine.IsNull()) - { - Handle(Geom_TrimmedCurve) aTC = Handle(Geom_TrimmedCurve)::DownCast(aCur); - if (!aTC.IsNull()) - { - Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast(aTC->BasisCurve()); - if (aLine.IsNull()) - return -1; - } - else - return -1; - } - } - if (aSh.ShapeType() == TopAbs_FACE) + if (theInputShape.ShapeType() == TopAbs_FACE) { - ProcessFace(TopoDS::Face(aSh), theShpHandle); + ProcessFace(theDocument, TopoDS::Face(theInputShape), theShpHandle, bUseDiscr, theDefl); } - else if (aSh.ShapeType() == TopAbs_COMPOUND) + else if (theInputShape.ShapeType() == TopAbs_COMPOUND) { - TopExp_Explorer Ex(aSh, TopAbs_FACE); + TopExp_Explorer Ex(theInputShape, TopAbs_FACE); for (; Ex.More(); Ex.Next()) { TopoDS_Face aF = TopoDS::Face(Ex.Current()); if (aF.IsNull()) continue; - ProcessFace(aF, theShpHandle); + ProcessFace(theDocument, aF, theShpHandle, bUseDiscr, theDefl); } } else @@ -216,56 +252,125 @@ int HYDROData_ShapeFile::WriteObjectLC(SHPHandle theShpHandle, Handle_HYDROData_ } -void HYDROData_ShapeFile::ProcessFace(TopoDS_Face theFace, SHPHandle theShpHandle) +void HYDROData_ShapeFile::ProcessFace(Handle(HYDROData_Document) theDocument, + const TopoDS_Face& theFace, + SHPHandle theShpHandle, + bool bUseDiscr, double theDefl ) { + if (theFace.ShapeType() != TopAbs_FACE) + return; SHPObject *aSHPObj; std::vector x, y; std::vector anPartStart; - if (theFace.ShapeType() == TopAbs_FACE) + TopoDS_Wire OuterW = BRepTools::OuterWire(theFace); + NCollection_Sequence aWires; + + //write an outer wire first + aWires.Append(OuterW); + TopExp_Explorer Ex(theFace, TopAbs_WIRE); + for (; Ex.More(); Ex.Next()) { - TopExp_Explorer Ex(theFace, TopAbs_WIRE); - int NbWires = 0; - for (; Ex.More(); Ex.Next()) + TopoDS_Wire aW = TopoDS::Wire(Ex.Current()); + if (aW.IsEqual(OuterW)) + continue; + aWires.Append(aW); + } + + int NbWires = 0; + for (int k = 1; k <= aWires.Length(); k++) + { + TopoDS_Wire aW = aWires(k); + if (aW.IsNull()) + continue; + NbWires++; + if (aW.Orientation() == TopAbs_INTERNAL) + //cant write internal wires/edges + continue; + // Try to reorder edges + Handle(ShapeFix_Wire) aSFW = new ShapeFix_Wire( aW, theFace, Precision::Confusion() ); + aSFW->ModifyTopologyMode() = Standard_False; + aSFW->ModifyGeometryMode() = Standard_False; + aSFW->FixReorder(); + Handle(ShapeExtend_WireData) aSEWD = aSFW->WireData(); + Standard_Integer nbE = aSEWD->NbEdges(); + if (nbE == 0) + continue; + // + anPartStart.push_back(x.size()); + NCollection_Sequence aPnts; + for (Standard_Integer i = 1; i <= nbE; i++) { - TopoDS_Wire aW = TopoDS::Wire(Ex.Current()); - if (aW.IsNull()) - continue; - NbWires++; - anPartStart.push_back(x.size()); - TopExp_Explorer aVEx(aW, TopAbs_VERTEX); - NCollection_Sequence aPnts; - for (; aVEx.More(); aVEx.Next()) + TopoDS_Edge E = aSEWD->Edge(i); + if (!bUseDiscr) { - TopoDS_Vertex aV = TopoDS::Vertex(aVEx.Current()); + TopoDS_Vertex aV = TopExp::LastVertex(E, 1); if (aV.IsNull()) continue; gp_Pnt P = BRep_Tool::Pnt(aV); aPnts.Append(gp_Pnt2d(P.X(), P.Y())); } - NCollection_Sequence aNPnts; - aNPnts.Append(aPnts.First()); - for (int j = 1; j <= aPnts.Size() - 1; j++) + else { - if (!aPnts(j).IsEqual(aPnts(j + 1), Precision::Confusion())) - aNPnts.Append(aPnts(j + 1)); - } - - for (int j = 1; j <= aNPnts.Size(); j++) - { - x.push_back( aNPnts(j).X()); - y.push_back( aNPnts(j).Y()); + BRepAdaptor_Curve Cur( E ); + GCPnts_QuasiUniformDeflection Discr( Cur, theDefl ); + if( !Discr.IsDone() ) + continue; //skip edge? + double NewDefl = theDefl/2.0; + while (Discr.NbPoints() < 2) + { + Discr.Initialize(Cur, NewDefl); + NewDefl = NewDefl/2.0; + } + // + if (E.Orientation() == TopAbs_FORWARD) + { + for( int i = 1; i <= Discr.NbPoints(); i++ ) + { + gp_Pnt P = Discr.Value( i ); + aPnts.Append(gp_Pnt2d(P.X(), P.Y())); + } + } + else + { + for( int i = Discr.NbPoints(); i > 0; i-- ) + { + gp_Pnt P = Discr.Value( i ); + aPnts.Append(gp_Pnt2d(P.X(), P.Y())); + } + } } - //x.push_back( aNPnts(1).X()); - //y.push_back( aNPnts(1).Y()); + } + NCollection_Sequence aNPnts; + aNPnts.Append(aPnts.First()); + for (int j = 1; j <= aPnts.Size() - 1; j++) + { + if (!aPnts(j).IsEqual(aPnts(j + 1), Precision::Confusion())) + aNPnts.Append(aPnts(j + 1)); + } + //assume that the orientation of external wire & internal wires is correct + //so just write all points "as-is" + //External wire will be written in clockwise direction + //any other wires (holes) - in anticlockwise direction + for (int j = aNPnts.Size(); j >= 1; j--) + { + gp_XY P = gp_XY(aNPnts(j).X(), aNPnts(j).Y()); + theDocument->Transform(P, false); + x.push_back( P.X()); + y.push_back( P.Y()); } - - aSHPObj = SHPCreateObject( SHPT_POLYGON, -1, NbWires, &anPartStart[0], NULL, x.size(), &x[0], &y[0], NULL, NULL ); - SHPWriteObject( theShpHandle, -1, aSHPObj ); - SHPDestroyObject( aSHPObj ); + //first point is same as the last one => closed polygon + gp_XY P = gp_XY(aNPnts.Last().X(), aNPnts.Last().Y()); + theDocument->Transform(P, false); + x.push_back( P.X()); + y.push_back( P.Y()); + } - else - return; + + aSHPObj = SHPCreateObject( SHPT_POLYGON, -1, NbWires, &anPartStart[0], NULL, x.size(), &x[0], &y[0], NULL, NULL ); + SHPWriteObject( theShpHandle, -1, aSHPObj ); + SHPDestroyObject( aSHPObj ); + } bool HYDROData_ShapeFile::Parse(SHPHandle theHandle, ShapeType theType, int& theShapeTypeOfFile) @@ -274,7 +379,8 @@ bool HYDROData_ShapeFile::Parse(SHPHandle theHandle, ShapeType theType, int& the mySHPObjects.clear(); SHPGetInfo( theHandle, NULL, &aShapeType, NULL, NULL ); theShapeTypeOfFile = aShapeType; - bool ToRead = (theType == ShapeType_Polyline && (aShapeType == 3 || aShapeType == 13 || aShapeType == 23)) || + bool ToRead = (theType == ShapeType_Polyline && + (aShapeType == 3 || aShapeType == 13 || aShapeType == 23 || aShapeType == 5)) || (theType == ShapeType_Polygon && aShapeType == 5); if (ToRead) { @@ -286,15 +392,19 @@ bool HYDROData_ShapeFile::Parse(SHPHandle theHandle, ShapeType theType, int& the return false; } -void HYDROData_ShapeFile::ReadSHPPolygon(SHPObject* anObj, int i, TopoDS_Face& F) +void HYDROData_ShapeFile::ReadSHPPolygon(Handle(HYDROData_Document) theDocument, SHPObject* anObj, int i, TopoDS_Face& F) { - TopoDS_Wire W; + if (!anObj) + return; TopoDS_Edge E; int nParts = anObj->nParts; - gp_Pln pln(gp_Pnt(0,0,0), gp_Dir(0,0,1)); + Handle(Geom_Plane) aPlaneSur = new Geom_Plane(gp_Pnt(0,0,0), gp_Dir(0,0,1)); + + BRep_Builder BB; + BB.MakeFace(F); + + NCollection_Sequence allWires; - //Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape; - //sfs->FixFaceTool()->FixOrientationMode() = 1; TopTools_SequenceOfShape aWires; for ( int i = 0 ; i < nParts ; i++ ) { @@ -306,51 +416,111 @@ void HYDROData_ShapeFile::ReadSHPPolygon(SHPObject* anObj, int i, TopoDS_Face& F else EndIndex = anObj->nVertices; - for ( int k = StartIndex; k < EndIndex - 1 ; k++ ) + TopoDS_Wire W; + BB.MakeWire(W); + + //First point is same as the last point + int NbPnts = EndIndex - StartIndex - 1; + NCollection_Array1 VPoints(0, NbPnts); + int j = NbPnts; + for ( int k = StartIndex; k < EndIndex; k++ ) + { + gp_Pnt P (anObj->padfX[k], anObj->padfY[k], 0); + theDocument->Transform(P, true); + VPoints.ChangeValue(j) = BRepLib_MakeVertex(P).Vertex(); + j--; + } + + for ( int k = 0; k < VPoints.Size() - 1; k++ ) { - gp_Pnt P1 (anObj->padfX[k], anObj->padfY[k], 0); - gp_Pnt P2 (anObj->padfX[k+1], anObj->padfY[k+1], 0); + gp_Pnt P1 = BRep_Tool::Pnt(VPoints(k)); + gp_Pnt P2 = BRep_Tool::Pnt(VPoints(k + 1)); if (P1.Distance(P2) < Precision::Confusion()) continue; - BRepBuilderAPI_MakeEdge aMakeEdge(P1, P2); - aBuilder.Add(TopoDS::Edge(aMakeEdge.Shape())); + Handle(Geom_TrimmedCurve) aTC = GC_MakeSegment(P1, P2).Value(); + TopoDS_Edge E; + if ( k != VPoints.Size() - 2) + E = BRepLib_MakeEdge(aTC, VPoints(k), VPoints(k + 1)).Edge(); + else + //the last edge => use first and last vertices + E = BRepLib_MakeEdge(aTC, VPoints.First(), VPoints.Value(VPoints.Upper() - 1)).Edge(); + //Add edge to wire + //If SHP file is correct then the outer wire and the holes will have the correct orientations + W.Closed (Standard_True); + W.Orientation(TopAbs_FORWARD); + BB.Add(W, E); } - - aBuilder.Build(); - W = TopoDS::Wire(aBuilder.Shape()); - W.Orientation(TopAbs_FORWARD); - BRepBuilderAPI_MakeFace aDB(pln, W); - TopoDS_Face aDummyFace = TopoDS::Face(aDB.Shape()); - BRepTopAdaptor_FClass2d FClass(aDummyFace, Precision::PConfusion()); - if ( i == 0 && FClass.PerformInfinitePoint() == TopAbs_OUT) - W.Reverse(); - if ( i > 0 && FClass.PerformInfinitePoint() != TopAbs_IN) - W.Reverse(); - - aWires.Append(W); + allWires.Append(W); } - - BRepBuilderAPI_MakeFace aFBuilder(pln, TopoDS::Wire(aWires(1))); - for (int i = 2; i <= aWires.Length(); i++) - aFBuilder.Add(TopoDS::Wire(aWires(i))); - TopoDS_Face DF = TopoDS::Face(aFBuilder.Shape()); - BRepLib::BuildCurves3d(DF); - if(!DF.IsNull()) + int OutWIndex = -1; + if (allWires.Size() > 1) + { + NCollection_Sequence BBs; + //try to find the largest bbox + for (int i = 1; i <= allWires.Size(); i++) + { + TopoDS_Wire W = allWires(i); + Bnd_Box BB; + BRepBndLib::AddClose(W, BB); + BBs.Append(BB); + } + for (int i = 1; i <= BBs.Size(); i++) + { + bool IsIn = false; + for (int j = 1; j <= BBs.Size(); j++) + { + if (i == j) + continue; + Standard_Real iXmax, iXmin, iYmax, iYmin, z0, z1; + Standard_Real jXmax, jXmin, jYmax, jYmin; + BBs(i).Get(iXmin, iYmin, z0, iXmax, iYmax, z1); + BBs(j).Get(jXmin, jYmin, z0, jXmax, jYmax, z1); + if (!(iXmin > jXmin && + iYmin > jYmin && + iXmax < jXmax && + iYmax < jYmax)) + IsIn = true; + } + if (IsIn) + { + OutWIndex = i; + break; + } + } + } + else + OutWIndex = 1; //one wire => no need to check + + for (int i = 1; i <= allWires.Size(); i++) { - //sfs->Init ( DF ); - //sfs->Perform(); - F = DF; //TopoDS::Face(sfs->Shape()); + TopoDS_Face DF; + BB.MakeFace(DF); + TopoDS_Wire W = allWires(i); + BB.Add(DF, W); + BB.UpdateFace(DF, aPlaneSur, TopLoc_Location(), Precision::Confusion()); + // + BRepTopAdaptor_FClass2d FClass(DF, Precision::PConfusion()); + if ( i == OutWIndex && FClass.PerformInfinitePoint() == TopAbs_IN) + W.Reverse(); + if ( i != OutWIndex && FClass.PerformInfinitePoint() == TopAbs_OUT) + W.Reverse(); + // + BB.Add(F, W); } + + //Add surface to the face + BB.UpdateFace(F, aPlaneSur, TopLoc_Location(), Precision::Confusion()); + F.Closed(Standard_True); } -int HYDROData_ShapeFile::ImportLandCovers(const QString theFileName, QStringList& thePolygonsList, TopTools_SequenceOfShape& theFaces, int& theShapeTypeOfFile) +int HYDROData_ShapeFile::ImportPolygons(Handle(HYDROData_Document) theDocument, const QString theFileName, QStringList& thePolygonsList, TopTools_SequenceOfShape& theFaces, int& theShapeTypeOfFile) { Free(); int Stat = TryOpenShapeFile(theFileName); if (Stat != 0) return Stat; - myHSHP = SHPOpen( theFileName.toAscii().data(), "rb" ); + myHSHP = SHPOpen( theFileName.toLatin1().data(), "rb" ); if (!Parse(myHSHP, HYDROData_ShapeFile::ShapeType_Polygon, theShapeTypeOfFile)) return 0; for (size_t i = 0; i < mySHPObjects.size(); i++) @@ -359,11 +529,19 @@ int HYDROData_ShapeFile::ImportLandCovers(const QString theFileName, QStringList TopoDS_Face aF; if (myHSHP->nShapeType == 5) { +#ifdef OSD_TIMER + OSD_Timer timer; + timer.Start(); +#endif for (size_t i = 0; i < mySHPObjects.size(); i++) { - ReadSHPPolygon(mySHPObjects[i], i, aF); + ReadSHPPolygon(theDocument, mySHPObjects[i], i, aF); theFaces.Append(aF); } +#ifdef OSD_TIMER + timer.Stop(); + timer.Show(); +#endif return 1; } else @@ -385,7 +563,7 @@ void HYDROData_ShapeFile::Free() void HYDROData_ShapeFile::ReadSHPPolyXY(Handle(HYDROData_Document) theDocument, SHPObject* anObj, QString theFileName, - int theInd, NCollection_Sequence& theEntities) + int theInd, NCollection_Sequence& theEntities, bool bReadAsPolyline) { Handle(HYDROData_PolylineXY) aPolylineXY = Handle(HYDROData_PolylineXY)::DownCast( theDocument->CreateObject( KIND_POLYLINEXY ) ); @@ -400,24 +578,32 @@ void HYDROData_ShapeFile::ReadSHPPolyXY(Handle(HYDROData_Document) theDocument, else EndIndex = anObj->nVertices; - bool IsClosed = false; HYDROData_PolylineXY::SectionType aSectType = HYDROData_PolylineXY::SECTION_POLYLINE; - if (anObj->padfX[StartIndex] == anObj->padfX[EndIndex - 1] && - anObj->padfY[StartIndex] == anObj->padfY[EndIndex - 1] ) + if (!bReadAsPolyline) { - IsClosed = true; - aPolylineXY->AddSection( TCollection_AsciiString( ("poly_section_" + QString::number(i)).data()->toAscii()), aSectType, true); + bool IsClosed = false; + if (anObj->padfX[StartIndex] == anObj->padfX[EndIndex - 1] && + anObj->padfY[StartIndex] == anObj->padfY[EndIndex - 1] ) + { + IsClosed = true; + aPolylineXY->AddSection( TCollection_AsciiString( ("poly_section_" + QString::number(i)).data()->toLatin1()), aSectType, true); + } + else + aPolylineXY->AddSection( TCollection_AsciiString( ("poly_section_" + QString::number(i)).data()->toLatin1()), aSectType, false); + + if (IsClosed) + EndIndex--; } else - aPolylineXY->AddSection( TCollection_AsciiString( ("poly_section_" + QString::number(i)).data()->toAscii()), aSectType, false); - - if (IsClosed) + { + //polygon; contours always closed + aPolylineXY->AddSection( TCollection_AsciiString( ("poly_section_" + QString::number(i)).data()->toLatin1()), aSectType, true); EndIndex--; + } for ( int k = StartIndex; k < EndIndex ; k++ ) { - HYDROData_PolylineXY::Point aSectPoint; - aSectPoint.SetX( anObj->padfX[k] ); - aSectPoint.SetY( anObj->padfY[k] ); + HYDROData_PolylineXY::Point aSectPoint = gp_XY(anObj->padfX[k], anObj->padfY[k]); + theDocument->Transform(aSectPoint, true); aPolylineXY->AddPoint( i, aSectPoint ); } @@ -432,7 +618,7 @@ void HYDROData_ShapeFile::ReadSHPPolyXY(Handle(HYDROData_Document) theDocument, } void HYDROData_ShapeFile::ReadSHPPoly3D(Handle(HYDROData_Document) theDocument, SHPObject* anObj, QString theFileName, - int theInd, NCollection_Sequence& theEntities) + int theInd, NCollection_Sequence& theEntities) { Handle(HYDROData_PolylineXY) aPolylineXY = Handle(HYDROData_PolylineXY)::DownCast( theDocument->CreateObject( KIND_POLYLINEXY ) ); @@ -459,20 +645,23 @@ void HYDROData_ShapeFile::ReadSHPPoly3D(Handle(HYDROData_Document) theDocument, anObj->padfZ[StartIndex] == anObj->padfZ[EndIndex - 1]) { IsClosed = true; - aPolylineXY->AddSection( TCollection_AsciiString( ("poly_section_" + QString::number(i)).data()->toAscii()), aSectType, true ); + aPolylineXY->AddSection( TCollection_AsciiString( ("poly_section_" + QString::number(i)).data()->toLatin1()), aSectType, true ); } else - aPolylineXY->AddSection( TCollection_AsciiString( ("poly_section_" + QString::number(i)).data()->toAscii()), aSectType, false ); + aPolylineXY->AddSection( TCollection_AsciiString( ("poly_section_" + QString::number(i)).data()->toLatin1()), aSectType, false ); if (IsClosed) EndIndex--; for ( int k = StartIndex ; k < EndIndex ; k++ ) { - HYDROData_PolylineXY::Point aSectPoint; - aSectPoint.SetX( anObj->padfX[k] ); - aSectPoint.SetY( anObj->padfY[k] ); + HYDROData_PolylineXY::Point aSectPoint = gp_XY(anObj->padfX[k], anObj->padfY[k]); + theDocument->Transform(aSectPoint, true); aPolylineXY->AddPoint( i, aSectPoint ); - aAPoints.Append(gp_XYZ (anObj->padfX[k], anObj->padfY[k], anObj->padfZ[k])); + HYDROData_Bathymetry::AltitudePoint p; + p.X = aSectPoint.X(); + p.Y = aSectPoint.Y(); + p.Z = anObj->padfZ[k]; + aAPoints.push_back(p); } } @@ -491,7 +680,7 @@ void HYDROData_ShapeFile::ReadSHPPoly3D(Handle(HYDROData_Document) theDocument, aPolylineObj->SetPolylineXY (aPolylineXY, false); aPolylineObj->SetAltitudeObject(aBath); - aPolylineObj->SetBorderColor( HYDROData_Polyline3D::DefaultBorderColor() ); + aPolylineObj->SetBorderColor( aPolylineObj->DefaultBorderColor() ); aPolylineObj->SetName( aPoly3DName ); aPolylineObj->Update(); @@ -500,10 +689,24 @@ void HYDROData_ShapeFile::ReadSHPPoly3D(Handle(HYDROData_Document) theDocument, } - +void HYDROData_ShapeFile::GetFreeIndices(std::vector& theAllowedIndexes, QString strName, size_t theObjsSize, + QStringList theExistingNames, QString theBaseFileName) +{ + int anInd = 0; + for (;theAllowedIndexes.size() < theObjsSize;) + { + if (!theExistingNames.contains(theBaseFileName + strName + QString::number(anInd))) + { + theAllowedIndexes.push_back(anInd); + anInd++; + } + else + anInd++; + } +} int HYDROData_ShapeFile::ImportPolylines(Handle(HYDROData_Document) theDocument, const QString& theFileName, - NCollection_Sequence& theEntities, int& theShapeTypeOfFile) + NCollection_Sequence& theEntities, int& theShapeTypeOfFile) { //Free(); int aStat = TryOpenShapeFile(theFileName); @@ -518,7 +721,7 @@ int HYDROData_ShapeFile::ImportPolylines(Handle(HYDROData_Document) theDocument, anExistingNames.push_back(anIter.Current()->GetName()); SHPHandle aHSHP; - aHSHP = SHPOpen( theFileName.toAscii().data(), "rb" ); + aHSHP = SHPOpen( theFileName.toLatin1().data(), "rb" ); QFileInfo aFileInfo(theFileName); QString aBaseFileName = aFileInfo.baseName(); @@ -527,21 +730,12 @@ int HYDROData_ShapeFile::ImportPolylines(Handle(HYDROData_Document) theDocument, return 0; if (aHSHP->nShapeType == 3 || aHSHP->nShapeType == 23) { - anInd = 0; - for (;anAllowedIndexes.size() < mySHPObjects.size();) - { - if (!anExistingNames.contains(aBaseFileName + "_PolyXY_" + QString::number(anInd))) - { - anAllowedIndexes.push_back(anInd); - anInd++; - } - else - anInd++; - } - + size_t anObjsSize = mySHPObjects.size(); + GetFreeIndices(anAllowedIndexes, "_PolyXY_", anObjsSize, anExistingNames, aBaseFileName); + for (size_t i = 0; i < mySHPObjects.size(); i++ ) { - ReadSHPPolyXY(theDocument, mySHPObjects[i], aBaseFileName, anAllowedIndexes[i], theEntities); + ReadSHPPolyXY(theDocument, mySHPObjects[i], aBaseFileName, anAllowedIndexes[i], theEntities, false); } aStat = 1; } @@ -561,9 +755,23 @@ int HYDROData_ShapeFile::ImportPolylines(Handle(HYDROData_Document) theDocument, anInd++; } for (size_t i = 0; i < mySHPObjects.size(); i++ ) + { ReadSHPPoly3D(theDocument, mySHPObjects[i], aBaseFileName, anAllowedIndexes[i], theEntities); + } aStat = 1; } + else if (aHSHP->nShapeType == 5) + { + //import polygon's contours as polylines + size_t anObjsSize = mySHPObjects.size(); + GetFreeIndices(anAllowedIndexes, "_PolyXY_", anObjsSize, anExistingNames, aBaseFileName); + + for (size_t i = 0; i < mySHPObjects.size(); i++ ) + { + ReadSHPPolyXY(theDocument, mySHPObjects[i], aBaseFileName, anAllowedIndexes[i], theEntities, true); + } + aStat = 2; + } else { aStat = 0; @@ -617,11 +825,16 @@ QString HYDROData_ShapeFile::GetShapeTypeName(int theType) int HYDROData_ShapeFile::TryOpenShapeFile(QString theFileName) { QString aSHPfile = theFileName.simplified(); - QString aSHXfile = theFileName.simplified().replace( ".shp", ".shx", Qt::CaseInsensitive); + QString aSHXfile = theFileName.simplified().replace( theFileName.simplified().size() - 4, 4, ".shx"); + + QString anExt = theFileName.split('.', QString::SkipEmptyParts).back(); + if (anExt.toLower() != "shp") + return -3; + FILE* pFileSHP = NULL; - pFileSHP = fopen (aSHPfile.toAscii().data(), "r"); + pFileSHP = fopen (aSHPfile.toLatin1().data(), "r"); FILE* pFileSHX = NULL; - pFileSHX = fopen (aSHXfile.toAscii().data(), "r"); + pFileSHX = fopen (aSHXfile.toLatin1().data(), "r"); if (pFileSHP == NULL || pFileSHX == NULL) { @@ -640,9 +853,9 @@ int HYDROData_ShapeFile::TryOpenShapeFile(QString theFileName) bool HYDROData_ShapeFile::CheckDBFFileExisting(const QString& theSHPFilePath, QString& thePathToDBFFile) { QString aSHPfile = theSHPFilePath.simplified(); - QString aDBFfile = theSHPFilePath.simplified().replace( ".shp", ".dbf", Qt::CaseInsensitive); + QString aDBFfile = theSHPFilePath.simplified().replace( theSHPFilePath.simplified().size() - 4, 4, ".dbf"); FILE* pFileDBF = NULL; - pFileDBF = fopen (aDBFfile.toAscii().data(), "r"); + pFileDBF = fopen (aDBFfile.toLatin1().data(), "r"); if (pFileDBF == NULL) { @@ -657,7 +870,7 @@ bool HYDROData_ShapeFile::CheckDBFFileExisting(const QString& theSHPFilePath, QS bool HYDROData_ShapeFile::DBF_OpenDBF(const QString& thePathToDBFFile) { - myHDBF = DBFOpen( thePathToDBFFile.toAscii().data(), "r" ); + myHDBF = DBFOpen( thePathToDBFFile.toLatin1().data(), "r" ); if(myHDBF != NULL) return true; else @@ -737,6 +950,16 @@ void HYDROData_ShapeFile::DBF_GetAttributeList(int theIndexOfField, std::vector< if( DBFIsAttributeNULL( myHDBF, i, theIndexOfField ) ) { anAttr.myIsNull = true; + DBF_FieldType FT = DBF_FieldType_None; + if( eType == FTString ) + FT = DBF_FieldType_String; + else if( eType == FTInteger ) + FT = DBF_FieldType_Integer; + else if( eType == FTDouble ) + FT = DBF_FieldType_Double; + else if( eType == FTInvalid ) + FT = DBF_FieldType_Invalid; + anAttr.myFieldType = FT; } else { @@ -758,7 +981,7 @@ void HYDROData_ShapeFile::DBF_GetAttributeList(int theIndexOfField, std::vector< anAttr.myIsNull = false; anAttr.myFieldType = DBF_FieldType_Integer; anAttr.myRawValue = DBFReadStringAttribute( myHDBF, i, theIndexOfField ); - anAttr.myStrVal = QString::number(iAttr); + anAttr.myIntVal = iAttr; break; } @@ -768,7 +991,7 @@ void HYDROData_ShapeFile::DBF_GetAttributeList(int theIndexOfField, std::vector< anAttr.myIsNull = false; anAttr.myFieldType = DBF_FieldType_Double; anAttr.myRawValue = DBFReadStringAttribute( myHDBF, i, theIndexOfField ); - anAttr.myStrVal = QString::number(dAttr, 'g', 20); + anAttr.myDoubleVal = dAttr; break; } default: @@ -778,4 +1001,120 @@ void HYDROData_ShapeFile::DBF_GetAttributeList(int theIndexOfField, std::vector< theAttrV.push_back(anAttr); } -} \ No newline at end of file +} + +bool HYDROData_ShapeFile::DBF_WriteFieldAndValues(const QString& theFileName, const QString& theFieldName, DBF_FieldType theType, const std::vector& theAttrV, bool bUseRawValue) +{ + // Check that given field type is equal to field types of attributes values + for (size_t i = 0; i < theAttrV.size(); i++) + { + if (theAttrV[i].myFieldType != theType) + return false; + } + + DBFHandle hDBF; + hDBF = DBFCreate( theFileName.toStdString().c_str() ); + if( hDBF == NULL ) + return false; + + if (theType != DBF_FieldType_String && theType != DBF_FieldType_Integer && theType != DBF_FieldType_Double) + { + DBFClose( hDBF ); + return false; //cant handle any other cases + } + + int nWidth = 20; + switch( theType ) + { + case DBF_FieldType_String: + { + DBFAddField (hDBF, theFieldName.toStdString().c_str(), FTString, nWidth, 0); + break; + } + + case DBF_FieldType_Integer: + { + DBFAddField (hDBF, theFieldName.toStdString().c_str(), FTInteger, nWidth, 0); + break; + } + + case DBF_FieldType_Double: + { + DBFAddField (hDBF, theFieldName.toStdString().c_str(), FTDouble, nWidth, 0); + break; + } + default: + break; + } + + if (DBFGetFieldCount( hDBF ) != 1) + { + DBFClose( hDBF ); + return false; + } + if (DBFGetRecordCount( hDBF ) != 0) + { + DBFClose( hDBF ); + return false; + } + int stat = -1; + + if (bUseRawValue) + { + for (size_t i = 0; i < theAttrV.size(); i++) + { + if (!theAttrV[i].myIsNull) + stat = DBFWriteStringAttribute(hDBF, (int)i, 0, theAttrV[i].myRawValue.c_str()); + else + stat = DBFWriteNULLAttribute(hDBF, (int)i, 0 ); + + if (stat != 1) + { + DBFClose( hDBF ); + return false; + } + } + } + else + { + for (size_t i = 0; i < theAttrV.size(); i++) + { + if (!theAttrV[i].myIsNull) + switch( theType ) + { + case DBF_FieldType_String: + { + stat = DBFWriteStringAttribute(hDBF, (int)i, 0, theAttrV[i].myStrVal.toStdString().c_str()); + break; + } + + case DBF_FieldType_Integer: + { + stat = DBFWriteIntegerAttribute(hDBF, (int)i, 0, theAttrV[i].myIntVal); + break; + } + + case DBF_FieldType_Double: + { + stat = DBFWriteDoubleAttribute(hDBF, (int)i, 0, theAttrV[i].myDoubleVal); + break; + } + default: + break; + } + else + stat = DBFWriteNULLAttribute(hDBF, (int)i, 0 ); + + if (stat != 1) + { + DBFClose( hDBF ); + return false; + } + } + } + + DBFClose( hDBF ); + return true; + +} +