void ILI1Reader::ReadGeom(char **stgeom, OGRwkbGeometryType eType, OGRFeature *feature) { char **tokens = NULL; const char *firsttok = NULL; int end = FALSE; int isArc = FALSE; OGRLineString *ogrLine = NULL; //current line OGRLinearRing *ogrRing = NULL; //current ring OGRPolygon *ogrPoly = NULL; //current polygon OGRPoint ogrPoint, arcPoint, endPoint; //points for arc interpolation OGRMultiLineString *ogrMultiLine = NULL; //current multi line //tokens = ["STPT", "1111", "22222"] ogrPoint.setX(atof(stgeom[1])); ogrPoint.setY(atof(stgeom[2])); ogrLine = (eType == wkbPolygon) ? new OGRLinearRing() : new OGRLineString(); ogrLine->addPoint(&ogrPoint); //Set feature geometry if (eType == wkbMultiLineString) { ogrMultiLine = new OGRMultiLineString(); feature->SetGeometryDirectly(ogrMultiLine); } else if (eType == wkbGeometryCollection) //AREA { if (feature->GetGeometryRef()) ogrMultiLine = (OGRMultiLineString *)feature->GetGeometryRef(); else { ogrMultiLine = new OGRMultiLineString(); feature->SetGeometryDirectly(ogrMultiLine); } } else if (eType == wkbPolygon) { if (feature->GetGeometryRef()) { ogrPoly = (OGRPolygon *)feature->GetGeometryRef(); if (ogrPoly->getNumInteriorRings() > 0) ogrRing = ogrPoly->getInteriorRing(ogrPoly->getNumInteriorRings()-1); else ogrRing = ogrPoly->getExteriorRing(); if (ogrRing && !ogrRing->get_IsClosed()) ogrLine = ogrRing; //SURFACE polygon spread over multiple OBJECTs } else { ogrPoly = new OGRPolygon(); feature->SetGeometryDirectly(ogrPoly); } } else { feature->SetGeometryDirectly(ogrLine); } //Parse geometry while (!end && (tokens = ReadParseLine())) { firsttok = CSLGetField(tokens, 0); if (EQUAL(firsttok, "LIPT")) { if (isArc) { endPoint.setX(atof(tokens[1])); endPoint.setY(atof(tokens[2])); interpolateArc(ogrLine, &ogrPoint, &arcPoint, &endPoint, arcIncr); } ogrPoint.setX(atof(tokens[1])); ogrPoint.setY(atof(tokens[2])); isArc = FALSE; ogrLine->addPoint(&ogrPoint); } else if (EQUAL(firsttok, "ARCP")) { isArc = TRUE; arcPoint.setX(atof(tokens[1])); arcPoint.setY(atof(tokens[2])); } else if (EQUAL(firsttok, "ELIN")) { if (ogrMultiLine) { ogrMultiLine->addGeometryDirectly(ogrLine); } if (ogrPoly && ogrLine != ogrRing) { ogrPoly->addRingDirectly((OGRLinearRing *)ogrLine); } end = TRUE; } else if (EQUAL(firsttok, "EEDG")) { end = TRUE; } else if (EQUAL(firsttok, "LATT")) { //Line Attributes (ignored) } else if (EQUAL(firsttok, "EFLA")) { end = TRUE; } else if (EQUAL(firsttok, "ETAB")) { end = TRUE; } else { CPLDebug( "OGR_ILI", "Unexpected token: %s", firsttok ); } CSLDestroy(tokens); } }
void QgsCircularString::segmentize( const QgsPointV2 &p1, const QgsPointV2 &p2, const QgsPointV2 &p3, QgsPointSequence &points, double tolerance, SegmentationToleranceType toleranceType ) const { bool clockwise = false; int segSide = segmentSide( p1, p3, p2 ); if ( segSide == -1 ) { clockwise = true; } QgsPointV2 circlePoint1 = clockwise ? p3 : p1; QgsPointV2 circlePoint2 = p2; QgsPointV2 circlePoint3 = clockwise ? p1 : p3 ; //adapted code from postgis double radius = 0; double centerX = 0; double centerY = 0; QgsGeometryUtils::circleCenterRadius( circlePoint1, circlePoint2, circlePoint3, radius, centerX, centerY ); if ( circlePoint1 != circlePoint3 && ( radius < 0 || qgsDoubleNear( segSide, 0.0 ) ) ) //points are colinear { points.append( p1 ); points.append( p2 ); points.append( p3 ); return; } double increment = tolerance; //one segment per degree if ( toleranceType == QgsAbstractGeometry::MaximumDifference ) { double halfAngle = acos( -tolerance / radius + 1 ); increment = 2 * halfAngle; } //angles of pt1, pt2, pt3 double a1 = atan2( circlePoint1.y() - centerY, circlePoint1.x() - centerX ); double a2 = atan2( circlePoint2.y() - centerY, circlePoint2.x() - centerX ); double a3 = atan2( circlePoint3.y() - centerY, circlePoint3.x() - centerX ); /* Adjust a3 up so we can increment from a1 to a3 cleanly */ if ( a3 <= a1 ) a3 += 2.0 * M_PI; if ( a2 < a1 ) a2 += 2.0 * M_PI; bool hasZ = is3D(); bool hasM = isMeasure(); double x, y; double z = 0; double m = 0; QList<QgsPointV2> stringPoints; stringPoints.insert( clockwise ? 0 : stringPoints.size(), circlePoint1 ); if ( circlePoint2 != circlePoint3 && circlePoint1 != circlePoint2 ) //draw straight line segment if two points have the same position { QgsWkbTypes::Type pointWkbType = QgsWkbTypes::Point; if ( hasZ ) pointWkbType = QgsWkbTypes::addZ( pointWkbType ); if ( hasM ) pointWkbType = QgsWkbTypes::addM( pointWkbType ); //make sure the curve point p2 is part of the segmentized vertices. But only if p1 != p3 bool addP2 = true; if ( qgsDoubleNear( circlePoint1.x(), circlePoint3.x() ) && qgsDoubleNear( circlePoint1.y(), circlePoint3.y() ) ) { addP2 = false; } for ( double angle = a1 + increment; angle < a3; angle += increment ) { if ( ( addP2 && angle > a2 ) ) { stringPoints.insert( clockwise ? 0 : stringPoints.size(), circlePoint2 ); addP2 = false; } x = centerX + radius * cos( angle ); y = centerY + radius * sin( angle ); if ( !hasZ && !hasM ) { stringPoints.insert( clockwise ? 0 : stringPoints.size(), QgsPointV2( x, y ) ); continue; } if ( hasZ ) { z = interpolateArc( angle, a1, a2, a3, circlePoint1.z(), circlePoint2.z(), circlePoint3.z() ); } if ( hasM ) { m = interpolateArc( angle, a1, a2, a3, circlePoint1.m(), circlePoint2.m(), circlePoint3.m() ); } stringPoints.insert( clockwise ? 0 : stringPoints.size(), QgsPointV2( pointWkbType, x, y, z, m ) ); } } stringPoints.insert( clockwise ? 0 : stringPoints.size(), circlePoint3 ); points.append( stringPoints ); }