1 | // //////////////////////////////
|
2 | // ## class fuzzyFactory
|
3 | // This class acts as a factory for objects. We can search for an object with approximately
|
4 | // the desired properties (say a rectangle with width 2 and height 1)
|
5 | // The lookupOrCreate() method looks for an existing object (for example it may find an existing rectangle
|
6 | // with width 2.0001 and height 0.999. If no object is found, the user supplied callback is
|
7 | // called, which should generate a new object. The new object is inserted into the database
|
8 | // so it can be found by future lookupOrCreate() calls.
|
9 | // Constructor:
|
10 | // numdimensions: the number of parameters for each object
|
11 | // for example for a 2D rectangle this would be 2
|
12 | // tolerance: The maximum difference for each parameter allowed to be considered a match
|
13 | const FuzzyFactory = function (numdimensions, tolerance) {
|
14 | this.lookuptable = {}
|
15 | this.multiplier = 1.0 / tolerance
|
16 | }
|
17 |
|
18 | FuzzyFactory.prototype = {
|
19 | // let obj = f.lookupOrCreate([el1, el2, el3], function(elements) {/* create the new object */});
|
20 | // Performs a fuzzy lookup of the object with the specified elements.
|
21 | // If found, returns the existing object
|
22 | // If not found, calls the supplied callback function which should create a new object with
|
23 | // the specified properties. This object is inserted in the lookup database.
|
24 | lookupOrCreate: function (els, creatorCallback) {
|
25 | let hash = ''
|
26 | let multiplier = this.multiplier
|
27 | els.forEach(function (el) {
|
28 | let valueQuantized = Math.round(el * multiplier)
|
29 | hash += valueQuantized + '/'
|
30 | })
|
31 | if (hash in this.lookuptable) {
|
32 | return this.lookuptable[hash]
|
33 | } else {
|
34 | let object = creatorCallback(els)
|
35 | let hashparts = els.map(function (el) {
|
36 | let q0 = Math.floor(el * multiplier)
|
37 | let q1 = q0 + 1
|
38 | return ['' + q0 + '/', '' + q1 + '/']
|
39 | })
|
40 | let numelements = els.length
|
41 | let numhashes = 1 << numelements
|
42 | for (let hashmask = 0; hashmask < numhashes; ++hashmask) {
|
43 | let hashmaskShifted = hashmask
|
44 | hash = ''
|
45 | hashparts.forEach(function (hashpart) {
|
46 | hash += hashpart[hashmaskShifted & 1]
|
47 | hashmaskShifted >>= 1
|
48 | })
|
49 | this.lookuptable[hash] = object
|
50 | }
|
51 | return object
|
52 | }
|
53 | }
|
54 | }
|
55 |
|
56 | module.exports = FuzzyFactory
|