mirror of
https://github.com/placeAtlas/atlas.git
synced 2024-09-27 12:39:18 +02:00
Improvements on validator
Should now detect conflicts/overlaps and insufficient paths
This commit is contained in:
parent
ab00863b73
commit
347d2f9dff
3 changed files with 142 additions and 58 deletions
|
@ -1336,11 +1336,15 @@ .period-group {
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.period-group[data-active="true"] {
|
.period-group[data-status="active"] {
|
||||||
border-color: lime;
|
border-color: lime;
|
||||||
box-shadow: 0px 0px lime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.period-group[data-status="error"] {
|
||||||
|
border-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.period-group input {
|
.period-group input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
191
web/_js/draw.js
191
web/_js/draw.js
|
@ -36,6 +36,7 @@ var exportCloseButton = document.getElementById("exportCloseButton");
|
||||||
var exportBackButton = document.getElementById("exportBackButton")
|
var exportBackButton = document.getElementById("exportBackButton")
|
||||||
|
|
||||||
var path = [];
|
var path = [];
|
||||||
|
var center = [];
|
||||||
|
|
||||||
var pathWithPeriods = []
|
var pathWithPeriods = []
|
||||||
var periodGroupElements = []
|
var periodGroupElements = []
|
||||||
|
@ -116,6 +117,8 @@ function initDraw(){
|
||||||
if(path.length >= 3){
|
if(path.length >= 3){
|
||||||
finishButton.disabled = false;
|
finishButton.disabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updatePath()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -229,7 +232,7 @@ function initDraw(){
|
||||||
|
|
||||||
pathWithPeriodsTemp = pathWithPeriods.concat()
|
pathWithPeriodsTemp = pathWithPeriods.concat()
|
||||||
|
|
||||||
console.log(pathWithPeriodsTemp)
|
// console.log(pathWithPeriodsTemp)
|
||||||
|
|
||||||
// calculateCenter(path)
|
// calculateCenter(path)
|
||||||
|
|
||||||
|
@ -267,31 +270,6 @@ function initDraw(){
|
||||||
textarea.select();
|
textarea.select();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function calculateCenter(path){
|
|
||||||
|
|
||||||
var area = 0,
|
|
||||||
i,
|
|
||||||
j,
|
|
||||||
point1,
|
|
||||||
point2,
|
|
||||||
x = 0,
|
|
||||||
y = 0,
|
|
||||||
f;
|
|
||||||
|
|
||||||
for (i = 0, j = path.length - 1; i < path.length; j=i,i++) {
|
|
||||||
point1 = path[i];
|
|
||||||
point2 = path[j];
|
|
||||||
f = point1[0] * point2[1] - point2[0] * point1[1];
|
|
||||||
area += f;
|
|
||||||
x += (point1[0] + point2[0]) * f;
|
|
||||||
y += (point1[1] + point2[1]) * f;
|
|
||||||
}
|
|
||||||
area *= 3;
|
|
||||||
|
|
||||||
return [Math.floor(x / area)+0.5, Math.floor(y / area)+0.5];
|
|
||||||
}
|
|
||||||
|
|
||||||
function undo(){
|
function undo(){
|
||||||
if(path.length > 0 && drawing){
|
if(path.length > 0 && drawing){
|
||||||
undoHistory.push(path.pop());
|
undoHistory.push(path.pop());
|
||||||
|
@ -447,7 +425,7 @@ function initDraw(){
|
||||||
var [before, after] = period.split('-')
|
var [before, after] = period.split('-')
|
||||||
startPeriodField.value = before
|
startPeriodField.value = before
|
||||||
endPeriodField.value = after
|
endPeriodField.value = after
|
||||||
console.log(before, after)
|
// console.log(before, after)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -459,27 +437,26 @@ function initDraw(){
|
||||||
pathWithPeriods = Object.entries(path)
|
pathWithPeriods = Object.entries(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(pathWithPeriods)
|
|
||||||
|
|
||||||
zoom = 4;
|
|
||||||
|
|
||||||
zoomOrigin = [
|
|
||||||
innerContainer.clientWidth/2 - entry.center[0]* zoom,// + container.offsetLeft
|
|
||||||
innerContainer.clientHeight/2 - entry.center[1]* zoom// + container.offsetTop
|
|
||||||
];
|
|
||||||
|
|
||||||
scaleZoomOrigin = [
|
|
||||||
2000/2 - entry.center[0],// + container.offsetLeft
|
|
||||||
2000/2 - entry.center[1]// + container.offsetTop
|
|
||||||
];
|
|
||||||
|
|
||||||
applyView();
|
|
||||||
} else {
|
} else {
|
||||||
pathWithPeriods.push([defaultPeriod, []])
|
pathWithPeriods.push([defaultPeriod, []])
|
||||||
}
|
}
|
||||||
|
|
||||||
initPeriodGroups()
|
initPeriodGroups()
|
||||||
|
|
||||||
|
zoom = 4;
|
||||||
|
|
||||||
|
zoomOrigin = [
|
||||||
|
innerContainer.clientWidth/2 - center[0] * zoom,// + container.offsetLeft
|
||||||
|
innerContainer.clientHeight/2 - center[1] * zoom// + container.offsetTop
|
||||||
|
];
|
||||||
|
|
||||||
|
scaleZoomOrigin = [
|
||||||
|
2000/2 - center[0],// + container.offsetLeft
|
||||||
|
2000/2 - center[1]// + container.offsetTop
|
||||||
|
];
|
||||||
|
|
||||||
|
applyView();
|
||||||
|
|
||||||
document.addEventListener('timeupdate', (event) => {
|
document.addEventListener('timeupdate', (event) => {
|
||||||
renderBackground()
|
renderBackground()
|
||||||
updatePeriodGroups()
|
updatePeriodGroups()
|
||||||
|
@ -492,8 +469,32 @@ function initDraw(){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function calculateCenter(path){
|
||||||
|
|
||||||
|
var area = 0,
|
||||||
|
i,
|
||||||
|
j,
|
||||||
|
point1,
|
||||||
|
point2,
|
||||||
|
x = 0,
|
||||||
|
y = 0,
|
||||||
|
f;
|
||||||
|
|
||||||
|
for (i = 0, j = path.length - 1; i < path.length; j=i,i++) {
|
||||||
|
point1 = path[i];
|
||||||
|
point2 = path[j];
|
||||||
|
f = point1[0] * point2[1] - point2[0] * point1[1];
|
||||||
|
area += f;
|
||||||
|
x += (point1[0] + point2[0]) * f;
|
||||||
|
y += (point1[1] + point2[1]) * f;
|
||||||
|
}
|
||||||
|
area *= 3;
|
||||||
|
|
||||||
|
return [Math.floor(x / area)+0.5, Math.floor(y / area)+0.5];
|
||||||
|
}
|
||||||
|
|
||||||
function isOnPeriod(start = parseInt(startPeriodField.value), end = parseInt(endPeriodField.value), current = period) {
|
function isOnPeriod(start = parseInt(startPeriodField.value), end = parseInt(endPeriodField.value), current = period) {
|
||||||
console.log(start, end, current, current >= start && current <= end)
|
// console.log(start, end, current, current >= start && current <= end)
|
||||||
return current >= start && current <= end
|
return current >= start && current <= end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,7 +503,7 @@ function initPeriodGroups() {
|
||||||
periodGroupElements = []
|
periodGroupElements = []
|
||||||
periodGroups.textContent = ''
|
periodGroups.textContent = ''
|
||||||
|
|
||||||
console.log(pathWithPeriods)
|
// console.log(pathWithPeriods)
|
||||||
|
|
||||||
pathWithPeriods.forEach(([period, path], index) => {
|
pathWithPeriods.forEach(([period, path], index) => {
|
||||||
let periodGroupEl = periodGroupTemplate.cloneNode(true)
|
let periodGroupEl = periodGroupTemplate.cloneNode(true)
|
||||||
|
@ -530,12 +531,12 @@ function initPeriodGroups() {
|
||||||
startPeriodEl.addEventListener('input', event => {
|
startPeriodEl.addEventListener('input', event => {
|
||||||
timelineSlider.value = parseInt(event.target.value)
|
timelineSlider.value = parseInt(event.target.value)
|
||||||
updateTime(parseInt(event.target.value))
|
updateTime(parseInt(event.target.value))
|
||||||
console.log(parseInt(event.target.value))
|
// console.log(parseInt(event.target.value))
|
||||||
})
|
})
|
||||||
endPeriodEl.addEventListener('input', event => {
|
endPeriodEl.addEventListener('input', event => {
|
||||||
timelineSlider.value = parseInt(event.target.value)
|
timelineSlider.value = parseInt(event.target.value)
|
||||||
updateTime(parseInt(event.target.value))
|
updateTime(parseInt(event.target.value))
|
||||||
console.log(parseInt(event.target.value))
|
// console.log(parseInt(event.target.value))
|
||||||
})
|
})
|
||||||
periodDeleteEl.addEventListener('click', () => {
|
periodDeleteEl.addEventListener('click', () => {
|
||||||
if (pathWithPeriods.length === 1) return
|
if (pathWithPeriods.length === 1) return
|
||||||
|
@ -555,7 +556,7 @@ function initPeriodGroups() {
|
||||||
periodVisibilityEl
|
periodVisibilityEl
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
console.log(periodGroupTemplate)
|
// console.log(periodGroupTemplate)
|
||||||
updatePeriodGroups()
|
updatePeriodGroups()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -564,6 +565,7 @@ function updatePeriodGroups() {
|
||||||
var pathToActive = []
|
var pathToActive = []
|
||||||
var lastActivePathIndex
|
var lastActivePathIndex
|
||||||
var currentActivePathIndex
|
var currentActivePathIndex
|
||||||
|
var currentActivePathIndexes = []
|
||||||
|
|
||||||
periodGroupElements.forEach((elements, index) => {
|
periodGroupElements.forEach((elements, index) => {
|
||||||
let {
|
let {
|
||||||
|
@ -574,6 +576,7 @@ function updatePeriodGroups() {
|
||||||
} = elements
|
} = elements
|
||||||
|
|
||||||
if (periodGroupEl.dataset.active === "true") lastActivePathIndex = index
|
if (periodGroupEl.dataset.active === "true") lastActivePathIndex = index
|
||||||
|
periodGroupEl.dataset.active = ""
|
||||||
|
|
||||||
if (isOnPeriod(
|
if (isOnPeriod(
|
||||||
parseInt(startPeriodEl.value),
|
parseInt(startPeriodEl.value),
|
||||||
|
@ -582,9 +585,8 @@ function updatePeriodGroups() {
|
||||||
)) {
|
)) {
|
||||||
pathToActive = pathWithPeriods[index][1]
|
pathToActive = pathWithPeriods[index][1]
|
||||||
currentActivePathIndex = index
|
currentActivePathIndex = index
|
||||||
periodGroupEl.dataset.active = true
|
currentActivePathIndexes.push(index)
|
||||||
} else {
|
periodGroupEl.dataset.active = "true"
|
||||||
periodGroupEl.dataset.active = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pathWithPeriods[index][0] = formatPeriod(
|
pathWithPeriods[index][0] = formatPeriod(
|
||||||
|
@ -595,6 +597,16 @@ function updatePeriodGroups() {
|
||||||
})
|
})
|
||||||
|
|
||||||
periodsStatus.textContent = ""
|
periodsStatus.textContent = ""
|
||||||
|
|
||||||
|
// if (currentActivePathIndexes.length > 1) {
|
||||||
|
// periodsStatus.textContent = "Collision detected! Please resolve it."
|
||||||
|
// currentActivePathIndexes.forEach(index => {
|
||||||
|
// periodGroupElements[index].periodGroupEl.dataset.status = "error"
|
||||||
|
// })
|
||||||
|
// currentActivePathIndex = undefined
|
||||||
|
// }
|
||||||
|
|
||||||
|
console.log(lastActivePathIndex)
|
||||||
if (lastActivePathIndex !== undefined) {
|
if (lastActivePathIndex !== undefined) {
|
||||||
if (lastActivePathIndex === currentActivePathIndex) {
|
if (lastActivePathIndex === currentActivePathIndex) {
|
||||||
// just update the path
|
// just update the path
|
||||||
|
@ -605,11 +617,10 @@ function updatePeriodGroups() {
|
||||||
),
|
),
|
||||||
path
|
path
|
||||||
]
|
]
|
||||||
console.log(pathWithPeriods[currentActivePathIndex])
|
updatePath()
|
||||||
} else if (currentActivePathIndex === undefined) {
|
} else if (currentActivePathIndex === undefined) {
|
||||||
pathWithPeriods[lastActivePathIndex][1] = path
|
pathWithPeriods[lastActivePathIndex][1] = path
|
||||||
updatePath([])
|
updatePath([])
|
||||||
periodsStatus.textContent = "No paths available on this period!"
|
|
||||||
} else {
|
} else {
|
||||||
// switch the path
|
// switch the path
|
||||||
pathWithPeriods[lastActivePathIndex][1] = path
|
pathWithPeriods[lastActivePathIndex][1] = path
|
||||||
|
@ -642,13 +653,83 @@ function formatPeriod(start, end) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function updatePath(newPath = path) {
|
function updatePath(newPath = path) {
|
||||||
|
console.log('updatePath')
|
||||||
path = newPath
|
path = newPath
|
||||||
|
center = calculateCenter(path)
|
||||||
render(path)
|
render(path)
|
||||||
finishButton.disabled = path.length;
|
|
||||||
undoButton.disabled = path.length == 0; // Maybe make it undo the cancel action in the future
|
undoButton.disabled = path.length == 0; // Maybe make it undo the cancel action in the future
|
||||||
undoHistory = []
|
undoHistory = []
|
||||||
// TODO: Able to click finish when one period has it.
|
|
||||||
finishButton.disabled = path.length < 3;
|
if (path.length === 0) {
|
||||||
|
periodsStatus.textContent = "No paths available on this period!"
|
||||||
|
}
|
||||||
|
|
||||||
|
let [conflicts, invalidPaths, allErrors] = getErrors()
|
||||||
|
|
||||||
|
if (allErrors.length > 0) {
|
||||||
|
periodsStatus.textContent = `Problems detected. Please check the groups indicated by red.`
|
||||||
|
if (conflicts.length > 0) periodsStatus.textContent += `\nConflicts on ${conflicts.join(', ')}.`
|
||||||
|
if (invalidPaths.length > 0) periodsStatus.textContent += `\nInsufficient paths on ${invalidPaths.join(', ')}.`
|
||||||
|
allErrors.forEach(index => {
|
||||||
|
periodGroupElements[index].periodGroupEl.dataset.status = "error"
|
||||||
|
})
|
||||||
|
if (conflicts.length > 0) currentActivePathIndex = undefined
|
||||||
|
finishButton.disabled = true
|
||||||
|
} else {
|
||||||
|
periodsStatus.textContent = ``
|
||||||
|
finishButton.disabled = false
|
||||||
|
periodGroupElements.forEach((elements, index) => {
|
||||||
|
let {
|
||||||
|
periodGroupEl,
|
||||||
|
startPeriodEl,
|
||||||
|
endPeriodEl,
|
||||||
|
periodVisibilityEl
|
||||||
|
} = elements
|
||||||
|
if (periodGroupEl.dataset.active === "true") periodGroupEl.dataset.status = "active"
|
||||||
|
else periodGroupEl.dataset.status = ""
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function getConflicts() {
|
||||||
|
|
||||||
|
let conflicts = new Set()
|
||||||
|
|
||||||
|
for (let i = pathWithPeriods.length - 1; i > 0; i--) {
|
||||||
|
for (let j = 0; j < i; j++) {
|
||||||
|
let [start1, end1] = parsePeriod(pathWithPeriods[i][0])
|
||||||
|
let [start2, end2] = parsePeriod(pathWithPeriods[j][0])
|
||||||
|
if (
|
||||||
|
(start2 <= start1 && start1 <= end2) ||
|
||||||
|
(start2 <= end1 && end1 <= end2) ||
|
||||||
|
(start1 <= start2 && start2 <= end1) ||
|
||||||
|
(start1 <= end2 && end2 <= end1)
|
||||||
|
) {
|
||||||
|
conflicts.add(i)
|
||||||
|
conflicts.add(j)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conflicts = [...conflicts]
|
||||||
|
|
||||||
|
return conflicts
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function getErrors() {
|
||||||
|
let conflicts = getConflicts()
|
||||||
|
let invalidPaths = []
|
||||||
|
|
||||||
|
pathWithPeriods.forEach(([period, path], i) => {
|
||||||
|
if (path.length < 3) invalidPaths.push(i)
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('conflicts', conflicts)
|
||||||
|
console.log('invalid paths', invalidPaths)
|
||||||
|
|
||||||
|
return [conflicts, invalidPaths, [...new Set([...conflicts, ...invalidPaths])]]
|
||||||
}
|
}
|
||||||
|
|
||||||
// function compressPeriod(periodsString) {
|
// function compressPeriod(periodsString) {
|
||||||
|
|
|
@ -172,7 +172,6 @@ async function updateTime(currentPeriod) {
|
||||||
centerChosen = Object.values(atlasAll[atlasIndex].center)[chosenIndex]
|
centerChosen = Object.values(atlasAll[atlasIndex].center)[chosenIndex]
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(pathChosen)
|
|
||||||
if (pathChosen === undefined) continue
|
if (pathChosen === undefined) continue
|
||||||
|
|
||||||
atlas.push({
|
atlas.push({
|
||||||
|
|
Loading…
Reference in a new issue