Lucene.Net  3.0.3
Lucene.Net is a .NET port of the Java Lucene Indexing Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties
AreaSimilarity.cs
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 using System;
19 using Lucene.Net.Search;
20 using Spatial4n.Core.Context;
21 using Spatial4n.Core.Shapes;
22 
23 namespace Lucene.Net.Spatial.BBox
24 {
51  {
52  /*
53  * Properties associated with the query envelope
54  */
55  private readonly Rectangle queryExtent;
56  private readonly double queryArea;
57 
58  private readonly double targetPower;
59  private readonly double queryPower;
60 
61  public AreaSimilarity(Rectangle queryExtent, double queryPower, double targetPower)
62  {
63  this.queryExtent = queryExtent;
64  this.queryArea = queryExtent.GetArea(null);
65 
66  this.queryPower = queryPower;
67  this.targetPower = targetPower;
68 
69  // if (this.qryMinX > queryExtent.getMaxX()) {
70  // this.qryCrossedDateline = true;
71  // this.qryArea = Math.abs(qryMaxX + 360.0 - qryMinX) * Math.abs(qryMaxY - qryMinY);
72  // } else {
73  // this.qryArea = Math.abs(qryMaxX - qryMinX) * Math.abs(qryMaxY - qryMinY);
74  // }
75  }
76 
77  public AreaSimilarity(Rectangle queryExtent)
78  : this(queryExtent, 2.0, 0.5)
79  {
80  }
81 
82  public String GetDelimiterQueryParameters()
83  {
84  return queryExtent + ";" + queryPower + ";" + targetPower;
85  }
86 
87  public double Score(Rectangle target, Explanation exp)
88  {
89  if (target == null || queryArea <= 0)
90  {
91  return 0;
92  }
93  double targetArea = target.GetArea(null);
94  if (targetArea <= 0)
95  {
96  return 0;
97  }
98  double score = 0;
99 
100  double top = Math.Min(queryExtent.GetMaxY(), target.GetMaxY());
101  double bottom = Math.Max(queryExtent.GetMinY(), target.GetMinY());
102  double height = top - bottom;
103  double width = 0;
104 
105  // queries that cross the date line
106  if (queryExtent.GetCrossesDateLine())
107  {
108  // documents that cross the date line
109  if (target.GetCrossesDateLine())
110  {
111  double left = Math.Max(queryExtent.GetMinX(), target.GetMinX());
112  double right = Math.Min(queryExtent.GetMaxX(), target.GetMaxX());
113  width = right + 360.0 - left;
114  }
115  else
116  {
117  double qryWestLeft = Math.Max(queryExtent.GetMinX(), target.GetMaxX());
118  double qryWestRight = Math.Min(target.GetMaxX(), 180.0);
119  double qryWestWidth = qryWestRight - qryWestLeft;
120  if (qryWestWidth > 0)
121  {
122  width = qryWestWidth;
123  }
124  else
125  {
126  double qryEastLeft = Math.Max(target.GetMaxX(), -180.0);
127  double qryEastRight = Math.Min(queryExtent.GetMaxX(), target.GetMaxX());
128  double qryEastWidth = qryEastRight - qryEastLeft;
129  if (qryEastWidth > 0)
130  {
131  width = qryEastWidth;
132  }
133  }
134  }
135  }
136  else
137  { // queries that do not cross the date line
138 
139  if (target.GetCrossesDateLine())
140  {
141  double tgtWestLeft = Math.Max(queryExtent.GetMinX(), target.GetMinX());
142  double tgtWestRight = Math.Min(queryExtent.GetMaxX(), 180.0);
143  double tgtWestWidth = tgtWestRight - tgtWestLeft;
144  if (tgtWestWidth > 0)
145  {
146  width = tgtWestWidth;
147  }
148  else
149  {
150  double tgtEastLeft = Math.Max(queryExtent.GetMinX(), -180.0);
151  double tgtEastRight = Math.Min(queryExtent.GetMaxX(), target.GetMaxX());
152  double tgtEastWidth = tgtEastRight - tgtEastLeft;
153  if (tgtEastWidth > 0)
154  {
155  width = tgtEastWidth;
156  }
157  }
158  }
159  else
160  {
161  double left = Math.Max(queryExtent.GetMinX(), target.GetMinX());
162  double right = Math.Min(queryExtent.GetMaxX(), target.GetMaxX());
163  width = right - left;
164  }
165  }
166 
167 
168  // calculate the score
169  if ((width > 0) && (height > 0))
170  {
171  double intersectionArea = width * height;
172  double queryRatio = intersectionArea / queryArea;
173  double targetRatio = intersectionArea / targetArea;
174  double queryFactor = Math.Pow(queryRatio, queryPower);
175  double targetFactor = Math.Pow(targetRatio, targetPower);
176  score = queryFactor * targetFactor * 10000.0;
177 
178  if (exp != null)
179  {
180  // StringBuilder sb = new StringBuilder();
181  // sb.append("\nscore=").append(score);
182  // sb.append("\n query=").append();
183  // sb.append("\n target=").append(target.toString());
184  // sb.append("\n intersectionArea=").append(intersectionArea);
185  //
186  // sb.append(" queryArea=").append(queryArea).append(" targetArea=").append(targetArea);
187  // sb.append("\n queryRatio=").append(queryRatio).append(" targetRatio=").append(targetRatio);
188  // sb.append("\n queryFactor=").append(queryFactor).append(" targetFactor=").append(targetFactor);
189  // sb.append(" (queryPower=").append(queryPower).append(" targetPower=").append(targetPower).append(")");
190 
191  exp.Value = (float) score;
192  exp.Description = GetType().Name;
193 
194  Explanation e = null;
195 
196  exp.AddDetail(e = new Explanation((float)intersectionArea, "IntersectionArea"));
197  e.AddDetail(new Explanation((float)width, "width; Query: " + queryExtent));
198  e.AddDetail(new Explanation((float)height, "height; Target: " + target));
199 
200  exp.AddDetail(e = new Explanation((float)queryFactor, "Query"));
201  e.AddDetail(new Explanation((float)queryArea, "area"));
202  e.AddDetail(new Explanation((float)queryRatio, "ratio"));
203  e.AddDetail(new Explanation((float)queryPower, "power"));
204 
205  exp.AddDetail(e = new Explanation((float)targetFactor, "Target"));
206  e.AddDetail(new Explanation((float)targetArea, "area"));
207  e.AddDetail(new Explanation((float)targetRatio, "ratio"));
208  e.AddDetail(new Explanation((float)targetPower, "power"));
209  }
210  }
211  else if (exp != null)
212  {
213  exp.Value = 0;
214  exp.Description = "Shape does not intersect";
215  }
216  return score;
217  }
218 
219  public override bool Equals(object obj)
220  {
221  var other = obj as AreaSimilarity;
222  if (other == null) return false;
223  return GetDelimiterQueryParameters().Equals(other.GetDelimiterQueryParameters());
224  }
225 
226  public override int GetHashCode()
227  {
228  return GetDelimiterQueryParameters().GetHashCode();
229  }
230  }
231 }