Select to view content in your preferred language

Japanese visual multiplication with lines using arcpy

2231
11
07-03-2014 07:51 PM
XanderBakker
Esri Esteemed Contributor
3 11 2,231

Today I stumbled upon a tweet showing how children in Japan are using line intersections to calculate the multiplication of two numbers. I was amazed by the beauty of the method which can be extended to larger numbers too.  Just take a look at the example below:

Japanese-Multiplication-Trick.jpg

Source: http://www.pinpopular.com/japanese-multiplication-trick-pinterest-education/

It is basically counting intersections of lines. Wait ... intersections of lines ... sounds to me that arcpy could do that too. So, why not write some arcpy / python code to multiply 2 numbers?

I know, what you're thinking ... why? Because it's fun and completely useless!

So this is what I came up with:

# Japanese visual multiplication with arcpy

import arcpy

import os

ws = r"C:\Forum\JapaneseMultiply\fgdb\test.gdb"

arcpy.env.workspace = ws

arcpy.env.overwriteOutput = True

sr = arcpy.SpatialReference(3857)

arcpy.env.outputCoordinateSystem = sr

# values to multiply:

value1 = 47 # (1 -99)

value2 = 63 # (1 -99)

fc_points = "points"

fc_lines_h = "lines_h"

fc_lines_v = "lines_v"

fc_polygones = "polygons"

fc_result = "result"

size = 10

fld_factor = "factor"

val_h1 = value1 / 10

val_h2 = value1 % 10

val_v1 = value2 / 10

val_v2 = value2 % 10

# create horizontal lines

arcpy.CreateFeatureclass_management(ws, fc_lines_h, "POLYLINE", "#", "DISABLED", "DISABLED", sr)

with arcpy.da.InsertCursor(fc_lines_h, ("SHAPE@")) as rows:

    for y in range(1, val_h1 + 1):

        x1 = -1 * size

        x2 = size

        array = arcpy.Array([arcpy.Point(x1, y),

                     arcpy.Point(x2, y)])

        polyline = arcpy.Polyline(array)

        rows.insertRow([polyline])

    for y in range(1, val_h2 + 1):

        x1 = -1 * size

        x2 = size

        array = arcpy.Array([arcpy.Point(x1, -1 * y),

                     arcpy.Point(x2, -1 * y)])

        polyline = arcpy.Polyline(array)

        rows.insertRow([polyline])

# create vertical lines

arcpy.CreateFeatureclass_management(ws, fc_lines_v, "POLYLINE", "#", "DISABLED", "DISABLED", sr)

with arcpy.da.InsertCursor(fc_lines_v, ("SHAPE@")) as rows:

    for x in range(1, val_v1 + 1):

        y1 = -1 * size

        y2 = size

        array = arcpy.Array([arcpy.Point(-1 * x, y1),

                     arcpy.Point(-1 * x, y2)])

        polyline = arcpy.Polyline(array)

        rows.insertRow([polyline])

    for x in range(1, val_v2 + 1):

        y1 = -1 * size

        y2 = size

        array = arcpy.Array([arcpy.Point(x, y1),

                     arcpy.Point(x, y2)])

        polyline = arcpy.Polyline(array)

        rows.insertRow([polyline])

# Create polygon cuadrants

arcpy.CreateFeatureclass_management(ws, fc_polygones, "POLYGON", "#", "DISABLED", "DISABLED", sr)

arcpy.AddField_management(fc_polygones, fld_factor, "DOUBLE")

with arcpy.da.InsertCursor(fc_polygones, ("SHAPE@", fld_factor)) as rows:

    # left top factor 100

    factor = 100

    array = arcpy.Array([arcpy.Point(-1 * size, 0),

                         arcpy.Point(-1 * size, size),

                         arcpy.Point(0, size),

                         arcpy.Point(0, 0),

                         arcpy.Point(-1 * size, 0)])

    polygon = arcpy.Polygon(array)

    rows.insertRow([polygon, factor])

    # right top factor 10

    factor = 10

    array = arcpy.Array([arcpy.Point(0, 0),

                         arcpy.Point(0, size),

                         arcpy.Point(size, size),

                         arcpy.Point(size, 0),

                         arcpy.Point(0, 0)])

    polygon = arcpy.Polygon(array)

    rows.insertRow([polygon, factor])

    # left bottom factor 10

    factor = 10

    array = arcpy.Array([arcpy.Point(-1 * size, -1 * size),

                         arcpy.Point(-1 * size, 0),

                         arcpy.Point(0, 0),

                         arcpy.Point(0, -1 * size),

                         arcpy.Point(-1 * size, -1 * size)])

    polygon = arcpy.Polygon(array)

    rows.insertRow([polygon, factor])

    # right bottom factor 1

    factor = 1

    array = arcpy.Array([arcpy.Point(0, 0),

                         arcpy.Point(0, -1 * size),

                         arcpy.Point(size, -1 * size),

                         arcpy.Point(size, 0),

                         arcpy.Point(0, 0)])

    polygon = arcpy.Polygon(array)

    rows.insertRow([polygon, factor])

# start analysis: intersect horizontal and vertical lines

arcpy.Intersect_analysis([fc_lines_h, fc_lines_v], fc_points, "ALL", "", "POINT")

# Next intersect the polygon with the points (intersection of lines)

arcpy.Intersect_analysis([fc_polygones, fc_points], fc_result)

# now use Search cursor to get result

res = 0

with arcpy.da.SearchCursor(fc_result, (fld_factor)) as rows:

    for row in rows:

        factor = row[0]

        res += factor

print "{0} * {1} = {2}".format(value1, value2, res)

print "verify: {0} * {1} = {2}".format(value1, value2, value1 * value2)

In the example above the following result is printed:

47 * 63 = 2961.0

verify: 47 * 63 = 2961

Displaying the featureclasses gives the following result:

result.png

I hope my next blog post will be of more use.

Xander

Tags (2)
11 Comments
T__WayneWhitley
Honored Contributor

...interesting and innovative, and yes, fun!

FilipKrál
Frequent Contributor

Nice.

JamesFitzgerald
Frequent Contributor

Hey,

This managed to burn about 45 minutes of my day by working on it and showing it to co-workers. We went from two digits to three digits. Awesome!

James

XanderBakker
Esri Esteemed Contributor

The next step would be to make it work with any size of numbers...

NeilAyres
MVP Alum

Xander, do you not have a day job....

XanderBakker
Esri Esteemed Contributor

actually, I do have a day job...

MelitaKennedy
Esri Notable Contributor

That's really cool. I'll have to remember that for when my kids are older...

XanderBakker
Esri Esteemed Contributor

Glad you liked it!

QiuhuaMa
Deactivated User

I am working on my dissertation right now and need help with python.

I would like to calculate the distance from the nearest wildfire to each house. House is a point and fire is a polygon in my data. However the fires I am interested in is the fire that burned within the past 7 years before the sale of the homes. So I need to exclude all fires that burned after the sale date of the home, and all fires that burned greater than seven years before the sale of the home.

Is there anyway to add a time constraint to near tool using python? I knew nothing about python and hope can get some advice from you! I tried to do it manually but it took so much time!

My email address is qiuhuanihao@gmail.com. Any advice is greatly appreciated!

Best Regards,

Chelsea

XanderBakker
Esri Esteemed Contributor

Hi Qiuhua Ma ,

I see you just joined GeoNet. First of all Welcome!

You have posted your question in a comment to my blog on Japanese visual multiplication. This is not where you should post your question. In order to get a fair amount of answers you should post your specific question in the Python place. If you are new to GeoNet, you might want to read some topics in the Help:

The members of the community will be glad to help you solving your problem.

Kind regards, Xander

AndriesPotgieter
Emerging Contributor

Hi Xander Bakker

Thanks for your code on extracting percentiles from raster using polygon.

It runs perfectly but all the percentiles have the same value.

i.e. Processing polygon: 138
- ExtractByMask...
- saved raster as ras138
- fill dict with Value x Count
- determine sum
- sum=7294
- create percentile dict
- iterate perceniles
- Perc_dec for is 0.02
- Perc for 2% is 1426
- Store value
- Perc_dec for is 0.05
- Perc for 5% is 1426
- Store value
- Perc_dec for is 0.1
- Perc for 10% is 1426
- Store value
- Perc_dec for is 0.25
- Perc for 25% is 1426
- Store value
- Perc_dec for is 0.5
- Perc for 50% is 1426
- Store value
- Perc_dec for is 0.75
- Perc for 75% is 1426
- Store value
- Perc_dec for is 0.9
- Perc for 90% is 1426
- Store value
- Perc_dec for is 0.95
- Perc for 95% is 1426
- Store value
- Perc_dec for is 0.98
- Perc for 98% is 1426
- Store value
- update row

I have followed your advice and used the latest code for extract mask. Still the same.

My polygon is not projected and is 1.5mx3m and the raster pixels is 2.5cm.  Big data sets 

hope you can advise what I should change to force the percentiles to be calculated uniquely?

kind regards

andries

About the Author
Solution Engineer for the Utilities Sector @ Esri Colombia - Ecuador - Panamá sr GIS Advisor / Python - Arcpy developer / GIS analyst / technical project leader / lecturer and GeoNet moderator, focusing on innovations in the field of GIS. Specialties: ArcGIS, Python, ArcGIS Enterprise, ArcGIS Online, Arcade, Configurable Apps, WAB, Mobile Apps, Insights, Spatial Analysis, LiDAR / 3D Laser Scanning / Point Clouds. UNME http://nl.linkedin.com/in/xanderbakker/ http://www.slideshare.net/XanderBakker http://www.scribd.com/xbakker http://twitter.com/#!/XanderBakker
Labels