1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
/**********************************************************************
* $Id: MCPointInRing.cpp,v 1.17 2004/07/08 19:34:49 strk Exp $
*
* GEOS - Geometry Engine Open Source
* http://geos.refractions.net
*
* Copyright (C) 2001-2002 Vivid Solutions Inc.
*
* This is free software; you can redistribute and/or modify it under
* the terms of the GNU Lesser General Public Licence as published
* by the Free Software Foundation.
* See the COPYING file for more information.
*
**********************************************************************
* $Log: MCPointInRing.cpp,v $
* Revision 1.17 2004/07/08 19:34:49 strk
* Mirrored JTS interface of CoordinateSequence, factory and
* default implementations.
* Added DefaultCoordinateSequenceFactory::instance() function.
*
* Revision 1.16 2004/07/02 13:28:26 strk
* Fixed all #include lines to reflect headers layout change.
* Added client application build tips in README.
*
* Revision 1.15 2003/11/07 01:23:42 pramsey
* Add standard CVS headers licence notices and copyrights to all cpp and h
* files.
*
* Revision 1.14 2003/10/16 08:50:00 strk
* Memory leak fixes. Improved performance by mean of more calls to
* new getCoordinatesRO() when applicable.
* Adapted to new getCoordinatesRO() interface
*
**********************************************************************/
#include <geos/geosAlgorithm.h>
#include <stdio.h>
namespace geos {
MCPointInRing::MCSelecter::MCSelecter(const Coordinate& newP,MCPointInRing *prt) {
p=newP;
parent=prt;
}
void MCPointInRing::MCSelecter::select(LineSegment *ls) {
parent->testLineSegment(p,ls);
}
MCPointInRing::MCPointInRing(LinearRing *newRing) {
ring=newRing;
tree=NULL;
crossings=0;
pts=NULL;
interval=new BinTreeInterval();
buildIndex();
}
MCPointInRing::~MCPointInRing() {
delete tree;
delete interval;
delete pts;
}
void MCPointInRing::buildIndex() {
// Envelope *env=ring->getEnvelopeInternal();
tree=new Bintree();
pts=CoordinateSequence::removeRepeatedPoints(ring->getCoordinatesRO());
vector<indexMonotoneChain*> *mcList=MonotoneChainBuilder::getChains(pts);
for(int i=0;i<(int)mcList->size();i++) {
indexMonotoneChain *mc=(*mcList)[i];
Envelope *mcEnv=mc->getEnvelope();
interval->min=mcEnv->getMinY();
interval->max=mcEnv->getMaxY();
tree->insert(interval,mc);
}
delete mcList;
}
bool MCPointInRing::isInside(const Coordinate& pt) {
crossings=0;
// test all segments intersected by ray from pt in positive x direction
Envelope *rayEnv=new Envelope(DoubleNegInfinity,DoubleInfinity,pt.y,pt.y);
interval->min=pt.y;
interval->max=pt.y;
vector<void*> *segs=tree->query(interval);
//System.out.println("query size=" + segs.size());
MCSelecter *mcSelecter=new MCSelecter(pt,this);
for(int i=0;i<(int)segs->size();i++) {
indexMonotoneChain *mc=(indexMonotoneChain*) (*segs)[i];
testMonotoneChain(rayEnv,mcSelecter,mc);
}
/*
* p is inside if number of crossings is odd.
*/
// for(int i=0;i<(int)segs->size();i++) {
// delete (indexMonotoneChain*) (*segs)[i];
// }
delete segs;
delete rayEnv;
delete mcSelecter;
if((crossings%2)==1) {
return true;
}
return false;
}
void MCPointInRing::testMonotoneChain(Envelope *rayEnv,MCSelecter *mcSelecter,indexMonotoneChain *mc) {
mc->select(rayEnv, mcSelecter);
}
void MCPointInRing::testLineSegment(Coordinate& p,LineSegment *seg) {
double xInt; // x intersection of segment with ray
double x1; // translated coordinates
double y1;
double x2;
double y2;
/*
* Test if segment crosses ray from test point in positive x direction.
*/
Coordinate& p1=seg->p0;
Coordinate& p2=seg->p1;
x1=p1.x-p.x;
y1=p1.y-p.y;
x2=p2.x-p.x;
y2=p2.y-p.y;
if (((y1>0)&&(y2<=0)) || ((y2>0)&&(y1<=0))) {
/*
* segment straddles x axis, so compute intersection.
*/
xInt=RobustDeterminant::signOfDet2x2(x1,y1,x2,y2)/(y2-y1);
//xsave=xInt;
/*
* crosses ray if strictly positive intersection.
*/
if (0.0<xInt) {
crossings++;
}
}
}
}
|