You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
4.0 KiB
117 lines
4.0 KiB
const express = require('express');
|
|
const bodyParser = require('body-parser');
|
|
const MTree = require('./m-tree/mtree');
|
|
const dimensions = 2;
|
|
|
|
// Generator used to generate random points for the MTree
|
|
const Generator = require('./data/generator');
|
|
|
|
// Express app
|
|
const app = express();
|
|
app.use(bodyParser.json());
|
|
|
|
// Euclidean distance function used as the distance metric for the MTree
|
|
function euclideanDistance(a, b) {
|
|
return Math.sqrt(a.reduce((acc, val, i) => acc + (val - b[i]) ** 2, 0));
|
|
}
|
|
|
|
// Create an MTree with the given dimensions and capacity, using the Euclidean distance
|
|
const mtree = new MTree(dimensions, 10, euclideanDistance);
|
|
|
|
// Generate 1000 random points
|
|
const generator = new Generator(dimensions);
|
|
const points = generator.generateMany(10000);
|
|
|
|
// Insert all points into the MTree
|
|
points.forEach(point => mtree.insert(point));
|
|
|
|
// Serve the index.html file
|
|
app.get('/', (req, res) => {
|
|
res.sendFile(__dirname + '/index.html');
|
|
});
|
|
|
|
// Return the MTree
|
|
app.get('/tree', (req, res) => {
|
|
res.send(JSON.parse(JSON.stringify(mtree, (key, value) => {
|
|
if (key === 'parent' || key === 'mtree') return value && value.id;
|
|
return value;
|
|
})));
|
|
});
|
|
|
|
// Insert a point into the MTree
|
|
app.post('/insert', (req, res) => {
|
|
const point = req.body.point;
|
|
if (!point || !Array.isArray(point)) {
|
|
return res.status(400).send('Invalid point');
|
|
}
|
|
mtree.insert(point);
|
|
res.send('Point inserted');
|
|
});
|
|
|
|
// Perform a range query on the MTree
|
|
app.get('/rangeQuery', (req, res) => {
|
|
const { queryPoint, radius } = req.query;
|
|
if (!queryPoint || !radius || JSON.parse(queryPoint).length !== dimensions) {
|
|
return res.status(400).send('Invalid query parameters');
|
|
}
|
|
console.time('mtreeRangeQuery');
|
|
const result = mtree.rangeQuery(JSON.parse(queryPoint), parseFloat(radius));
|
|
console.timeEnd('mtreeRangeQuery');
|
|
console.log(result);
|
|
|
|
console.time('sequentialSearch');
|
|
const sequentialResult = points.filter(point => euclideanDistance(point, JSON.parse(queryPoint)) <= parseFloat(radius));
|
|
console.timeEnd('sequentialSearch');
|
|
//console.log(sequentialResult.map(point => "point:" + point +" distance: " + euclideanDistance(point, JSON.parse(queryPoint))));
|
|
console.log(sequentialResult);
|
|
|
|
/*const furthestPoint = points.reduce((furthest, point) => {
|
|
const distance = euclideanDistance(point, mtree.root.entries[0].point);
|
|
return distance > euclideanDistance(furthest, mtree.root.entries[0].point) ? point : furthest;
|
|
}, points[0]);
|
|
console.log(`distance between first routing entry centroid and furthest point: ${euclideanDistance(furthestPoint, mtree.root.entries[0].point)}`);
|
|
console.log(`radius of first routing entry: ${furthestPoint, mtree.root.entries[0].radius}`);*/
|
|
|
|
res.send(result);
|
|
});
|
|
|
|
// Perform a k-NN query on the MTree
|
|
app.get('/kNNQuery', (req, res) => {
|
|
const { queryPoint, k } = req.query;
|
|
if (!queryPoint || !k) {
|
|
return res.status(400).send('Invalid query parameters');
|
|
}
|
|
const parsedQueryPoint = JSON.parse(queryPoint);
|
|
const kInt = parseInt(k, 10);
|
|
|
|
console.time('mtreeSearch');
|
|
const result = mtree.kNNQuery(parsedQueryPoint, kInt);
|
|
console.timeEnd('mtreeSearch');
|
|
|
|
console.time('sequentialSearch');
|
|
const sequentialResult = points.sort((a, b) => euclideanDistance(a, parsedQueryPoint) - euclideanDistance(b, parsedQueryPoint)).slice(0, kInt);
|
|
console.timeEnd('sequentialSearch');
|
|
|
|
console.log(sequentialResult);
|
|
|
|
res.send(result);
|
|
});
|
|
|
|
// Start the server
|
|
app.listen(3000, () => {
|
|
console.log('MTree API is running on port 3000');
|
|
});
|
|
|
|
// Recreate the MTree with the given dimensions
|
|
app.post('/recreate', (req, res) => {
|
|
const { dimensions } = req.body;
|
|
if (!dimensions || typeof dimensions !== 'number') {
|
|
return res.status(400).send('Invalid dimensions');
|
|
}
|
|
mtree = new MTree(dimensions, 10);
|
|
points = generator.generateMany(100);
|
|
points.forEach(point => mtree.insert(point));
|
|
res.send('MTree recreated');
|
|
});
|
|
|