How to check is two lines intersect/overlap on a grid? - objective-c

This is a rather trivial algorithmic problem but my implementation leaves speed and simplicity to be desired. I've got two Line objects which each hold two Coordinate structs in the form of {unsigned int x, unsigned int y}. This first Coordinate holds the position of the beginning of the line and the second Coordinate, the end of it. Assuming that Lines can only be vertical or horizontal on the grid, how can I check when two lines overlap parallelly or intersect perpendicularly. Preferably this is implemented as a method in Line:
- (BOOL)intersectsLine:(Line)otherLine;
THANKS!

Since we're talking only about horizontal or vertical lines, the first step I'd take it checking whether or not the lines have the same orientation.
typedef (NSUInteger, LineOrientation) {
HorizontalLine = 0,
VerticalLine = 1
};
So, given a line with two points...
LineOrientation line1orientation;
LineOrientation line2orientation;
if (a.x1 == a.x2) {
line1orientation = HorizontalLine;
} else {
line1orientation = VerticalLine;
}
if (b.x1 == b.x2) {
line2orientation = VerticalLine;
} else {
line2orientation = Horizontal;
}
Now we need to check whether they're both horizontal, both vertical, or one of each, and then test particular values:
if (line1orientation == line2orientation) {
if (line1orientation == VerticalLine) {
if (a.x1 != b.x1) {
return false;
} else {
if (a.y1 < a.y2) {
return ((b.y1 > a.y1 && b.y1 < a.y2) ||
(b.y2 > a.y1 && b.y2 < a.y2));
} else {
return ((b.y1 > a.y2 && b.y1 < a.y1) ||
(b.y2 > a.y2 && b.y2 < a.y1));
}
}
} else {
if (a.y1 != b.y1) {
return false;
} else {
if (a.x1 < a.x2) {
return ((b.x1 > a.x1 && b.x1 < a.x2) ||
(b.x2 > a.x1 && b.x2 < a.x2));
} else {
return ((b.x1 > a.x2 && b.x1 < a.x1) ||
(b.x2 > a.x2 && b.x2 < a.x1));
}
}
}
} else {
if (line1orientation == VerticalLine) {
if (a.y1 < a.y2) {
return (((b.y1 > a.y1) && (b.y1 < a.y2)) && ((b.x1 > a.x1 && b.x2
< a.x1) || (b.x2 > a.x1 && b.x1 < a.x1)));
} else {
return (((b.y1 > a.y2) && (b.y1 < a.y1)) && ((b.x1 > a.x1 && b.x2
< a.x1) || (b.x2 > a.x1 && b.x1 < a.x1)))
}
} else {
if (a.x1 < a.x2) {
return (((b.x1 > a.x1) && (b.x1 < a.x2)) && ((b.y1 > a.y1 && b.y2
< a.y2) || (b.y2 > a.y1 && b.y1 < a.y1)));
} else {
return (((b.x1 > a.x2) && (b.x1 < a.x1)) && ((b.y1 > a.y1 && b.y2
< a.y2) || (b.y2 > a.y1 && b.y1 < a.y1)));
}
}
This could be more efficient if you start with a check to make sure the lines aren't the same line.

Related

add game over to javascript game

let canvas = document.getElementById("snake");
let context = canvas.getContext("2d"); //....
let box = 42;
let snake = [];
snake[0] ={
x: 8 * box,
y: 8 * box
}
let direction = "rechts";
let food ={
x: Math.floor(Math.random() * 15 + 1) * box,
y: Math.floor(Math.random() * 15 + 1) * box
}
function maakachtergrond(){
context.fillStyle = "#FFEAF0";
context.fillRect(0, 0, 16*box, 16*box);
}
function maakslang (){
for(i = 0; i < snake.length; i++){
context.fillStyle = "#FFFFFF";
context.fillRect(snake[i].x, snake[i].y, box, box);
}
}
function heteten (){
context.fillStyle = "#010101";
context.fillRect(food.x, food.y, box, box);
}
document.addEventListener('keydown', update);
function update(event){
if(event.keyCode == 37 && direction != 'rechts') direction = 'left';
if(event.keyCode == 38 && direction != 'down') direction = 'up';
if(event.keyCode == 39 && direction != 'left') direction = 'rechts';
if(event.keyCode == 40 && direction != 'up') direction = 'down';
}
function starthetspel(){
if(snake[0].x > 15*box && direction == "rechts") snake[0].x = 0;
if(snake[0].x < 0 && direction == 'left') snake[0].x = 16 * box;
if(snake[0].y > 15*box && direction == "down") snake[0].y = 0;
if(snake[0].y < 0 && direction == 'up') snake[0].y = 16 * box;
for(i = 1; i < snake.length; i++){
if(snake[0].x == snake[i].x && snake[0].y == snake[i].y){
clearInterval(jogo);
}
}
maakachtergrond();
maakslang();
heteten();
let snakeX = snake[0].x;
let snakeY = snake[0].y;
if(direction == "rechts") snakeX += box;
if(direction == "left") snakeX -= box;
if (direction == "up") snakeY -= box;
if(direction == "down") snakeY += box;
if(snakeX != food.x || snakeY != food.y){
snake.pop();
}else{
food.x = Math.floor(Math.random() * 15 +1) * box;
food.y = Math.floor(Math.random() * 15 +1) * box;
}
let newHead ={
x: snakeX,
y: snakeY
}
snake.unshift(newHead);
}
let jogo = setInterval(starthetspel, 100);
how to add a game over if i touch the edge of the game. For now the snake just respawn on the other side of the game, but i would prefer it to make it a game over
Maybe something like
if fillStyle = "#FFEAF0"
window.alert(game over);
and allowing the snake to go outside his gamefield, but I don't know how. It's for a small asignment I got from my teacher and maybe someone can help me out.

If, if else, else doesn't work in cypress

I have the following code, but block with else if doesn't work,
how can I change this code, to make the if else block work?
cy.get('#cards-list').then((list) => {
const valueFormList = list.find(`a:contains('${nameForSite}')`)
const nextArrow = list.find(`li.pagination-next`)
if (valueFormList.length > 0 && nextArrow.length > 0){
cy.get(`a:contains('${nameForSite}')`).as('card')
} else if (valueFormList.length < 0 && nextArrow.length > 0) {
cy.get('li.pagination-next').click()
cy.wait(200)
cy.findCardOnFacebook(nameForSite)
} else {
cy.get('h4.learning-opportunities-title').should('contain', 'Learning')
}
})
The error is because of the condition valueFormList.length < 0. The length can never be less than 0. Either it can be zero or more than zero.
cy.get('#cards-list').then((list) => {
const valueFormList = list.find(`a:contains('${nameForSite}')`)
const nextArrow = list.find(`li.pagination-next`)
if (valueFormList.length == 0 && nextArrow.length > 0) {
cy.get('li.pagination-next').click()
cy.wait(200)
cy.findCardOnFacebook(nameForSite)
} else if (valueFormList.length > 0 && nextArrow.length > 0) {
cy.get(`a:contains('${nameForSite}')`).as('card')
} else {
cy.get('h4.learning-opportunities-title').should('contain', 'Learning')
}
})

React native run useState/force rerender inside worklet funtion

I'm calling the useAnimatedScrollHandler hook from react-native-reanimated to handle my onScroll function on an Animated.ScrollView. This hook works as expected but I now want to disable a custom button (My FlatButton) based on the currentIndex which is a sharedValue. But when the sharedValue changes the screen doesn't get rerendered, because the state doesn't change so the look of my button remains the same.
Is there a way to force a rerender inside of a worklet, or is it possible to use useState to force a rerender from inside a worklet?
const scrollHandler = useAnimatedScrollHandler((event) => {
translationX.value = event.contentOffset.x
if (event.contentOffset.x < width * 0.5 && currentIndex.value != 0) {
currentIndex.value = 0
} else if (
event.contentOffset.x > width * 0.5 &&
event.contentOffset.x < width * 1.5 &&
currentIndex.value != 1
) {
currentIndex.value = 1
} else if (event.contentOffset.x > width * 1.5 && currentIndex.value != 2) {
currentIndex.value = 2
}
})
<FlatButton
label="Next"
disabled={
(currentIndex.value == 0 && (!firstName || !lastName)) ||
(currentIndex.value == 1 && (!dateOfBirth || !sex)) ||
(currentIndex.value == 2 &&
(!streetNumber || !postalCode || !city || !state || !country))
}
onPress={() => {
if (currentIndex.value == 0) {
scrollRef.current
?.getNode()
.scrollTo({ x: width, animated: true })
} else if (currentIndex.value == 1) {
scrollRef.current?.getNode().scrollToEnd({ animated: true })
}
}}
/>
I just found out that reanimated offers the function runOnJS which makes it possible to run a javscript function like setState inside a worklet. So just create a wrapper function, like in my case toggleIndex in which you interact with your state and call this function inside runOnJS from your worklet.
const [currentIndex, setCurrentIndex] = useState(0)
const toggleIndex = (index: number) => {
setCurrentIndex(index)
}
const scrollHandler = useAnimatedScrollHandler((event) => {
translationX.value = event.contentOffset.x
if (event.contentOffset.x < width * 0.5 && currentIndex != 0) {
runOnJS(toggleIndex)(0)
} else if (
event.contentOffset.x > width * 0.5 &&
event.contentOffset.x < width * 1.5 &&
currentIndex != 1
) {
runOnJS(toggleIndex)(1)
} else if (event.contentOffset.x > width * 1.5 && currentIndex != 2) {
runOnJS(toggleIndex)(2)
}
})

dgrid custom sort with secondary sort column

I'm currently using a custom sort function on a dgrid (pasted below). It doesn't change sorting drastically, just sorts one particular column uniquely and sorts the others case-insensitive. I'd like to add a secondary sort by a column named "scheduled" to be added to the sort when any other column is sorted. I'm just not sure how to go about it. I've seen how to override the sort to sort by two columns, but not when a custom sort is in play. The secondary sort would always be there, not matter what other column is clicked.
For reference I'm running dojo 1.10 and dgrid 1.0. Data is coming from a RequestMemory DStore and I'd really rather this sort happen on the grid rather than back at the store level. Any help would be appreciated.
currGrid.on('dgrid-sort', function (event) {
event.preventDefault();
var sort = event.sort[0];
currGrid.set('sort', function (a, b) {
if (sort.property == "thisField") {
//special sort for thisField
if (a[sort.property] !== 'undefined' && typeof a[sort.property] == "string") {
var colorA = a[sort.property].split("|");
var aValue = colorA[0].toLowerCase();
}
if (b[sort.property] !== 'undefined' && typeof b[sort.property] == "string") {
var colorB = b[sort.property].split("|");
var bValue = colorB[0].toLowerCase();
}
if (String(aValue) == String(bValue)) {
var result = 0;
} else if (dojo.string.trim(aValue) == "") {
var result = true ? 1 : -1;
} else if (dojo.string.trim(bValue) == "") {
var result = true ? -1 : 1;
} else {
var result = aValue > bValue ? 1 : -1;
}
return result * (sort.descending ? -1 : 1);
} else {
//Sort for all other fields same as always (except toLowerCase)
if (a[sort.property] !== 'undefined' && typeof a[sort.property] == "string") {
var aValue = a[sort.property].toLowerCase();
} else {
var aValue = "";
}
if (b[sort.property] !== 'undefined' && typeof b[sort.property] == "string") {
var bValue = b[sort.property].toLowerCase();
} else {
var bValue = "";
}
var result = aValue > bValue ? 1 : -1;
return result * (sort.descending ? -1 : 1);
}
});
currGrid.updateSortArrow(event.sort, true);
});
currGrid.startup();
You could do something like below.
currGrid.on('dgrid-sort', function (event) {
event.preventDefault();
var sortSet = [];
sortSet.push(event.sort[0]);
sortSet.push({property: "scheduled"});
currGrid.set('sort', function (a, b) {
var aValue, bValue, result = 0;
for(var i = 0; i < sortSet.length; i++){
var sort = sortSet[i];
if (sort.property == "thisField") {
//special sort for thisField
if (a[sort.property] !== 'undefined' && typeof a[sort.property] == "string") {
var colorA = a[sort.property].split("|");
aValue = colorA[0].toLowerCase();
}
if (b[sort.property] !== 'undefined' && typeof b[sort.property] == "string") {
var colorB = b[sort.property].split("|");
bValue = colorB[0].toLowerCase();
}
if (String(aValue) == String(bValue)) {
result = 0;
} else if (dojo.string.trim(aValue) == "") {
result = true ? 1 : -1;
} else if (dojo.string.trim(bValue) == "") {
result = true ? -1 : 1;
} else {
result = aValue > bValue ? 1 : -1;
}
return result * (sort.descending ? -1 : 1);
} else {
//Sort for all other fields same as always (except toLowerCase)
if (a[sort.property] !== 'undefined' && typeof a[sort.property] == "string") {
aValue = a[sort.property].toLowerCase();
} else {
aValue = "";
}
if (b[sort.property] !== 'undefined' && typeof b[sort.property] == "string") {
bValue = b[sort.property].toLowerCase();
} else {
bValue = "";
}
//You need this check here
if(aValue != bValue){
result = aValue > bValue ? 1 : -1;
return result * (sort.descending ? -1 : 1);
}
}
}
return 0;
});
currGrid.updateSortArrow(event.sort, true);
});
currGrid.startup();
I have some concerns about your code, the variables result, aValue and bValue are all local within the if statement and yet they are being used outside the statement. It could result in wrong results if some other variables are defined with the same name in global space. So I have modified them.
So the second section you needed to check if aValue == bValue to return 0.

ExtJS 4 set background color to a cell

Is there a way in ExtJS 4 to add a background colour to the cells in the whole table, depending only on the value in the cell and not on the columns?
Add renderer to your column:
renderer: function (val, metadata, record) {
var backgroundColor = null;
if (val) {
if (val == 1) backgroundColor = "green";
if (val == 2) backgroundColor = "red";
}
metadata.style = 'background-color: ' + backgroundColor + ';';
return '';
}
Here is a working example: https://fiddle.sencha.com/fiddle/b73
This works for me...
renderer : function(value, meta) {
if(parseInt(value) > 0) {
meta.style = "background-color:green;";
} else {
meta.style = "background-color:red;";
}
}
Basicly what you want to do is:
Create 1 renderer for all columns:
columns:{
defaults: {
renderer: myrenderer
},
items:[
//your column definitions here...
]
}
The renderer is smth like this:
var myrenderer = function(value, metaData, record, rowIndex, colIndex, store, view) {
if (value >= 0 && value < 25) {
metaData.tdCls += 'x-change-cell-red';
} else if (value >= 25 && value < 50) {
metaData.tdCls += 'x-change-cell-orange';
} else if (value >= 50 && value < 75) {
metaData.tdCls += 'x-change-cell-yellow';
} else if (value >= 75 && value < 100) {
metaData.tdCls += 'x-change-cell-green';
} else if (value === 100){
metaData.tdCls +='x-change-cell-awesome-green';
}else {
metaData.tdCls += 'x-change-cell-violet';
}
return value + '%';
}