Example #1
0
void CXySlider::DoDrag(CPoint point)
{
    CPoint pt0 = point;

    HighlightGripper(true);

    CSize inGripper = pt0 - GetGripperRect().CenterPoint();
    CPoint ptMin(m_zero - m_range + inGripper);
    CPoint ptMax(m_zero + m_range + inGripper);

    SetCapture();
    while(true)
    {
        MSG msg;
        if(!GetMessage(&msg, NULL, 0, 0))
        {
            break;
        }

        if(msg.message == WM_LBUTTONUP)
        {
            break;
        }

        if(GetCapture() != this)
        {
            break;
        }

        if(msg.message == WM_MOUSEMOVE)
        {
            CPoint pt = msg.pt;
            ScreenToClient(&pt);

            CheckMinMax(pt.x, ptMin.x, ptMax.x);
            CheckMinMax(pt.y, ptMin.y, ptMax.y);

            int dx = pt.x - pt0.x;
            int dy = pt.y - pt0.y;

            DoMoveBy(dx, dy);

            pt0 = pt;
        }
        else
        {
            DispatchMessage(&msg);
        }
    }
    ReleaseCapture();

    HighlightGripper(false);
}
Example #2
0
void CScene::computeBoundingBox()
{
  CPoint ptMax(-FLT_MAX, -FLT_MAX, -FLT_MAX), ptMin(FLT_MAX, FLT_MAX, FLT_MAX);
  CPoint objMax, objMin;

  for (vector<CObject*>::iterator objectsArrayIterator = m_objectsArray.begin();
       objectsArrayIterator != m_objectsArray.end(); objectsArrayIterator++)
  {
    (*objectsArrayIterator)->buildBoundingBox();
    (*objectsArrayIterator)->getBoundingBox(objMax, objMin);
    /* Calcul du max */
    if ( objMax.x > ptMax.x)
      ptMax.x = objMax.x;
    if ( objMax.y > ptMax.y)
      ptMax.y = objMax.y;
    if ( objMax.z > ptMax.z)
      ptMax.z = objMax.z;
    /* Calcul du min */
    if ( objMin.x < ptMin.x)
      ptMin.x = objMin.x;
    if ( objMin.y < ptMin.y)
      ptMin.y = objMin.y;
    if ( objMin.z < ptMin.z)
      ptMin.z = objMin.z;
  }

  /** Normalisation */
  CPoint offset = CPoint(0,0,0) - ((ptMax + ptMin)/2.0f);
  float invNormMax = 1.0f/((ptMax - ptMin).max());

  for (vector<CObject*>::iterator objectsArrayIterator = m_objectsArray.begin();
       objectsArrayIterator != m_objectsArray.end();
       objectsArrayIterator++)
  {
    (*objectsArrayIterator)->scale(invNormMax,offset);
  }

  m_max = (ptMax+offset) * invNormMax;
  m_min = (ptMin+offset) * invNormMax;
}
Example #3
0
// protected:
BOOL COXSplashWnd::BuildRegion(POINT ptStart)
	// --- In      : ptStart, the starting point to search for region boundary
	// --- Out     :
	// --- Returns : TRUE if successful; FALSE otherwise
	// --- Effect  : calculate the region to be visible in a bitmap
{
	CArray<CPoint, CPoint&> vertexs;
	CPoint ptMax(0,0);
	CPoint pt0(0,0);
	CPoint pt1(0,0);
	CPoint pt(0,0);
	CPoint ptPrev(0,0);
	CSize sizeInc(0,0);
	int i = 0;
	int iFirst = 0;
	int iLast = 0;
	int iPrev = 0;

	// move directions: index (xInc, yInc) alternate_index
	//        0 (-1,-1) 8    1 ( 0,-1) 9    2 ( 1,-1) 10
	//		  7 (-1, 0)	15		            3 ( 1, 0) 11
	//		  6 (-1, 1) 14   5 ( 0, 1) 13   4 ( 1, 1) 12
	const int xd[] = {-1,0,1,1,1,0,-1,-1,-1,0,1,1,1,0,-1,-1};
	const int yd[] = {-1,-1,-1,0,1,1,1,0,-1,-1,-1,0,1,1,1,0};
	const int nextdir[] = {6,0,0,2,2,4,4,6,6,0,0,2,2,4,4,6};

	BITMAP bm;
	m_dib.GetBitmapInfo(bm);
	ptMax = CPoint(bm.bmWidth - 1, bm.bmHeight - 1);

	// find a start point that's outside the region
	UNREFERENCED_PARAMETER(ptStart);
	pt0 = CPoint(0,0);
	if (!IsBorder(pt0)) 
		pt0 = CPoint(-1,-1);

	// search diagonally for first point that's within the region
	sizeInc.cx = (pt0.x > (ptMax.x / 2)) ? -1 : 1;
	sizeInc.cy = (pt0.y > (ptMax.y / 2)) ? -1 : 1;
	for (pt1 = pt0 + sizeInc; IsBorder(pt1, FALSE); pt1 += sizeInc)
		;
	pt0 = pt1 - sizeInc;
	
	// if not found after hitting the boundary, search by scan lines
	if (m_dib.GetPixel(pt1) == CLR_INVALID)
	{
		for (pt1.y = 0; pt1.y <= ptMax.y; pt1.y++)
		{
			for (pt1.x = 0; pt1.x <= ptMax.x && IsBorder(pt1); pt1.x++)
				;
			if (pt1.x <= ptMax.x) 
				break;
		}
		if (ptMax.y < pt1.y) 
			return FALSE;
		pt0 = pt1 - CSize(0, 1);
	}

	// now pt1 should be the starting point that's within the region
	// and pt0 should be a neigboring point that's outside the region
	ASSERT(IsBorder(pt0) && !IsBorder(pt1));

	// clockwise find border/region boundary
	for (i = 0; i <= 7; i++)
	{
		pt = pt1 + CSize(xd[i], yd[i]);
		if (!IsBorder(pt)) 
			break;
	}
	if (i == 8) 
		return FALSE;

	// important: assign second point as the start point to prevent
	//			  diagonal circumvent
	pt1 = pt;
	vertexs.Add(pt);
	
	// cycle until the most beginning point is found back again
	do 
	{
		iPrev = i;
		ptPrev = pt;
		iFirst = nextdir[i];
		iLast = iFirst + 6;
		for (i = iFirst; i <= iLast; i++)
		{
			pt = ptPrev + CSize(xd[i], yd[i]);
			if (!IsBorder(pt)) 
				break;
		}
		if (i == iPrev)
		{
			// moving forward on the same direction
			// replace the last point with this new one, so that region
			// definition could be simpler
			vertexs[vertexs.GetSize()-1] = pt;
		}
		else
		{
			// direction changed, has to add a new vertex
			vertexs.Add(pt);
		}
		if(vertexs.GetSize()%3000==0)
			TRACE(_T("Add point: %d,%d, number %d\n"),pt.x,pt.y,vertexs.GetSize());
	} while (pt != pt1);

	m_rgn.DeleteObject();
	if (!m_rgn.CreatePolygonRgn(vertexs.GetData(), PtrToInt(vertexs.GetSize()), ALTERNATE))
	{
		ASSERT((HRGN)m_rgn == NULL);
		return FALSE;
	}

	return TRUE;
}
Example #4
0
void QgsWfsCapabilities::capabilitiesReplyFinished()
{
  const QByteArray& buffer = mResponse;

  QgsDebugMsg( "parsing capabilities: " + buffer );

  // parse XML
  QString capabilitiesDocError;
  QDomDocument capabilitiesDocument;
  if ( !capabilitiesDocument.setContent( buffer, true, &capabilitiesDocError ) )
  {
    mErrorCode = QgsWfsRequest::XmlError;
    mErrorMessage = capabilitiesDocError;
    emit gotCapabilities();
    return;
  }

  QDomElement doc = capabilitiesDocument.documentElement();

  // handle exceptions
  if ( doc.tagName() == "ExceptionReport" )
  {
    QDomNode ex = doc.firstChild();
    QString exc = ex.toElement().attribute( "exceptionCode", "Exception" );
    QDomElement ext = ex.firstChild().toElement();
    mErrorCode = QgsWfsRequest::ServerExceptionError;
    mErrorMessage = exc + ": " + ext.firstChild().nodeValue();
    emit gotCapabilities();
    return;
  }

  mCaps.clear();

  //test wfs version
  mCaps.version = doc.attribute( "version" );
  if ( !mCaps.version.startsWith( "1.0" ) &&
       !mCaps.version.startsWith( "1.1" ) &&
       !mCaps.version.startsWith( "2.0" ) )
  {
    mErrorCode = WFSVersionNotSupported;
    mErrorMessage = tr( "WFS version %1 not supported" ).arg( mCaps.version );
    emit gotCapabilities();
    return;
  }

  // WFS 2.0 implementation are supposed to implement resultType=hits, and some
  // implementations (GeoServer) might advertize it, whereas others (MapServer) do not.
  // WFS 1.1 implementation too I think, but in the examples of the GetCapabilites
  // response of the WFS 1.1 standard (and in common implementations), this is
  // explictly advertized
  if ( mCaps.version.startsWith( "2.0" ) )
    mCaps.supportsHits = true;

  // Note: for conveniency, we do not use the elementsByTagNameNS() method as
  // the WFS and OWS namespaces URI are not the same in all versions

  // find <ows:OperationsMetadata>
  QDomElement operationsMetadataElem = doc.firstChildElement( "OperationsMetadata" );
  if ( !operationsMetadataElem.isNull() )
  {
    QDomNodeList contraintList = operationsMetadataElem.elementsByTagName( "Constraint" );
    for ( int i = 0; i < contraintList.size(); ++i )
    {
      QDomElement contraint = contraintList.at( i ).toElement();
      if ( contraint.attribute( "name" ) == "DefaultMaxFeatures" /* WFS 1.1 */ )
      {
        QDomElement value = contraint.firstChildElement( "Value" );
        if ( !value.isNull() )
        {
          mCaps.maxFeatures = value.text().toInt();
          QgsDebugMsg( QString( "maxFeatures: %1" ).arg( mCaps.maxFeatures ) );
        }
      }
      else if ( contraint.attribute( "name" ) == "CountDefault" /* WFS 2.0 (e.g. MapServer) */ )
      {
        QDomElement value = contraint.firstChildElement( "DefaultValue" );
        if ( !value.isNull() )
        {
          mCaps.maxFeatures = value.text().toInt();
          QgsDebugMsg( QString( "maxFeatures: %1" ).arg( mCaps.maxFeatures ) );
        }
      }
      else if ( contraint.attribute( "name" ) == "ImplementsResultPaging" /* WFS 2.0 */ )
      {
        QDomElement value = contraint.firstChildElement( "DefaultValue" );
        if ( !value.isNull() && value.text() == "TRUE" )
        {
          mCaps.supportsPaging = true;
          QgsDebugMsg( "Supports paging" );
        }
      }
      else if ( contraint.attribute( "name" ) == "ImplementsStandardJoins" ||
                contraint.attribute( "name" ) == "ImplementsSpatialJoins" /* WFS 2.0 */ )
      {
        QDomElement value = contraint.firstChildElement( "DefaultValue" );
        if ( !value.isNull() && value.text() == "TRUE" )
        {
          mCaps.supportsJoins = true;
          QgsDebugMsg( "Supports joins" );
        }
      }
    }

    // In WFS 2.0, max features can also be set in Operation.GetFeature (e.g. GeoServer)
    // and we are also interested by resultType=hits for WFS 1.1
    QDomNodeList operationList = operationsMetadataElem.elementsByTagName( "Operation" );
    for ( int i = 0; i < operationList.size(); ++i )
    {
      QDomElement operation = operationList.at( i ).toElement();
      if ( operation.attribute( "name" ) == "GetFeature" )
      {
        QDomNodeList operationContraintList = operation.elementsByTagName( "Constraint" );
        for ( int j = 0; j < operationContraintList.size(); ++j )
        {
          QDomElement contraint = operationContraintList.at( j ).toElement();
          if ( contraint.attribute( "name" ) == "CountDefault" )
          {
            QDomElement value = contraint.firstChildElement( "DefaultValue" );
            if ( !value.isNull() )
            {
              mCaps.maxFeatures = value.text().toInt();
              QgsDebugMsg( QString( "maxFeatures: %1" ).arg( mCaps.maxFeatures ) );
            }
            break;
          }
        }

        QDomNodeList parameterList = operation.elementsByTagName( "Parameter" );
        for ( int j = 0; j < parameterList.size(); ++j )
        {
          QDomElement parameter = parameterList.at( j ).toElement();
          if ( parameter.attribute( "name" ) == "resultType" )
          {
            QDomNodeList valueList = parameter.elementsByTagName( "Value" );
            for ( int k = 0; k < valueList.size(); ++k )
            {
              QDomElement value = valueList.at( k ).toElement();
              if ( value.text() == "hits" )
              {
                mCaps.supportsHits = true;
                QgsDebugMsg( "Support hits" );
                break;
              }
            }
          }
        }

        break;
      }
    }
  }

  //go to <FeatureTypeList>
  QDomElement featureTypeListElem = doc.firstChildElement( "FeatureTypeList" );
  if ( featureTypeListElem.isNull() )
  {
    emit gotCapabilities();
    return;
  }

  // Parse operations supported for all feature types
  bool insertCap, updateCap, deleteCap;
  parseSupportedOperations( featureTypeListElem.firstChildElement( "Operations" ),
                            insertCap,
                            updateCap,
                            deleteCap );

  // get the <FeatureType> elements
  QDomNodeList featureTypeList = featureTypeListElem.elementsByTagName( "FeatureType" );
  for ( int i = 0; i < featureTypeList.size(); ++i )
  {
    FeatureType featureType;
    QDomElement featureTypeElem = featureTypeList.at( i ).toElement();

    //Name
    QDomNodeList nameList = featureTypeElem.elementsByTagName( "Name" );
    if ( nameList.length() > 0 )
    {
      featureType.name = nameList.at( 0 ).toElement().text();
    }
    //Title
    QDomNodeList titleList = featureTypeElem.elementsByTagName( "Title" );
    if ( titleList.length() > 0 )
    {
      featureType.title = titleList.at( 0 ).toElement().text();
    }
    //Abstract
    QDomNodeList abstractList = featureTypeElem.elementsByTagName( "Abstract" );
    if ( abstractList.length() > 0 )
    {
      featureType.abstract = abstractList.at( 0 ).toElement().text();
    }

    //DefaultSRS is always the first entry in the feature srs list
    QDomNodeList defaultCRSList = featureTypeElem.elementsByTagName( "DefaultSRS" );
    if ( defaultCRSList.length() == 0 )
      // In WFS 2.0, this is spelled DefaultCRS...
      defaultCRSList = featureTypeElem.elementsByTagName( "DefaultCRS" );
    if ( defaultCRSList.length() > 0 )
    {
      QString srsname( defaultCRSList.at( 0 ).toElement().text() );
      // Some servers like Geomedia advertize EPSG:XXXX even in WFS 1.1 or 2.0
      if ( srsname.startsWith( "EPSG:" ) )
        mCaps.useEPSGColumnFormat = true;
      featureType.crslist.append( NormalizeSRSName( srsname ) );
    }

    //OtherSRS
    QDomNodeList otherCRSList = featureTypeElem.elementsByTagName( "OtherSRS" );
    if ( otherCRSList.length() == 0 )
      // In WFS 2.0, this is spelled OtherCRS...
      otherCRSList = featureTypeElem.elementsByTagName( "OtherCRS" );
    for ( int i = 0; i < otherCRSList.size(); ++i )
    {
      featureType.crslist.append( NormalizeSRSName( otherCRSList.at( i ).toElement().text() ) );
    }

    //Support <SRS> for compatibility with older versions
    QDomNodeList srsList = featureTypeElem.elementsByTagName( "SRS" );
    for ( int i = 0; i < srsList.size(); ++i )
    {
      featureType.crslist.append( NormalizeSRSName( srsList.at( i ).toElement().text() ) );
    }

    // Get BBox WFS 1.0 way
    QDomElement latLongBB = featureTypeElem.firstChildElement( "LatLongBoundingBox" );
    if ( latLongBB.hasAttributes() )
    {
      // Despite the name LatLongBoundingBox, the coordinates are supposed to
      // be expressed in <SRS>. From the WFS schema;
      // <!-- The LatLongBoundingBox element is used to indicate the edges of
      // an enclosing rectangle in the SRS of the associated feature type.
      featureType.bbox = QgsRectangle(
                           latLongBB.attribute( "minx" ).toDouble(),
                           latLongBB.attribute( "miny" ).toDouble(),
                           latLongBB.attribute( "maxx" ).toDouble(),
                           latLongBB.attribute( "maxy" ).toDouble() );
      featureType.bboxSRSIsWGS84 = false;

      // But some servers do not honour this and systematically reproject to WGS84
      // such as GeoServer. See http://osgeo-org.1560.x6.nabble.com/WFS-LatLongBoundingBox-td3813810.html
      // This is also true of TinyOWS
      if ( !featureType.crslist.isEmpty() &&
           featureType.bbox.xMinimum() >= -180 && featureType.bbox.yMinimum() >= -90 &&
           featureType.bbox.xMaximum() <= 180 && featureType.bbox.yMaximum() < 90 )
      {
        QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( featureType.crslist[0] );
        if ( !crs.isGeographic() )
        {
          // If the CRS is projected then check that projecting the corner of the bbox, assumed to be in WGS84,
          // into the CRS, and then back to WGS84, works (check that we are in the validity area)
          QgsCoordinateReferenceSystem crsWGS84 = QgsCoordinateReferenceSystem::fromOgcWmsCrs( "CRS:84" );
          QgsCoordinateTransform ct( crsWGS84, crs );

          QgsPoint ptMin( featureType.bbox.xMinimum(), featureType.bbox.yMinimum() );
          QgsPoint ptMinBack( ct.transform( ct.transform( ptMin, QgsCoordinateTransform::ForwardTransform ), QgsCoordinateTransform::ReverseTransform ) );
          QgsPoint ptMax( featureType.bbox.xMaximum(), featureType.bbox.yMaximum() );
          QgsPoint ptMaxBack( ct.transform( ct.transform( ptMax, QgsCoordinateTransform::ForwardTransform ), QgsCoordinateTransform::ReverseTransform ) );

          QgsDebugMsg( featureType.bbox.toString() );
          QgsDebugMsg( ptMinBack.toString() );
          QgsDebugMsg( ptMaxBack.toString() );

          if ( fabs( featureType.bbox.xMinimum() - ptMinBack.x() ) < 1e-5 &&
               fabs( featureType.bbox.yMinimum() - ptMinBack.y() ) < 1e-5 &&
               fabs( featureType.bbox.xMaximum() - ptMaxBack.x() ) < 1e-5 &&
               fabs( featureType.bbox.yMaximum() - ptMaxBack.y() ) < 1e-5 )
          {
            QgsDebugMsg( "Values of LatLongBoundingBox are consistent with WGS84 long/lat bounds, so as the CRS is projected, assume they are indeed in WGS84 and not in the CRS units" );
            featureType.bboxSRSIsWGS84 = true;
          }
        }
      }
    }
    else
    {
      // WFS 1.1 way
      QDomElement WGS84BoundingBox = featureTypeElem.firstChildElement( "WGS84BoundingBox" );
      if ( !WGS84BoundingBox.isNull() )
      {
        QDomElement lowerCorner = WGS84BoundingBox.firstChildElement( "LowerCorner" );
        QDomElement upperCorner = WGS84BoundingBox.firstChildElement( "UpperCorner" );
        if ( !lowerCorner.isNull() && !upperCorner.isNull() )
        {
          QStringList lowerCornerList = lowerCorner.text().split( " ", QString::SkipEmptyParts );
          QStringList upperCornerList = upperCorner.text().split( " ", QString::SkipEmptyParts );
          if ( lowerCornerList.size() == 2 && upperCornerList.size() == 2 )
          {
            featureType.bbox = QgsRectangle(
                                 lowerCornerList[0].toDouble(),
                                 lowerCornerList[1].toDouble(),
                                 upperCornerList[0].toDouble(),
                                 upperCornerList[1].toDouble() );
            featureType.bboxSRSIsWGS84 = true;
          }
        }
      }
    }

    // Parse Operations specific to the type name
    parseSupportedOperations( featureTypeElem.firstChildElement( "Operations" ),
                              featureType.insertCap,
                              featureType.updateCap,
                              featureType.deleteCap );
    featureType.insertCap |= insertCap;
    featureType.updateCap |= updateCap;
    featureType.deleteCap |= deleteCap;

    mCaps.featureTypes.push_back( featureType );
  }

  Q_FOREACH ( const FeatureType& f, mCaps.featureTypes )
  {
    mCaps.setAllTypenames.insert( f.name );
    QString unprefixed( QgsWFSUtils::removeNamespacePrefix( f.name ) );
    if ( !mCaps.setAmbiguousUnprefixedTypename.contains( unprefixed ) )
    {
      if ( mCaps.mapUnprefixedTypenameToPrefixedTypename.contains( unprefixed ) )
      {
        mCaps.setAmbiguousUnprefixedTypename.insert( unprefixed );
        mCaps.mapUnprefixedTypenameToPrefixedTypename.remove( unprefixed );
      }
      else
      {
        mCaps.mapUnprefixedTypenameToPrefixedTypename[unprefixed] = f.name;
      }
    }
  }

  //go to <Filter_Capabilities>
  QDomElement filterCapabilitiesElem = doc.firstChildElement( "Filter_Capabilities" );
  if ( !filterCapabilitiesElem.isNull() )
    parseFilterCapabilities( filterCapabilitiesElem );

  // Hard-coded functions
  Function f_ST_GeometryFromText( "ST_GeometryFromText", 1, 2 );
  f_ST_GeometryFromText.returnType = "gml:AbstractGeometryType";
  f_ST_GeometryFromText.argumentList << Argument( "wkt", "xs:string" );
  f_ST_GeometryFromText.argumentList << Argument( "srsname", "xs:string" );
  mCaps.functionList << f_ST_GeometryFromText;

  Function f_ST_GeomFromGML( "ST_GeomFromGML", 1 );
  f_ST_GeomFromGML.returnType = "gml:AbstractGeometryType";
  f_ST_GeomFromGML.argumentList << Argument( "gml", "xs:string" );
  mCaps.functionList << f_ST_GeomFromGML;

  Function f_ST_MakeEnvelope( "ST_MakeEnvelope", 4, 5 );
  f_ST_MakeEnvelope.returnType = "gml:AbstractGeometryType";
  f_ST_MakeEnvelope.argumentList << Argument( "minx", "xs:double" );
  f_ST_MakeEnvelope.argumentList << Argument( "miny", "xs:double" );
  f_ST_MakeEnvelope.argumentList << Argument( "maxx", "xs:double" );
  f_ST_MakeEnvelope.argumentList << Argument( "maxy", "xs:double" );
  f_ST_MakeEnvelope.argumentList << Argument( "srsname", "xs:string" );
  mCaps.functionList << f_ST_MakeEnvelope;

  emit gotCapabilities();
}