Write the relational algebra expression to find the manufacturers (maker) of printers which are not colour (color) printers - algebra

Product(model, maker, type)
PC(model, speed, ram, hd, price)
Laptop(model, speed, ram, hd, screen, price)
Printer(model, color, type, price)
so far iv got this: σ Printer = 'color' (Product join model = model Printer)
Some help please

You want to select your maker first, then you can join the product and printer table on model. After that put in your selection on Printer.color = false.
This code should work:
π maker (Product ⨝ π model (σ color = false (Printer)))

Related

Clingo: Compare String Literals by Order (Index)?

I have defined a color palette called tableau10 in Clingo:
tableau10(blue;orange;red;teal;green;yellow;purple;pink;brown;gray).
Is there a way to compare the colors by the order they appear in my color definition? (e.g., blue = 0, orange = 1, red = 2, ...)
My goal is to be able to claim things like blue < orange, blue < gray...
The predicate tableau10 is unordered. To do such comparisons you'd have to encode order in one way or another. You could for example assign numbers to the colors value(blue, 1). value(orange, 2). ... and compare the associated numbers when necessary, or you could write lessthan(blue, orange). lessthan(orange, red). ... lessthan(brown,gray). and also add the transitivity rule lessthan(A, C) :- lessthan(A, B), lessthan(B, C).

OrientDB Find vertex is linked with a list of another vertex

i am discovering OrientDB and i have a problem :
I have two vertex definition :
Product
Criterion
And one Edge definition:
- IsRelatedToEdge
Thanks to IsRelatedToEdge, I can link one product to many criterion
In my example, i have populated the database with 5 products
shoe-1
shoe-2
shoe-3
hat-1
hat-2
and 4 criterions :
blue
red
hat
shoe
Then I linked products with criterion this way:
shoe-1 <=> shoe
shoe-1 <=> blue
shoe-2 <=> shoe
shoe-2 <=> red
shoe-3 <=> shoe
shoe-3 <=> blue
hat-1 <=> shoe
hat-1 <=> blue
hat-2 <=> hat
hat-2 <=> red
so we have 2 blue shoe, 1 blue hat, 1 red shoe, 1 red hat.
I cannot figure out how to find all blue shoes.
EDIT : I have found a 'solution' but it doesn't looks good :
select from Product where
in('IsRelatedToEdge')[name="blue"].size() = 1 and
in('IsRelatedToEdge')[name="shoe"].size() = 1
IMO, the power of OrientDB lies in the graph abilities, and queries on a table/index do not really leverage this. I feel the best way to do this query is to get the shoe criterion, then get all of the products that have an edge to the criterion. From those products (ie all the shoes), you can now filter for ones that also have an edge to the blue criterion. One way to write this is as follows...
select *
from (select expand(both('IsRelatedToEdge')) from Criterion where name = 'Shoe')
let $blue_criterion = (select from Criterion where name = 'Blue')
where both('IsRelatedToEdge') contains $blue_criterion[0]
Taking the above thought process further though, you could consider rearranging your data for better/easier querying. For example, you could make a Hat and Shoe class that are both subclasses of Product. That way to query on shoes, you query against the Shoe vertex class only. Similarly, you can make different criterion subclass, such as Color. To get blue shoes with such a config, the query would like the following...
select *
from Shoes
let $blue_criterion = (select from Color where name = 'Blue')
where both('IsRelatedToEdge') contains $blue_criterion[0]
You could even make more specific edges to take this a step further.
After studying neRok'solutions, i came at this solutions:
select expand($result)
let
$crit1 = (select expand(out('IsRelatedToEdge')) from Criterion where name='blue'),
$crit2 = (select expand(out('IsRelatedToEdge')) from Criterion where name='shoe'),
$result = intersect($crit1, $crit2)
With this kind of query, I can add another criterion.
Imagine if we have anotehr criterion named adidas and i want to have all blue adidas shoes :
select expand($result)
let
$crit1 = (select expand(out('IsRelatedToEdge')) from Criterion where name='blue'),
$crit2 = (select expand(out('IsRelatedToEdge')) from Criterion where name='shoe'),
$crit3 = (select expand(out('IsRelatedToEdge')) from Criterion where name='adidas'),
$result = intersect($crit1, $crit2, $crit3)

How to find LINESTRINGs that touch in a begin/ending node

In PostGIS you can intersect two geometries using:
geometry ST_Intersection (geometry geomA, geometry geomB);
In my case both geomA and geomB are LINESTRING so ST_Intersection() returns a POINT geometry.
I want to know if the intersection occurs in a begin/end node (the geometries touch) or in the middle (the geometries intersect).
I can compare the (Point.X, Point.Y) with each ending node:
geomA.nodes(0) - geomA.nodes(len-1)
geomB.nodes(0) - geomB.nodes(len-1)
But is very complex. And I would like a simple solution.
There are 3 intersect cases.
Example 1: Two lines in a "L" shape intersect in an end node on both lines on the bottom left.
Example 2: Two lines in a "T" shape where the vertical line intersects in the middle of the horizontal line. In this case the vertical line end node touches a non-end node of the horizontal line.
Example 3: Two lines in a "X" shape. Intersection point isn't an end node for either line.
For my problem I'm only interested in finding the touching scenario like Example 2.
NOTE
This is the pseudo code I use now.
geomM, geomN Linestring
a, b, c, d, z Points.
(a,b) begin/end node for geomM ST_StartPoint(geom) and ST_EndPoint(geom)
(c,d) begin/end node for geomN
z = ST_Intersect(geomM, geomN)
SELECT geomM, geomN, z
FROM Table
WHERE
(A and not ( B or C or D))
OR (B and not ( A or C or D))
OR (C and not ( A or B or D))
OR (D and not ( A or B or C))
A, B, C, D replace ( a=z ) ( b=z ) ( c=z ) ( d=z )
This mean one node {a,b,c,d} is equal to intersection z. But only one
This return all "T" shape intersections.
You need the PostGIS function ST_Touches() here. The function returns true if the geometries touch on their boundaries, but false if they intersect. In terms of your examples, Example 1 and 2 return true, Example 3 returns false.
Relaxed solution
To select the IDs of all pairs of touching geometry(LINESTRING, xxx) records from a single table use this:
SELECT x.id AS idA, y.id AS idB
FROM my_table x
JOIN my_table y ON ST_Touches(y.the_geom, x.the_geom)
WHERE x.id < y.id;
(The WHERE clause avoids duplicate results like (132, 254) and (254, 132).)
Note that the linestrings can also touch on any of their non-node vertices. If you want to strictly follow Example 2 then you have to compare every point on every linestring against every point on all other linestrings, which is obviously going to be a very intensive operation. Example 2 is basically only feasible when you know that the linestrings are very short, preferably just straight lines.
Strict solution, straight lines only
If all LINESTRINGs are straight, i.e. composed of a starting and an ending node only, then this is your solution:
SELECT h.id AS touched, v.id AS touching, ST_Intersection(h.the_geom, v.the_geom) AS touch_point
FROM my_table h -- "horizontal" T bar, being touched
JOIN my_table v ON -- "vertical" T bar, touching
(
-- The "vertical" start node touches, but not on either of the "horizonal" nodes
ST_Equals(ST_Intersection(h.the_geom, v.the_geom), ST_StartPoint(v.the_geom))
AND NOT ST_Equals(ST_StartPoint(h.the_geom), ST_StartPoint(v.the_geom))
AND NOT ST_Equals(ST_EndPoint(h.the_geom), ST_StartPoint(v.the_geom))
) OR (
-- The "vertical" end node touches, but not on either of the "horizonal" nodes
ST_Equals(ST_Intersection(h.the_geom, v.the_geom), ST_EndPoint(v.the_geom))
AND NOT ST_Equals(ST_StartPoint(h.the_geom), ST_EndPoint(v.the_geom))
AND NOT ST_Equals(ST_EndPoint(h.the_geom), ST_EndPoint(v.the_geom))
);
All the requirements are checked in the JOIN ON clause. This will also return the location where the "vertical" bar of the T touches the "horizontal" bar. Note that the conditions are short-circuited when being evaluated and repeated calls to a function with the same input data are optimized to a single call.

World.QueryAABB giving incorrect results in libgdx

I'm trying to implement mouse selection for my game. When I QueryAABB it looks like it's treating objects much larger than they really are.
Here's what's going on in the image
The blue box is an actor containing a body that I'd like to select
The outline on the blue box is drawn by Box2DDebugRenderer
The mouse selects a region on the screen (white box), this is entirely graphical
The AABB is converted to meters and passed to QueryAABB
The callback was called for the blue box and turned it red
The green outline left behind is a separate body to check if my conversions were correct, this is not used for the actual selection process
It seems to be connected to my meter size, the larger it is, the more inaccurate the result is. At 1 meter = 1 pixel it works perfectly.
Meter conversions
val MetersToPixels = 160f
val PixelsToMeters = 1/MetersToPixels
def toMeters(n: Float) = n * PixelsToMeters
def toPixels(n: Float) = n * MetersToPixels
In the image I'm using MetersToPixels = 160f so the inaccuracy is more visible, but I really want MetersToPixels = 16f.
Relevant selection code
val x1 = selectPos.x
val y1 = selectPos.y
val x2 = getX
val y2 = getY + getHeight
val (l,r) =
if (x2 < x1)
(x2,x1)
else
(x1,x2)
val (b,t) =
if (y2 < y1)
(y2,y1)
else
(y1,y2)
world.QueryAABB(selectCallback, toMeters(l),toMeters(b), toMeters(r),toMeters(t))
This code is inside the act method of my CursorActor class. And selectPos represents the initial point where the use pressed down the left mouse button and getX and getY are Actor methods giving the current position. The next bit sorts them because they might be out of order. Then they are converted to meters because they are all in pixel units.
selectCallback: QueryCallback
override def reportFixture(fixture: Fixture): Boolean = {
fixture.getBody.getUserData match {
case selectable: Selectable =>
selected += selectable
true
case _ => true
}
}
Selectable is a trait that sets a boolean flag internally after the query which helps determines the color of the blue box. And selected is a mutable.HashSet[Selectable] defined inside of CursorActor.
Other things possibly worth noting
I'm new to libgdx and box2d.
The camera is scaled x2
My Box2DDebugRenderer uses the camera's combined matrix multiplied by MetersToPixels
From what I was able to gather, QueryAABB is naturally inaccurate for optimization. However, I've hit a roadblock with libgdx because it doesn't have any publicly visible function like b2testOverlap and from what I understand, there's no plan for there to be one any time soon.
I think my best solution would probably be to use jbox2d and pretend that libgdx's physics implementation doesn't exist.
Or as noone suggested I could add it to libgdx myself.
UPDATE
I decided to go with a simple solution of gathering the vertices from the fixture's shape and using com.badlogic.gdx.math.Intersector against the vertices of the selection. It works I guess. I may stop using QueryAABB all together if I decide to switch to using a sensor for the select box.

Intersecting Layers Returns Empty Collection Despite Visible Intersection

When I perform an intersection of a polygon I draw in OpenLayers and a postgis database layer, it seems that I am getting incorrect results.
Intersection works correctly on some layers. For instance, if I intersect a triangle with a layer of polygons that represent crop fields, I get the following:
The query my app generates to produce the above result is:
SELECT ST_AsText(ST_Intersection(%(geometries_0)s::geometry, %(geometry)s::geometry))
where geometries_0 is my triangle:
POLYGON((-104.84928345939991 40.518951354186285,-104.82319093011056 40.51953858115158,-104.83700967095314 40.50707521626648,-104.84928345939991 40.518951354186285))
and geometry is my layer of crop fields, as well-known text:
MULTIPOLYGON(((-104.841309611298 40.5075331998226,-104.84173356681 40.5069932245841,-104.842041204329 40.50640946683,-104.842224948796 40.5057962996657,-104.842280275816 40.5051688207073,-104.842205823049 40.5045424803865,-104.842003423773 40.5039327015263,-104.841678061729 40.5033544995574,-104.841237748411 40.502822112724,-104.840693325791 40.5023486513933,-104.840058199365 40.5019457751149,-104.839348008051 40.5016234053897,-104.838580239118 40.5013894812384,-104.837773797582 40.5012497635973,-104.836948540713 40.501207693373,-104.836124789073 40.5012643066572,-104.83532282616 40.5014182091969,-104.834562398965 40.5016656107496,-104.833862231727 40.5020004184754,-104.833239564888 40.5024143870601,-104.832709730574 40.5028973218633,-104.83228577506 40.5034373300773,-104.831978137541 40.5040211136997,-104.831794393074 40.5046342970926,-104.831739066055 40.5052617810515,-104.831813518821 40.5058881146554,-104.832015918097 40.5064978757385,-104.832341280141 40.5070760506105,-104.83278159346 40.5076084036796,-104.833326016079 40.5080818278834,-104.833961142505 40.5084846673069,-104.834671333819 40.5088070040565,-104.835439102753 40.5090409023397,-104.836245544289 40.5091806037522,-104.837070801158 40.5092226689759,-104.837894552799 40.5091660624086,-104.83869651571 40.509012177646,-104.839456942906 40.5087648031902,-104.840157110143 40.5084300292289,-104.840779776982 40.5080160977709,-104.841309611298 40.5075331998226)))
However, if I perform the same query with a different layer ("soils"), I get an empty result:
The query is the same:
SELECT ST_AsText(ST_Intersection(%(geometries_0)s::geometry, %(geometry)s::geometry))
with a polygon geometries_0 that should overlap:
POLYGON((-104.84627938530097 40.54511058649626,-104.83460641167578 40.545175808723876,-104.84070039055733 40.537283458057615,-104.84627938530097 40.54511058649626))
and a geometry layer representing soils, similar to the crop fields in the above query:
MULTIPOLYGON(((-104.939716 40.258166,-104.939775 40.258174,-104.939963 40.258159,-104.940159 40.258065,-104.940039 40.257671,-104.939917 40.25749,-104.939928 40.257419,-104.94003 40.257404,-104.940265 40.257641,-104.940632 40.257902,-104.940826 40.258061,-104.941051 40.258188,-104.941123 40.258235,-104.941205 40.258283,-104.941246 40.258275,-104.941287 40.258212,-104.941186 40.258094,-104.941186 40.258007,-104.941167 40.257921,-104.941105 40.257858,-104.941044 40.257786,-104.941045 40.257716,-104.941127 40.257676,-104.94122 40.257653,-104.94141 40.257731,-104.941559 40.257671,-104.941255 40.257181,-104.940857 40.256794,-104.940644 40.256478,-104.940319 40.255997,-104.940003 40.255728,-104.939676 40.255561,-104.939419 40.255544,-104.938895 40.255529,-104.938287 40.255512,-104.938046 40.255528,-104.937733 40.255549,-104.937322 40.255533,-104.937012 40.255577,-104.936947 40.255593,-104.936623 40.255774,-104.936581 40.255924,-104.93658 40.256042,-104.936661 40.256223,-104.93671 40.256436,-104.936842 40.256618,-104.937262 40.256753,-104.937662 40.256818,-104.937897 40.257,-104.938181 40.25745,-104.938374 40.257742,-104.938465 40.257931,-104.938782 40.258051,-104.939121 40.258092,-104.939439 40.258133,-104.939716 40.258166)))
I use the postgis ST_AsText function to convert database layers to well-known text, and I checked to make sure that all layers have the EPSG:4326 projection (using the Find_SRID function).
Why would one layer (crop fields) intersect correctly, and another (soils) not? I've tried the same query using geographies instead of geometries, with the same result.
It returns an empty collection because they don't intersect. In fact, they are 32 km away from each other.
SELECT ST_Intersects(A, B), ST_Distance(A, B)/1000 AS dist_km
FROM (
SELECT
'POLYGON((-104.84627938530097 40.54511058649626,-104.83460641167578 40.545175808723876,-104.84070039055733 40.537283458057615,-104.84627938530097 40.54511058649626))'::geography AS A,
'MULTIPOLYGON(((-104.939716 40.258166,-104.939775 40.258174,-104.939963 40.258159,-104.940159 40.258065,-104.940039 40.257671,-104.939917 40.25749,-104.939928 40.257419,-104.94003 40.257404,-104.940265 40.257641,-104.940632 40.257902,-104.940826 40.258061,-104.941051 40.258188,-104.941123 40.258235,-104.941205 40.258283,-104.941246 40.258275,-104.941287 40.258212,-104.941186 40.258094,-104.941186 40.258007,-104.941167 40.257921,-104.941105 40.257858,-104.941044 40.257786,-104.941045 40.257716,-104.941127 40.257676,-104.94122 40.257653,-104.94141 40.257731,-104.941559 40.257671,-104.941255 40.257181,-104.940857 40.256794,-104.940644 40.256478,-104.940319 40.255997,-104.940003 40.255728,-104.939676 40.255561,-104.939419 40.255544,-104.938895 40.255529,-104.938287 40.255512,-104.938046 40.255528,-104.937733 40.255549,-104.937322 40.255533,-104.937012 40.255577,-104.936947 40.255593,-104.936623 40.255774,-104.936581 40.255924,-104.93658 40.256042,-104.936661 40.256223,-104.93671 40.256436,-104.936842 40.256618,-104.937262 40.256753,-104.937662 40.256818,-104.937897 40.257,-104.938181 40.25745,-104.938374 40.257742,-104.938465 40.257931,-104.938782 40.258051,-104.939121 40.258092,-104.939439 40.258133,-104.939716 40.258166)))'::geography AS B
) AS data;
st_intersects | dist_km
---------------+------------------
f | 32.1052124928391
Something with your map is incorrect.
After some debugging (in addition to some helpful troubleshooting steps) I realized that I was building my WKT blobs incorrectly using the ST_AsText function, specifically for my soils layer. As a result, my intersection was not being applied to the entire set of geometries contained within my soils layer.
Currently my soils layer contains a subset of SSURGO soil map units, some of which do not actually contain a geometry. In order to correctly build a text string representing all non-null geometries, I needed to explicitly join the geometries before converting the result to WKT:
SELECT ST_AsText(ST_Union(the_geom)) FROM schema.layer
did the trick.