Returns the distance between the given pair of font/class pairs. Finds in cache or computes and caches. OrganizeByFontAndClass must have been already called.
| 294 | // Finds in cache or computes and caches. |
| 295 | // OrganizeByFontAndClass must have been already called. |
| 296 | float TrainingSampleSet::ClusterDistance(int font_id1, int class_id1, |
| 297 | int font_id2, int class_id2, |
| 298 | const IntFeatureMap& feature_map) { |
| 299 | ASSERT_HOST(font_class_array_ != NULL); |
| 300 | int font_index1 = font_id_map_.SparseToCompact(font_id1); |
| 301 | int font_index2 = font_id_map_.SparseToCompact(font_id2); |
| 302 | if (font_index1 < 0 || font_index2 < 0) |
| 303 | return 0.0f; |
| 304 | FontClassInfo& fc_info = (*font_class_array_)(font_index1, class_id1); |
| 305 | if (font_id1 == font_id2) { |
| 306 | // Special case cache for speed. |
| 307 | if (fc_info.unichar_distance_cache.size() == 0) |
| 308 | fc_info.unichar_distance_cache.init_to_size(unicharset_size_, -1.0f); |
| 309 | if (fc_info.unichar_distance_cache[class_id2] < 0) { |
| 310 | // Distance has to be calculated. |
| 311 | float result = ComputeClusterDistance(font_id1, class_id1, |
| 312 | font_id2, class_id2, |
| 313 | feature_map); |
| 314 | fc_info.unichar_distance_cache[class_id2] = result; |
| 315 | // Copy to the symmetric cache entry. |
| 316 | FontClassInfo& fc_info2 = (*font_class_array_)(font_index2, class_id2); |
| 317 | if (fc_info2.unichar_distance_cache.size() == 0) |
| 318 | fc_info2.unichar_distance_cache.init_to_size(unicharset_size_, -1.0f); |
| 319 | fc_info2.unichar_distance_cache[class_id1] = result; |
| 320 | } |
| 321 | return fc_info.unichar_distance_cache[class_id2]; |
| 322 | } else if (class_id1 == class_id2) { |
| 323 | // Another special-case cache for equal class-id. |
| 324 | if (fc_info.font_distance_cache.size() == 0) |
| 325 | fc_info.font_distance_cache.init_to_size(font_id_map_.CompactSize(), |
| 326 | -1.0f); |
| 327 | if (fc_info.font_distance_cache[font_index2] < 0) { |
| 328 | // Distance has to be calculated. |
| 329 | float result = ComputeClusterDistance(font_id1, class_id1, |
| 330 | font_id2, class_id2, |
| 331 | feature_map); |
| 332 | fc_info.font_distance_cache[font_index2] = result; |
| 333 | // Copy to the symmetric cache entry. |
| 334 | FontClassInfo& fc_info2 = (*font_class_array_)(font_index2, class_id2); |
| 335 | if (fc_info2.font_distance_cache.size() == 0) |
| 336 | fc_info2.font_distance_cache.init_to_size(font_id_map_.CompactSize(), |
| 337 | -1.0f); |
| 338 | fc_info2.font_distance_cache[font_index1] = result; |
| 339 | } |
| 340 | return fc_info.font_distance_cache[font_index2]; |
| 341 | } |
| 342 | // Both font and class are different. Linear search for class_id2/font_id2 |
| 343 | // in what is a hopefully short list of distances. |
| 344 | int cache_index = 0; |
| 345 | while (cache_index < fc_info.distance_cache.size() && |
| 346 | (fc_info.distance_cache[cache_index].unichar_id != class_id2 || |
| 347 | fc_info.distance_cache[cache_index].font_id != font_id2)) |
| 348 | ++cache_index; |
| 349 | if (cache_index == fc_info.distance_cache.size()) { |
| 350 | // Distance has to be calculated. |
| 351 | float result = ComputeClusterDistance(font_id1, class_id1, |
| 352 | font_id2, class_id2, |
| 353 | feature_map); |
no test coverage detected