Using an ADT's constrctor as a type in Purescript - purescript

Here's an example of an ADT from PureScript by Example
data Shape
= Circle Point Number
| Rectangle Point Number Number
| Line Point Point
| Text Point String
type Point =
{ x :: Number
, y :: Number
}
Does it make sense to want to do something like this?
boundingCircle :: Shape -> Circle
boundingBox :: Shape -> Rectangle
Right now, this isn't allowed, as Circle isn't a type. I could perhaps have Shape be a type class and Circle, Rectangle, ect have instances of Shape. Then I lose the semantics that a Shape is the union of exactly 4 constructors (pattern matching becomes messier).
Is treating ADT constructors as types themselves something really worth avoiding?

Whether treating ADP constructors as types is worth avoiding or not is a meaningless questions, because that's impossible. ADT constructors can't be types, and that's the end of that.
But if you wanted to have Circle and Rectangle available as their own types, but still keep Shape as an ADT, there is nothing impossible about that:
type Circle = { center :: Point, radius :: Number }
type Rectangle = { center :: Point, width :: Number, height :: Number }
data Shape
= Circle Circle
| Rectangle Rectangle
| Line Point Point
| Text Point String
boundingCircle :: Shape -> Circle
boundingBox :: Shape -> Rectangle

I could perhaps have Shape be a type class and Circle, Rectangle, ect
have instances of Shape. Then I lose the semantics that a Shape is the
union of exactly 4 constructors (pattern matching becomes messier).
You can actually have both 4 separate types and easy pattern matching.
First the individual types corresponding to the constructors in the original example:
data Circle = Circle Point Number
data Rectangle = Rectangle Point Number Number
data Line = Line Point Point
data Text = Text Point String
And then the Shape type can be a simple "union" (or "sum") of the 4 individual types:
data Shape = CircleShape Circle | RectangleShape Rectangle | LineShape Line | TextShape Text
This setup would allow you to do both the things you seem to want. The functions you mention would have a form roughly like this:
boundingCircle :: Shape -> Circle
boundingCircle (CircleShape (Circle center radius)) = Circle (...) (...)
boundingCircle (CircleRectangle (Rectangle corner length width)) = Circle (...) (...)
and so on for the remaining cases, which also shows that you can pattern match on a Shape and know it is one of the four particular variants.
It's not a "free win" though. Everything comes with pros and cons, and deciding how to design your datatypes isn't always straightforward. In particular, with the above, you will note that the pattern matching on a Shape, while still possible, has become significantly more verbose. Quite often you won't actually want to have things like Circle as their own types. Or you might be happy with the typeclass approach - while this stops you from pattern-matching, you could still have boundingCircle and so on as methods of that typeclass, or as other functions that can easily be derived from the typeclass methods.
Indeed I would suggest that my favoured approach here might be exactly the typeclass one - if you're designing the typeclass, you can put in exactly the methods you need, and no more. But there's never any one "right answer" in these situations - you weigh the pros and cons and do what fits your use best.

Related

Get world space Oriented Boundin Box 8 points in unreal (C++)

Does anybody know how to retrieve an actor's world space oriented bounding box 8 points in C++. Im reading the official documentation but it's a bit vague as it never specifies whether the bounds objects (FBox, FBoxShpereBounds) are local space, world space, axis aligned etc
I'm thinking something like below but I'm not sure if that's right
UStaticMeshComponent* pMesh = Cast<UStaticMeshComponent>(actor->GetComponentByClass(UStaticMeshComponent::StaticClass()));
if (pMesh)
{
UStaticMesh* pStaticMesh = pMesh->GetStaticMesh();
if (pStaticMesh && pStaticMesh->GetRenderData())
{
FStaticMeshRenderData* pRenderData = pStaticMesh->GetRenderData();
if (pRenderData)
FBoxSphereBounds bounds = pRenderData->Bounds;
bounds.TransformBy(actor>GetActorTransform());
}
}
Unreal maintains it's bounds as axis-aligned (AABB). This is often done in game engines for efficiency in the physics/collision subsystem. To get an AABB for an actor, you can use the following function - this is essentially equivalent to what you did above with pRenderData->Bounds but is independent of the actor implementation.
FBox GetActorAABB(const AActor& Actor)
{
FVector ActorOrigin;
FVector BoxExtent;
// First argument is bOnlyCollidingComponents - if you want to get the bounds for components that don't have collision enabled then set to false
// Last argument is bIncludeFromChildActors. Usually this won't do anything but if we've child-ed an actor - like a gun child-ed to a character then we wouldn't want the gun to be part of the bounds so set to false
Actor.GetActorBounds(true, ActorOrigin, BoxExtent, false);
return FBox::BuildAABB(ActorOrigin, BoxExtent);
}
From code above it looks like you want an oriented bounded box (OBB) since you are applying the transform to it. Trouble is the AABB Unreal maintains will be "fit" to the world space axes and what you are essentially doing just rotates the center point of the AABB which will not give a "tight fit" for rotation angles far from the world axes. The following two UE forum posts provide some insight into how you might do this:
https://forums.unrealengine.com/t/oriented-bounding-box-from-getlocalbounds/241396
https://forums.unrealengine.com/t/object-oriented-bounding-box-from-either-aactor-or-mesh/326571/4
If you want a true OBB, FOrientedBox is what you need, but the engine lacks documented utilities to do intersection or overlap tests with this structure depending on what you are trying to do, but these things do exist in the engine but you have to hunt through the source code to find them. In general, the separating axis theorem (SAT) can be used to find collisions between two convex hull shapes, which an OBB is by definition.

Grid based dungeon with random room sizes

I'm making a game, where levels are grid based.
At first, I have rectangle MxM cells. Then within this rectangle I have to put rooms. Room is another rectangle which is AxB cells, where 2 <= A, B <= 4. Besides, It's necessary to put N rooms in each row and N ones in each column. They should fill all the space, there can't be empty space between them. In other words, I have to feel rectangle with other rectangles the way that there will no be empty space between them and they will form a grid with N rows and N columns.
What I did:
I store information about rooms in form of their left-top corner, calculate it and then put rooms based on their and neighbor's corners. To do that:
Divide grid on rooms 3x3
In each of 3x3 rooms define area which is obligatory floor (2x2 square, let's call it red area)
In loop for each room count it's neighbor x and y corner position the way that it doesn't cross none of the obligatory floor ares. For that:
a. Get red area of current room and it's neighbors. Set corner somewhere between them, making sure the dimensions of the room are within range above.
b. Resolve collisions, when it's not possible to set random corner. For instance, if x position of room above isn't equal to our room, then we can't put horizontal wall between to rooms righter them in random y position, because in that case these rooms will overlap each other.
Some other stuff with converting information about corners to rooms themselves
So, what's the problem? My code with a lot of if-statements and crutches became so unreadable and huge that it almost impossible to test and find bugs. Approach I used seems to work but it's impossible to control the way it's working or not working.
Another issue is that I want to have more control on how it looks like. Grid must be interesting, which means that neighbor rooms are preferably not of the same size. There's an example (grid) of such a grid (with red areas that are gray there), which is not bad.
Is there some alternative to solve this? In other questions I saw a lot of similar solutions, but all of them doesn't assume that there's fixed amount of rows and columns.
Recommend me some articles I haven't managed to find, probably, literature devoted to this topic, or point the direction where to move and find a working solution.
A traditional method of generating grids containing rooms is to use Binary-Space-Partition trees.
One thing about that method is that it often produces grids that are less densely populated than your example. You might be able to modify some BSP example code and make the map more dense though.
Another possible approach would be to generate the rectangles first, (perhaps with a border along two edges for the gap) then try to pack them using a rectangle packing algorithm. This previous answer has several potential packing algorithms.

Need help producing this code: Dynamic fieldnames to calculate distance btw centers of two shapes

So I have a structure that was developed based on user's input and preference. The code begins with the user choosing between 3 given shapes: circle triangle, and square. Each of these shapes is structures themselves, the CIRCLE struct has {'radius', random int, 'center, [random_int1, randomint2] and area,[]), the area is calculated only if the user chooses the shape, although it's probably not pertinent to what I am asking. Additionally, the other two shapes have FN's (sidelength, center, area). So basically the center of each is valued with a 1x2 double, both randomly assigned.
after the shapes are created and displayed to the user, the user chooses two of the shapes. These two shapes are to undergo DYNAMIC FIELD NAME computation to calculate the distance between the two centers using sqrt((x2-x1)^2 + (y2-y1)^2)). Following this, we need to calculate the ratio of areas of two shapes, which are again chosen by the user. for example, it states "if the user chooses square and circle, calculate the ratio of the areas of the square to the circle, using dynamic field names.
shape = struct('circle;, [], 'square',[], 'triangle', [])
I'm new to Matlab, so please if possible, explain accordingly. I'm so nervous about this class, that I'm literally shaking right now after being up for almost 2 days trying to learn all this. It's really intense.

Visio (Re)naming shapes as 'sheet' when it should be circle, box, etc

This may seem pretty idiotic, but here goes: I'm making some networks in visio and I'm literally just cutting and pasting boxes and circles (changing the text) over and over again and adding connectors as appropriate. I have a macro that then sorts the shape texts based on whether it is a circle or box.
Every once in a while the macro will fail, not because there is a problem with the macro but because one of my shapes (boxes, circles, and even connectors) have been renamed by visio as a 'sheet'. For example, I copy 'Circle.18' and then paste it right back in, and instead of being 'Circle.19' this shape is 'Sheet.19'. This can happen when I copy & paste, or when I drag a new shape off the stencil. It appears to be totally random when this happens, but it messes up my subsequent macro operation so I would really like to stop visio from naming different shapes as 'sheet.xx'
Any ideas?
Is it possible to change the name of a shape in the shapesheet or anything?
Thanks in advance
I don't know how the naming works in Visio, and I don't rely on the names for macros.
In your case, distinguishing the geometries from one another is how I would identify shapes. So if it's a 2D shape, and it has a geometry section with 6 rows, it's probably a rectangle. If the geometry section has 2 rows, it's probably a circle.
However, I wouldn't necessarily let it get to the point where I'm going off of the shape geometry, unless I want whoever is using the macro to use whatever circle or box shapes they want. Instead, I would just provide a stencil with a box and a circle shape, and I would either put the different shapes on different layers, or just add a user cell with the type clearly defined. Then the macro would just look for those shapes specifically denoted as the type I'm interested in.

Identify Lobed and bumps of Leaves

I need some help, I have to make a project about leaves.
I want to make it by MATLAB.
my input is an image of one leaf (with a white background) and I need to know two things about the leaf:
1) find the lobed leaf (the pixels of each lobed leaf):
Lay the leaf on a table or work space where you can examine it.
Look at the leaf you are trying to identify. If the leaf looks like it has fingers, these are considered lobes. There can be
anywhere from two to many lobes on a leaf.
Distinguish pinnate leaves from palmate leaves by looking at the veins on the underside of the leaf. If the veins all come from
the same place at the base of the leaf it is considered palmately
lobed. If they are formed at various places on the leaf from one
centre line, the leaf is pinnately lobed.
Identify the type of leaf by using a leaf dictionary.
2) find approximately the number of bumps of the leaf:
in other words, find the "swollen points" of each leaf.
these are examples of leaves:
I've found some leaves examples in here.
Here is my attempt to solve the problem.
In the images that I've found, the background is completely black. If it is not so in your images, you should use Otsu's thresholding method.
I assumed that there can be only 3 types of leaves, according to your image:
The idea is to do blob analysis. I use the morphological operation of opening, to separate the leaves. If there is only one blob after the opening, I assume it is not compound. If the leaves are not compound, I analyze the solidity of the blobs. Non-solid enough means they are lobed.
Here are some examples:
function IdentifyLeaf(dirName,fileName)
figure();
im = imread(fullfile(dirName,fileName));
subplot(1,3,1); imshow(im);
% thresh = graythresh( im(:,:,2));
imBw = im(:,:,2) > 0;
subplot(1,3,2);imshow(imBw);
radiusOfStrel = round( size(im,1)/20 ) ;
imBwOpened = imopen(imBw,strel('disk',radiusOfStrel));
subplot(1,3,3);imshow(imBwOpened);
rpOpened = regionprops(imBwOpened,'Area');
if numel(rpOpened)>1
title('Pinnately Compound');
else
rp = regionprops(imBw,'Area','Solidity');
%Leave only largest blob
area = [rp.Area];
[~,maxIndex] = max(area);
rp = rp(maxIndex);
if rp.Solidity < 0.9
title('Pinnately Lobed');
else
title('Pinnately Veined');
end
end
end
I would approach this problem by converting it from 2d to 1d by scanning in a vector the perimeter of the leaf using "right hand on the wall" -algorithm.
From that data, I presume, one can find a dominant axis of symmetry (e.g. fitting a line); the distance of the perimeter would be calculated from that axis and then one could simply use a threshold+filtering to find local maxima and minima to reveal the number lobes/fingers... The histogram of distance could differentiate between pinnately lobed and pinnately compound leaves.
Another single metrics to check the curvature of the perimeter (from two extreme points) would be http://en.wikipedia.org/wiki/Sinuosity
Recognizing veins is unfortunately a complete different topic.