- added a 2D collision detection for new added systems, closed #570

This commit is contained in:
Mark Friedrich
2017-12-24 01:09:29 +01:00
parent fd5b397671
commit bdefb90d23
6 changed files with 198 additions and 42 deletions

View File

@@ -40,18 +40,48 @@ define(() => {
*/
this._getElementDimension = (element) => {
let dim = null;
if(element){
// add "gap" to a and b in order to have some space around elements
dim = {
left: element.style.left ? parseInt(element.style.left, 10) : 0,
top: element.style.top ? parseInt(element.style.top, 10) : 0,
a: parseInt((element.offsetWidth / 2).toString(), 10) + this._config.gapX,
b: parseInt((element.offsetHeight / 2).toString(), 10) + this._config.gapY,
width: element.offsetWidth,
height: element.offsetHeight
};
let left = 0;
let top = 0;
let a = 0;
let b = 0;
let width = this._config.newElementWidth;
let height = this._config.newElementHeight;
if(Array.isArray(element)){
// xy coordinates
let point = [
element[0] ? parseInt(element[0], 10) : 0,
element[1] ? parseInt(element[1], 10) : 0
];
if(this._config.grid){
point = this._transformPointToGrid(point);
}
left = point[0];
top = point[1];
a = this._config.gapX ;
b = this._config.gapY ;
}else if(element){
// DOM element
left = element.style.left ? parseInt(element.style.left, 10) : 0;
top = element.style.top ? parseInt(element.style.top, 10) : 0;
a = parseInt((element.offsetWidth / 2).toString(), 10) + this._config.gapX;
b = parseInt((element.offsetHeight / 2).toString(), 10) + this._config.gapY;
width = element.offsetWidth;
height = element.offsetHeight;
}
return dim;
// add "gap" to a and b in order to have some space around elements
return {
left: left,
top: top,
a: a,
b: b,
width: width,
height: height
};
};
/**
@@ -96,6 +126,18 @@ define(() => {
return dimensions;
};
/**
* transform a x/y point into a x/y point that snaps to grid
* @param point
* @returns {*}
* @private
*/
this._transformPointToGrid = (point) => {
point[0] = Math.floor(point[0] / this._config.grid[0]) * this._config.grid[0];
point[1] = Math.floor(point[1] / this._config.grid[1]) * this._config.grid[1];
return point;
};
/**
* Transform a x/y coordinate into a 2D element with width/height
* @param centerDimension
@@ -136,8 +178,9 @@ define(() => {
// transform to grid coordinates (if grid snapping is enabled) ------------------------------------
if(this._config.grid){
left = Math.floor(left / this._config.grid[0]) * this._config.grid[0];
top = Math.floor(top / this._config.grid[1]) * this._config.grid[1];
let point = this._transformPointToGrid([left, top]);
left = point[0];
top = point[1];
}
dim = {
@@ -239,14 +282,30 @@ define(() => {
steps = steps || 1;
loops = loops || 1;
if(loops === 1){
// check center element
let centerDimension = this._getElementDimension(this._config.center);
if (!this._isOverlapping(centerDimension, dimensionContainer, allDimensions)) {
dimensions.push({
left: centerDimension.left,
top: centerDimension.top,
width: centerDimension.width,
height: centerDimension.height
});
// render debug element
this._showDebugElement(centerDimension, 0);
maxResults--;
}
}
// increase the "gab" between center element and potential found dimensions...
// ... for each recursive loop call, to get an elliptical cycle beyond
// -> defaultGab for 1. loop, ..., defaultGab + 3 * defaultGab/ 2 for 3. loop
this._config.gapX = this._config.defaultGapX + loops * Math.round(this._config.defaultGapX / 2);
this._config.gapY = this._config.defaultGapY + loops * Math.round(this._config.defaultGapY / 2);
this._config.gapX = this._config.defaultGapX + (loops - 1) * 20;
this._config.gapY = this._config.defaultGapY + (loops - 1) * 20;
let centerDimension = this._getElementDimension(this._config.center);
do {
while(maxResults > 0 && start < end){
// get all potential coordinates on an eclipse around a given "centerElementDimension"
let coordinate = this._getEllipseCoordinates(centerDimension, end);
// transform relative x/y coordinate into a absolute 2D area
@@ -264,7 +323,7 @@ define(() => {
maxResults--;
}
end -= angle;
} while (maxResults > 0 && start < end);
}
if(maxResults > 0 && loops < this._config.loops){
loops++;

View File

@@ -10,6 +10,7 @@ define([
'bootbox',
'app/map/util',
'app/map/system',
'app/map/layout',
'app/map/magnetizing',
'app/map/scrollbar',
'dragToSelect',
@@ -17,7 +18,7 @@ define([
'app/map/contextmenu',
'app/map/overlay',
'app/map/local'
], function($, Init, Util, Render, bootbox, MapUtil, System, MagnetizerWrapper) {
], function($, Init, Util, Render, bootbox, MapUtil, System, Layout, MagnetizerWrapper) {
'use strict';
@@ -2661,6 +2662,24 @@ define([
switch(action){
case 'add_system':
// add new system dialog
let grid = [MapUtil.config.mapSnapToGridDimension, MapUtil.config.mapSnapToGridDimension];
let positionFinder = new Layout.Position({
container: currentMapElement[0],
center: [position.x, position.y],
loops: 5,
defaultGapX: 10,
defaultGapY: 10,
grid: currentMapElement.hasClass(MapUtil.config.mapGridClass) ? grid : false,
debug: false
});
let dimensions = positionFinder.findNonOverlappingDimensions(1, 8);
if(dimensions.length){
position.x = dimensions[0].left;
position.y = dimensions[0].top;
}
showNewSystemDialog(currentMap, {position: position});
break;
case 'select_all':

View File

@@ -309,7 +309,7 @@ define([
let x = 0;
let y = 0;
let position = new Layout.Position({
let positionFinder = new Layout.Position({
container: mapContainer[0],
center: sourceSystem[0],
loops: 4,
@@ -317,7 +317,7 @@ define([
debug: false
});
let dimensions = position.findNonOverlappingDimensions(1, 16);
let dimensions = positionFinder.findNonOverlappingDimensions(1, 16);
if(dimensions.length){
//... empty map space found
x = dimensions[0].left;

View File

@@ -40,18 +40,48 @@ define(() => {
*/
this._getElementDimension = (element) => {
let dim = null;
if(element){
// add "gap" to a and b in order to have some space around elements
dim = {
left: element.style.left ? parseInt(element.style.left, 10) : 0,
top: element.style.top ? parseInt(element.style.top, 10) : 0,
a: parseInt((element.offsetWidth / 2).toString(), 10) + this._config.gapX,
b: parseInt((element.offsetHeight / 2).toString(), 10) + this._config.gapY,
width: element.offsetWidth,
height: element.offsetHeight
};
let left = 0;
let top = 0;
let a = 0;
let b = 0;
let width = this._config.newElementWidth;
let height = this._config.newElementHeight;
if(Array.isArray(element)){
// xy coordinates
let point = [
element[0] ? parseInt(element[0], 10) : 0,
element[1] ? parseInt(element[1], 10) : 0
];
if(this._config.grid){
point = this._transformPointToGrid(point);
}
left = point[0];
top = point[1];
a = this._config.gapX ;
b = this._config.gapY ;
}else if(element){
// DOM element
left = element.style.left ? parseInt(element.style.left, 10) : 0;
top = element.style.top ? parseInt(element.style.top, 10) : 0;
a = parseInt((element.offsetWidth / 2).toString(), 10) + this._config.gapX;
b = parseInt((element.offsetHeight / 2).toString(), 10) + this._config.gapY;
width = element.offsetWidth;
height = element.offsetHeight;
}
return dim;
// add "gap" to a and b in order to have some space around elements
return {
left: left,
top: top,
a: a,
b: b,
width: width,
height: height
};
};
/**
@@ -96,6 +126,18 @@ define(() => {
return dimensions;
};
/**
* transform a x/y point into a x/y point that snaps to grid
* @param point
* @returns {*}
* @private
*/
this._transformPointToGrid = (point) => {
point[0] = Math.floor(point[0] / this._config.grid[0]) * this._config.grid[0];
point[1] = Math.floor(point[1] / this._config.grid[1]) * this._config.grid[1];
return point;
};
/**
* Transform a x/y coordinate into a 2D element with width/height
* @param centerDimension
@@ -136,8 +178,9 @@ define(() => {
// transform to grid coordinates (if grid snapping is enabled) ------------------------------------
if(this._config.grid){
left = Math.floor(left / this._config.grid[0]) * this._config.grid[0];
top = Math.floor(top / this._config.grid[1]) * this._config.grid[1];
let point = this._transformPointToGrid([left, top]);
left = point[0];
top = point[1];
}
dim = {
@@ -239,14 +282,30 @@ define(() => {
steps = steps || 1;
loops = loops || 1;
if(loops === 1){
// check center element
let centerDimension = this._getElementDimension(this._config.center);
if (!this._isOverlapping(centerDimension, dimensionContainer, allDimensions)) {
dimensions.push({
left: centerDimension.left,
top: centerDimension.top,
width: centerDimension.width,
height: centerDimension.height
});
// render debug element
this._showDebugElement(centerDimension, 0);
maxResults--;
}
}
// increase the "gab" between center element and potential found dimensions...
// ... for each recursive loop call, to get an elliptical cycle beyond
// -> defaultGab for 1. loop, ..., defaultGab + 3 * defaultGab/ 2 for 3. loop
this._config.gapX = this._config.defaultGapX + loops * Math.round(this._config.defaultGapX / 2);
this._config.gapY = this._config.defaultGapY + loops * Math.round(this._config.defaultGapY / 2);
this._config.gapX = this._config.defaultGapX + (loops - 1) * 20;
this._config.gapY = this._config.defaultGapY + (loops - 1) * 20;
let centerDimension = this._getElementDimension(this._config.center);
do {
while(maxResults > 0 && start < end){
// get all potential coordinates on an eclipse around a given "centerElementDimension"
let coordinate = this._getEllipseCoordinates(centerDimension, end);
// transform relative x/y coordinate into a absolute 2D area
@@ -264,7 +323,7 @@ define(() => {
maxResults--;
}
end -= angle;
} while (maxResults > 0 && start < end);
}
if(maxResults > 0 && loops < this._config.loops){
loops++;

View File

@@ -10,6 +10,7 @@ define([
'bootbox',
'app/map/util',
'app/map/system',
'app/map/layout',
'app/map/magnetizing',
'app/map/scrollbar',
'dragToSelect',
@@ -17,7 +18,7 @@ define([
'app/map/contextmenu',
'app/map/overlay',
'app/map/local'
], function($, Init, Util, Render, bootbox, MapUtil, System, MagnetizerWrapper) {
], function($, Init, Util, Render, bootbox, MapUtil, System, Layout, MagnetizerWrapper) {
'use strict';
@@ -2661,6 +2662,24 @@ define([
switch(action){
case 'add_system':
// add new system dialog
let grid = [MapUtil.config.mapSnapToGridDimension, MapUtil.config.mapSnapToGridDimension];
let positionFinder = new Layout.Position({
container: currentMapElement[0],
center: [position.x, position.y],
loops: 5,
defaultGapX: 10,
defaultGapY: 10,
grid: currentMapElement.hasClass(MapUtil.config.mapGridClass) ? grid : false,
debug: false
});
let dimensions = positionFinder.findNonOverlappingDimensions(1, 8);
if(dimensions.length){
position.x = dimensions[0].left;
position.y = dimensions[0].top;
}
showNewSystemDialog(currentMap, {position: position});
break;
case 'select_all':

View File

@@ -309,7 +309,7 @@ define([
let x = 0;
let y = 0;
let position = new Layout.Position({
let positionFinder = new Layout.Position({
container: mapContainer[0],
center: sourceSystem[0],
loops: 4,
@@ -317,7 +317,7 @@ define([
debug: false
});
let dimensions = position.findNonOverlappingDimensions(1, 16);
let dimensions = positionFinder.findNonOverlappingDimensions(1, 16);
if(dimensions.length){
//... empty map space found
x = dimensions[0].left;