addam / Export-Paper-Model-from-Blender

Python addon for creating paper models in Blender (development version)
https://blenderartists.org/t/export-paper-model/476597
409 stars 54 forks source link

Division by zero #29

Closed smimram closed 11 years ago

smimram commented 11 years ago

Hi,

When I try to export a model of mine I get the following error:

There are 62 twisted face(s) with ids: 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 52, 53, 55, 56, 57, 60, 61, 64, 66, 67, 68, 69, 70, 71
Traceback (most recent call last):
  File "/home/smimram/.blender/2.63/scripts/addons/io_export_paper_model.py", line 1467, in invoke
    self.unfolder.prepare(create_uvmap=self.do_create_uvmap)
  File "/home/smimram/.blender/2.63/scripts/addons/io_export_paper_model.py", line 168, in prepare
    self.mesh.generate_cuts()
  File "/home/smimram/.blender/2.63/scripts/addons/io_export_paper_model.py", line 265, in generate_cuts
    if island_a.join(island_b, edge):
  File "/home/smimram/.blender/2.63/scripts/addons/io_export_paper_model.py", line 852, in join
    rot = fitting_matrix(first_b - second_b, uvedge_a.vb - uvedge_a.va)
  File "/home/smimram/.blender/2.63/scripts/addons/io_export_paper_model.py", line 125, in fitting_matrix
    return (1/v1.length_squared)*M.Matrix((
ZeroDivisionError: float division by zero

location:<unknown location>:-1

location:<unknown location>:-1

Do you have an idea of what could have gone wrong? I guess that v1.length_squared was null because I have a vector of null length somewhere...

Thanks!

smimram commented 11 years ago

The error was in fitting_matrix which is supposed to compute the "Matrix that rotates v1 to the same direction as v2". I guess that in the case where v1 is null, the identity matrix is fine. And actually the following patch allowed me to export the model:

diff --git a/io_export_paper_model.py b/io_export_paper_model.py
index ee559e9..ee47197 100644
--- a/io_export_paper_model.py
+++ b/io_export_paper_model.py
@@ -122,9 +122,12 @@ def argmax_pair(array, key):

 def fitting_matrix(v1, v2):
        """Matrix that rotates v1 to the same direction as v2"""
-       return (1/v1.length_squared)*M.Matrix((
-               (+v1.x*v2.x +v1.y*v2.y, +v1.y*v2.x -v1.x*v2.y),
-               (+v1.x*v2.y -v1.y*v2.x, +v1.x*v2.x +v1.y*v2.y)))
+       if v1.length_squared == 0:
+               return M.Matrix(((1,0),(0,1)))
+       else:
+               return (1/v1.length_squared)*M.Matrix((
+                       (+v1.x*v2.x +v1.y*v2.y, +v1.y*v2.x -v1.x*v2.y),
+                       (+v1.x*v2.y -v1.y*v2.x, +v1.x*v2.x +v1.y*v2.y)))

 def z_up_matrix(n):
        """Get a rotation matrix that aligns given vector upwards."""
addam commented 11 years ago

Thanks for reporting this, I was overlooking this issue. You are right, it is caused by zero-length vectors: to my knowledge, always by zero-length edges when the algorithm tries to include them inside of an island.

But since such an operation does not make any sense (a zero-length piece of paper would make a rather weak joint), I would prefer not to let it happen at all:

diff --git a/io_export_paper_model.py b/io_export_paper_model.py
index ee559e9..6e42577 100644
--- a/io_export_paper_model.py
+++ b/io_export_paper_model.py
@@ -257,6 +257,8 @@ class Mesh:
                edge.generate_priority(average_length)
            edges.sort(key = lambda edge:edge.priority, reverse=False)
            for edge in edges:
+               if edge.length == 0:
+                   continue
                face_a, face_b = edge.main_faces
                island_a, island_b = face_a.uvface.island, face_b.uvface.island
                if len(island_b.faces) > len(island_a.faces):

Please, check if this patch solves the issue in your case as well. If so, I would prefer it over your code.

smimram commented 11 years ago

Yeah, that makes sense. I did not try very hard to find a proper solution :)