taskGNU Astronomy Utilities - Tasks: task #15713, Make quad structure with hashes...


You are not allowed to post comments on this tracker with your current authentication level.

task #15713: Make quad structure with hashes and store in kd-tree

Submitted by:  Sachin Kumar Singh <sks_15>
Submitted on:  Tue 30 Jun 2020 10:10:28 PM UTC  
Should Start On:  Tue 30 Jun 2020 12:00:00 AM UTC Should be Finished on:  Tue 30 Jun 2020 12:00:00 AM UTC
Category:  New program Priority:  5 - Normal
Item Group:  New feature Status:  Done
Privacy:  Public Percent Complete:  0%
Assigned to:  Sachin Kumar Singh <sks_15> Open/Closed:  Closed
Effort:  0.00

( Jump to the original submission)

Mon 10 Aug 2020 10:32:55 PM UTC, comment #30: 

The quad structure is done. The final quads(first 5 only) that are calculated for `gaia-in-img.fits` are:

      Cx              Cy                 Dx                    Dy          relative-brightness
-0.042045981178532 0.34919199605225   0.80225214850384   -0.031715181861999       16680
-0.42912677307865  0.23124787571642   0.0030258526555867 -0.6378191420571         6180
0.50230279083754   0.062025798026402  0.47054766298457   -0.46075964254161        4740
-0.24623018102375  0.43235834600382   0.47197948070874   0.45009254323365         4740
-0.26651345944186  0.44315227474372   0.35932303392371   -0.55776209603448        6210

For now only Cx, cy, dx, dy columns will be finally made to be used as the input to be used by the kd-tree. Relative brightness will later be used to choose the quad out the all the possible quad candidates.
You can check all the code here.
With all this done this task can be closed now:-)

Sachin Kumar Singh <sks_15>
Project MemberIn charge of this item.
Sat 01 Aug 2020 02:18:00 AM UTC, comment #29: 

Great! I look forward to the next steps (correct me if I am wrong):

  • Calculate the final hash.
  • Write them into the proper columns.
  • Write the result into a simple FITS table (just for a check).
  • Calculate the kd-tree and write the indexs of the left and write quads of each quad into it.
  • Save the full quad and kd-tree information into a file (to optionally avoid these steps for another image from the same field).
  • Calculate the quads from the image.

Then we can close this task and go back to task #15637 for the matching...

Mohammad Akhlaghi <makhlaghi>
Project Administrator
Sat 01 Aug 2020 12:21:29 AM UTC, comment #28: 

The function to find the farthest stars and assigning them as A and B is done and pushed on gitlab. Also, the result seems much better than before.

This function will assign the indexes of stars and hence I think instead of using the make_hash function in the make_quad function we shall use make_hash function in this function and return the final hash from here(we can change its name to better suit its function later on).

Fo now in the image the function properly assigns the two farthest stars indexes of A and B and the other 2 as C and D which satisfy the Cx<=Dx and Cx+Dx<=1 condition:-)

Sachin Kumar Singh <sks_15>
Project MemberIn charge of this item.
Thu 30 Jul 2020 12:09:49 PM UTC, comment #27: 

This is great! Nice work ;-)!

Now we can go onto the calculations of each quad and writing them into a table...

Mohammad Akhlaghi <makhlaghi>
Project Administrator
Thu 30 Jul 2020 11:39:28 AM UTC, comment #26: 

After using the 0.5 and 0.75 quartiles for the stars C and D, the result seems much cleaner and shaped like a polygon. Below are the images of all the quads and 2 random quads from them.

Sachin Kumar Singh <sks_15>
Project MemberIn charge of this item.
Wed 29 Jul 2020 05:57:00 PM UTC, comment #25: 

I change the dimension to 10  and also included sorting in the region file making function.

The result is that more no of quads are being formed(as expected) but they are still of the triangle shape. What would be the best way to find the middle two stars? Like shall I take the median of all the indexes to be mean? Or should I find a general quantile calculating method and map the required quantiles to the indexes for middle and 0.75 quantile indexes?

Sachin Kumar Singh <sks_15>
Project MemberIn charge of this item.
Wed 29 Jul 2020 12:38:01 AM UTC, comment #24: 

Indeed, its great that the polygons are now distributed over the full field :-D.

About your first question, please add sorting of the vertices in the ds9-region function. Otherwise in later scenarios you may mistakenly forget and will have to spend frustrating hours debugging the problem!

The fact that many of them look like triangles is a problem (because some images may not have the necessary resolution to separate stars that are so near to each other.

You can modify the vertice selection function to be a little more realistic: keep using the nearest and farthest points (2 points of 4). But for the other two points, come closer to the center of the distance distribution. For example, for the third point, try the middle element (at median distance), and for the fourth point, use the star at the three-quarters of the distance distribution (quantile of 0.75). 

Another good test would be to change the grid size (right now it is 5 grid elements per dimension) to smaller grid elements to see if everything is consistent. For example try 10 or 20 grid elements per dimension and look at the quad shapes and region file (also post it here).

Mohammad Akhlaghi <makhlaghi>
Project Administrator
Wed 29 Jul 2020 12:06:59 AM UTC, comment #23: 

The function for visualizations is done. For the function, I assumed that the array will be sorted, but is it okay or should I explicitly sort the array for every polygon and then display. Which one would be better?

But the results are good. Good thing the accumulation of quads in a single area is not done anymore:-) In the image of a single quad, it looks like a triangle but if we zoom on the left corner, the two points are so close that they seem to like it. It is expected because we select the n, n-2, and n-4 stars for a quad. The n, n-2, in this case, are very far from the reference star while the n-4 is quite near. I've also attached the region file for a quick check.

file #49568)

Sachin Kumar Singh <sks_15>
Project MemberIn charge of this item.
Sat 18 Jul 2020 11:56:01 PM UTC, comment #22: 

I had a fast look and I am impressed by the comments! Very nice! I really enjoyed reading them to get a good feeling without having to invest a lot of mental energy in understanding the coding. This is how a good code should look like! Good work!

Just one tiny point: since the kd-tree functions will later go into Gnuastro's library, prefix them with 'gal_kdtree_'. For example 'gal_kdtree_swap' or 'gal_kdtree_find_median' and so on. The same for the structure and macro.

Now that you are designing the kd-tree library and have the cute little example 'main' function to test with, let's do the next step too: reading/writing the kd-tree from/to a file (similar to the index files of astrometry.net). This will allow the users to optionally do the matching in two phases:

1) Run it once on the raw reference catalogs to generate the kd-trees and store them in files. For example this can be done in day time (before the observation run on known areas of the sky during the night). This step will also be the most time-consuming  (which is OK).

2) Run it a second time on catalogs derived from each image and load the kd-tree to calculate the image's WCS. This step will be much faster and can be done during the observation (without delaying that night's other observations).

To do this, we will also need to store the kd-tree in a file. But following the Unix philosophy, we shouldn't define an obscure binary format, let's just do it as a simple binary FITS table that is also fast to read.

Each row in the table can be one node. The first N columns for the N values along each dimension of each "point" (with type "double"). Then we can have two extra columns for the indexs of the "left" and "right" nodes (with type "size_t"). When writing the table, we can convert pointers to indexs and vice-versa when reading the table.

You can you add the kd-tree I/O as two high-level functions (maybe called 'gal_kdtree_write' and 'gal_kdtree_read'). I'd be happy to talk over a share-screen to help with reading/writing FITS tables.

In fact here is a fast brainstorm: how about removing the structure over-all and just using these columns instead? This will save a lot of time in reading/writing/debugging. For example, any "swap"ing of the nodes can be done by changing the "left" and "right" index columns of each row. Also, accessing any of the right-left nodes through their index is not much slower than using pointers (the compiler will convert them to a pointer anyway).

What do you think?

Mohammad Akhlaghi <makhlaghi>
Project Administrator
Sat 18 Jul 2020 10:55:35 PM UTC, comment #21: 

The KD-tree implementation is done and pushed here. You can see the main function to get a feel of how it works(a little test). Links to all the resources are included to get a better idea of the procedures involved.
To run it use `make compile PROGNAME=kdtree`.

Sachin Kumar Singh <sks_15>
Project MemberIn charge of this item.
Sat 18 Jul 2020 12:36:25 AM UTC, comment #20: 

Thanks for a nice review of the problem Sachin.

I think I understood the problem, but since my knowledge of kd-trees is very general and not yet as detailed as yours, please look at the following reply critically and feel free to correct any mis-understanding you may find ;-).

Given that you already know the number of points you want to put into the kd-tree before hand, pre-allocating the array/space before the hashes does generally seem like a good option.

In fact, in Gnuastro, I have done this in several places (for simply-linked lists): when I already know the total number of nodes in the list, I just allocate space once at the start for all of them, then write the values as they come in. In the end, I also just have to "free" one allocated space! This is also more efficient than allocating space for each node individually at different times, because each allocation/free-ing is itself computationally costly.

On a side-note, it would be interesting to see how astrometry.net implements its kd-tree.

Just one extra thing: try to keep the kd-tree related functions and structure nicely separate from this particular problem and modular (ideally in a separate .c and .h file). In this way, we can later generalize the kd-tree solution for other problems too ;-).

Mohammad Akhlaghi <makhlaghi>
Project Administrator
Fri 17 Jul 2020 11:56:31 PM UTC, comment #19: 

For the kd-tree, I have a bit dilemma on choosing the type of implementation. In one implementation(as given in its Wikipedia) it uses median to build the tree. But in another, it is also possible to build a tree without median(using only the axis to determine the next child). Also, it is mentioned in its Wikipedia page that,

Note that it is not required to select the median point. In the case where median points are not selected, there is no guarantee that the tree will be balanced. To avoid coding a complex O(n) median-finding algorithm or using an O(n log n) sort such as heapsort or mergesort to sort all n points, a popular practice is to sort a fixed number of randomly selected points and use the median of those points to serve as the splitting plane. In practice, this technique often results in nicely balanced trees.

Now it is desired/recommended to use a balanced tree for proper tree heights and skewness and hence fast operations. But if I choose the one with median, I'll have to make the array beforehand rather than inserting the hashes as they are made, which is a better and more modular design. What do you suggest?

P.S- Both kinds of implementation are ready to be tested after this minor problem is solved:-)

Sachin Kumar Singh <sks_15>
Project MemberIn charge of this item.
Thu 16 Jul 2020 07:19:41 PM UTC, comment #18: 

Thanks for defining bug #58773.

Indeed, the minor details of changing to 3 or 5 vertice polygons can be done later, so don't spend time on it now ;-). The important thing is that the infrastructure is now done.

Good to hear that the kd-tree functions are progressing. Once you define them (and we are ready to start looking into the catalogs from every image), I will do a code review ;-).

Mohammad Akhlaghi <makhlaghi>
Project Administrator
Thu 16 Jul 2020 07:02:07 PM UTC, comment #17: 

Ok, will do that:-)

Yes, for 3 or 5 quad system we just need to change the size of arrays and make a few modifications. We can define a loop for that for generality later. But we cannot make a general function for hash-code formation. We can talk about that possobility.

The implementation of remaining functions for kd-tree will be done and tested soon.

Sachin Kumar Singh <sks_15>
Project MemberIn charge of this item.
Thu 16 Jul 2020 06:45:11 PM UTC, comment #16: 

Good progress Sachin!

Can you define a bug for the issue of the quads not covering the full catalog? This isn't critical at this point, but before the final merging into Gnuastro, we need to fix it ;-).

Also, just for clarification, please correct me if I am wrong:

  • you implemented the 3 or 5 vertice polygon feature, but are using quadrilaterals now?
  • You now have the kd-tree of hashes and can start comparing with hashs in the individual images?
Mohammad Akhlaghi <makhlaghi>
Project Administrator
Thu 16 Jul 2020 06:28:56 PM UTC, comment #15: 

The final formation of hash codes is done along with the major implementation of kd-tree. For implementation, I'll be using similar implementation as done in this Wikipedia of kd-tree.

Also, according to Raul's suggestion, we can now use 3 or 5 star-quad but, for now, to so that we have to change lengths of certain arrays. Later on, this will be made as a feature to use as an option.

And yes the image is of the whole catalogue given. There were certain quads which were present on other places in the image but I think due to certain conditions later imposed they were eventually filtered out. Maybe we can look into it later.

Sachin Kumar Singh <sks_15>
Project MemberIn charge of this item.
Wed 15 Jul 2020 11:08:24 AM UTC, comment #14: 

Great, I am happy to see the progress ;-)!

Just one thing about the image with the many quads. Are these all the quads that have been found in the catalog, or only the quads that have been found in one healpix?

I think you are now set to continue to the next step for constructing the k-d tree and creating the hashes. We can look into possible bugs (or using 3-vertice polygons) later, as we go along ;-). For now, we should progress to have the matching hopefully complete by the end of July.

I am really busy with other projects these days, so I can't look into the code accurately right now. But as you make progress, more time will free up for me to look into the code in more detail ;-).

So keep on updating us with good visualizations of every step like the previous post and also don't hesitate to let me know if you want to talk, I always have time for a short talk ;-).

Mohammad Akhlaghi <makhlaghi>
Project Administrator
Wed 15 Jul 2020 12:53:52 AM UTC, comment #13: 

The code is pushed here. I removed the unwanted function and struct and have used indexes for all-purpose as discussed.

The healpixes are shown for theta_pix/2 which are not touching each other, but when I change values to theta_pix/1.2 or such they actually meet to produce a grid as expected.

For quads, as can be seen they are mostly concentrated on the lower right, though certainly, quads are available throughout the healpixels. But this behaviour seems likely as the other quads are not more in number than the ones in the lower right and hence are more in number, though I will certainly look if there are any logical error. Please point out if you find any:-)

Sachin Kumar Singh <sks_15>
Project MemberIn charge of this item.
Tue 14 Jul 2020 03:33:18 PM UTC, comment #12: 

Thanks, Raul. This will certainly give users flexibility. I'll try to implement it alongside.

Also, I read this paper in which they created a 3-star quad system to create the astroalign python package. It demonstrates the scenarios in which a 3-star system would be better.

Sachin Kumar Singh <sks_15>
Project MemberIn charge of this item.
Tue 14 Jul 2020 06:54:44 AM UTC, comment #11: 

Really good job Sachin. Yesterday I was talking with Mohammad and it just come to my mind that in Astrometry you are able to choose the number of objects to be considered as a quad. I thought it was in the solving step, but I was wrong. It is actually in the step of creating the catalogue indexes (with the program `build-astrometry-index'. Anyway, I just wanted to let you know this to make the code more general from the beginning. It may be useful to have this possibility in the future. You can have a look at this webpage: http://astrometry.net/doc/build-index.html

In the part where it is explained the option `-d':


[-d <dimquads>] number of stars in a "quad" (default 4).

Normally we use four-star featurse. This allows you to build 3- or 5-star features instead. 3-star features are useful for wide-angle images. 5-star features are probably not useful for most purposes.

Raul Infante-Sainz <infantesainz>
Project Member
Sat 11 Jul 2020 02:58:24 PM UTC, comment #10: 

The quads were made by firstly doing a search for all points and calculating the distance from every other point and filtering out those which were less than the helpix resolution(theta-pix as given in the documentation). It took an O(n^2) time and O(n) space complexity.
After that, I sorted(O(k*log(k)) these points(for every star) on the basis of distance from itself(including itself which produces distance = 0).
After that, if the array has at least 6 elements, then I pick the n-1, n-3, n-5 and 0 indexed elements and sort(O(4*log(4)) them according to brightness.
Finally, I make an array for plotting them and making a region file.
For viewing the output many printfs are included in between for debugging. We can do a meet where I can briefly explain all the code:-)
For the counting of the number of times a star can be used, I included a variable called `times_used` in `stuct quad_candidate`.

Fo generating helpix, I've created a function `make_healpix_polygon`. It generated a region file called polygon.reg for healpixes.

The polygon.reg has helpixed and final-quad.reg has final quads used. For now, some of the polygons in final-quad.reg might not be a proper polygon as they are still sorted on basis of brightness. To make them perfect polygon we can use the polygon sort function from the polygon library.

(file #49469, file #49470)

Sachin Kumar Singh <sks_15>
Project MemberIn charge of this item.
Sat 11 Jul 2020 12:42:04 AM UTC, comment #9: 

Great! No problem, paperwork is always the most important thing ;-).

The images are nice! Can you also add all the calculations for the quad that is shown alone? As well as the DS9 region file that you used (so I can load and check it)? For now I don't have time to look exactly into the code, so this would help for now.

I look forward to dig into the code soon ;-).

A few other small notes:

  • It looks like many of the polygons in the right image touch a single point. Maybe it would help if we generally put a counter on each point and avoid using it in a quad of each healpix size, once the count passes a certain threshold (maybe 5 or 10?).
  • If you can extract the corners of the healpix, it would help to also draw the healpix in DS9, maybe with a different color.
Mohammad Akhlaghi <makhlaghi>
Project Administrator
Sat 11 Jul 2020 12:28:32 AM UTC, comment #8: 

Sorry, it took so to reply back. Some college work came up and had to finish it first. But the good thing is, the task is (hopefully) done and pushed here. All the requirements are satisfied. There is still room of improvement to improve time complexity fo k nearest neighbours searches by using heaps to make it logarithmic, but that would complicate it further in the very initial stage and hence is marked for later.

The images for final quads are shown below(an individual quad and all of them for a particular Nside).

Sachin Kumar Singh <sks_15>
Project MemberIn charge of this item.
Mon 06 Jul 2020 08:05:14 PM UTC, comment #7: 

Perfect ;-)!

Then we have our first recipe to build a quad and identify it.

I look forward to the first visual example of all these calculations for one quad.

After that, you can visualize all the quads that found over the healpixes of the Gaia sub-catalog (covering that image). Just to see if everything is OK before continuing ;-).

Mohammad Akhlaghi <makhlaghi>
Project Administrator
Mon 06 Jul 2020 06:11:59 PM UTC, comment #6: 

The resolution part is where I had a doubt about. In astrometry.net, they have written in their paper that:
"The grid size is chosen so that grid cells are a small factor smaller than the query
images. Typically we choose the grid cells to be about a third of the size of the query
images, and select 10 stars from each grid cell so that most query images will contain about
a hundred query stars."

But I think using a HEALPix size to find quad within the circle is more efficient. And then we can use the kd-tree to find the nth nearest neighbour. This I think will be a more reliable method than randomly finding the points.

IN astrometry.net, they use brightness as stated below in their paper:
"We search for quads starting with the brightest stars, but for each star, we track the number of times it has already been used
to build a quad, and we skip stars that have been used too many times already. We repeat
this process, sweeping through the grid cells and attempting to build a quad in each one, a
the number of times."

But your suggestion really seems efficient. Also, we can use their approach of not using a star more than some n number of time.

Sachin Kumar Singh <sks_15>
Project MemberIn charge of this item.
Mon 06 Jul 2020 05:46:12 PM UTC, comment #5: 

There is another major problem with selecting the three nearest points:

The resolution of the reference catalog may be much more than the images! As a result there will not be any match at all (since all the quads of the reference catalog will be much smaller than the smallest possible quad of the catalog to match with!).

But if we use quads that are roughly the size of the healpix, the users just have to worry about the healpix size being smaller than their image.

Another thing just occurred to me that may provide a good improvement compared to astrometry.net's implementation: in the hash structure (and thus the kd-tree), besides the geometry of the points, use their relative brightness too.

For example you can define a four-element array (of type 'uint8' only keeping integer values 0, 1, 2, 3) to store sorted brightness of the points.

For example, let's assume the quad points (from the example of your blog, based on their geometry) are called A, B, C and D. Let's assume that after sorting their flux, B is the brightest, then C, then A and then D is the faintest.

Then the proposed array would have these values: [2,0,1,3], because point A is the third brightest (index 2), point B is the brightest (index 0) and so on...

In the matching we can then use this information also to get even more accurate fits of the quads ;-)!

Does astrometry.net have any way to account for the relative brightness of the points in the match?

Mohammad Akhlaghi <makhlaghi>
Project Administrator
Mon 06 Jul 2020 05:25:04 PM UTC, comment #4: 

Very good! But just one thing: probably using the 3 nearest neighbors isn't too good (there will be too many repetitions and thus too few quads for the fit).

Maybe a better way to select the three neighbors would be this: let's assume the healpix size is 'h' degrees. Look in a circle of radius of 'h' degrees around each point sort them by distance, so the series of points becomes (p[0] is the nearest, p[n] i the farthest):

p[0], p[1], ... p[n-4], p[n-3], p[n-2], p[n-1], p[n]

Then select p[n], p[n-2], p[n-4] as the other three points for constructing the quad.

I feel this will create less repetition between the quads (since the probability that they be the same is much less than the 3 nearest neighbors).

This method has the advantage that the quads will be large (on a scale of the healpix), thus decreasing statistical errors.

It will thus be a little more computationally expensive, but I think it will be worth it. To fix the computational cost when there are many points within the circle of radius 'h', it may be possible to exploit the kd-tree to find these points instead of actually sorting them. Or we can simply discard many of the points closer than 'h/2'.

Another method (that is still seems to be more robust than the three nearest neighbors) is to randomly select three points from all the points within a distance of 'h'.

What do you think?

Mohammad Akhlaghi <makhlaghi>
Project Administrator
Mon 06 Jul 2020 03:47:55 PM UTC, comment #3: 

Thanks for the review:-) I'll make all changes accordingly.

So, for now, the first thing is to create a kd-tree to store the positions of stars and then for each star find the 3 nearest neighbours.

After that, we can sort these 4 objects (using functions from polygon.h) and then make quads with them and store hashes.

Sachin Kumar Singh <sks_15>
Project MemberIn charge of this item.
Sun 05 Jul 2020 07:42:30 PM UTC, comment #2: 

I enjoyed looking through the blog, nice work!

I am just a little confused by the notation. If I understand correctly, you are now using ".orig" to differentiate between the before/after scaled phase. Since you have already defined '.' to be for the coordinates, this notation causes some confusion.

Maybe you can call the initial (original scale) points with capital letters (A, B, C and D) and the scaled/shifted points with small letters like (a, b, c and d).

Since we are talking about two systems (original and shifted), the term "scale" (in "Scale calculation" section) can be confusing: I initially thought you are calculating the transformation of the original to scaled coordinates!

But what you mean by "scale" is the length of AC and AD in the newly rotated coordinates, right? so maybe you can call it "newlength", or any other less-confusing term ;-).

I also wonder: finding the diagonal of the quad is great for separating A and B from C and D. But how do you select the reference point (coordinate 0,0) from A and B? We need to select a method that makes the reference point unique in any rotation. Maybe the one where the lengths r1+r2 is smaller? But this is just a raw brainstorm. If you have a solution to this, it would be good explain it here too ;-).

Finally, it would be good to highlight that you are following the recipe of Astrometry.net and say which parts follow a similar logic and which parts are new/different ;-).

I really enjoyed reading the blog, very nice!

Mohammad Akhlaghi <makhlaghi>
Project Administrator
Sun 05 Jul 2020 06:52:03 PM UTC, comment #1: 

Summarised the task in this blog. Please point any error in methods or otherwise.

Sachin Kumar Singh <sks_15>
Project MemberIn charge of this item.
Tue 30 Jun 2020 10:10:28 PM UTC, original submission:  

After the completion of task #15700, we now have a HEALPix map of the catalogue with the brightest objects in each map. Next step is the implementation of the quad structure that will take many permutations of these objects and make a unique hash of all these to be stored and later on compared with the query images and make relative matches.

This is a subtask of task #15637.

Sachin Kumar Singh <sks_15>
Project MemberIn charge of this item.


Depends on the following items: None found

Items that depend on this one: None found


Carbon-Copy List
  • -email is unavailable- added by infantesainz (Posted a comment)
  • -email is unavailable- added by makhlaghi (Posted a comment)
  • -email is unavailable- added by sks_15 (Submitted the item)

    Do you think this task is very important?
    If so, you can add your encouragement to it.
    This task has 0 encouragements so far.

    Only logged-in users can vote.




    Follow 19 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2020-08-10 sks_15 StatusIn Progress => Done
        Open/ClosedOpen => Closed
    2020-08-01 makhlaghi SummaryMake quad structure to make unique hashes of 4 objects => Make quad structure with hashes and store in kd-tree
    2020-08-01 sks_15 Attached File- => Added Screenshot@from@2020-08-01@05-41-55.png, #49593
    2020-07-30 sks_15 Attached File- => Added Screenshot@from@2020-07-30@17-05-56.png, #49581
        Attached File- => Added Screenshot@from@2020-07-30@17-06-25.png, #49582
        Attached File- => Added Screenshot@from@2020-07-30@17-05-32.png, #49583
    2020-07-29 sks_15 Attached File- => Added Screenshot@from@2020-07-29@21-26-28.png, #49575
    2020-07-29 sks_15 Attached File- => Added Screenshot@from@2020-07-29@05-27-22.png, #49565
        Attached File- => Added Screenshot@from@2020-07-29@05-26-54.png, #49566
        Attached File- => Added Screenshot@from@2020-07-29@05-27-03.png, #49567
        Attached File- => Added polygon.reg, #49568
    2020-07-15 sks_15 Attached File- => Added Screenshot@from@2020-07-15@06-13-05.png, #49485
        Attached File- => Added Screenshot@from@2020-07-15@06-13-19.png, #49486
        Attached File- => Added Screenshot@from@2020-07-15@06-13-50.png, #49487
    2020-07-11 sks_15 Attached File- => Added polygon.reg, #49469
        Attached File- => Added final-quads.reg, #49470
    2020-07-11 sks_15 Attached File- => Added Screenshot@from@2020-07-11@05-47-05.png, #49460
        Attached File- => Added Screenshot@from@2020-07-11@05-47-37.png, #49461

    Back to the top

    Powered by Savane 3.5