[GRASS-SVN] r68831 - grass-addons/grass7/vector/v.civil

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Jul 1 15:30:22 PDT 2016


Author: jfc
Date: 2016-07-01 15:30:22 -0700 (Fri, 01 Jul 2016)
New Revision: 68831

Added:
   grass-addons/grass7/vector/v.civil/img1.png
   grass-addons/grass7/vector/v.civil/img2.png
   grass-addons/grass7/vector/v.civil/img2_1.png
   grass-addons/grass7/vector/v.civil/img2_2.png
   grass-addons/grass7/vector/v.civil/img3.png
   grass-addons/grass7/vector/v.civil/img3_2.png
   grass-addons/grass7/vector/v.civil/img4.png
   grass-addons/grass7/vector/v.civil/img4_1.png
   grass-addons/grass7/vector/v.civil/img4_2.png
   grass-addons/grass7/vector/v.civil/img4_3.png
   grass-addons/grass7/vector/v.civil/img5.png
   grass-addons/grass7/vector/v.civil/img6.png
   grass-addons/grass7/vector/v.civil/img6_1.png
   grass-addons/grass7/vector/v.civil/img7.png
   grass-addons/grass7/vector/v.civil/img8.png
   grass-addons/grass7/vector/v.civil/img8_1.png
   grass-addons/grass7/vector/v.civil/img8_2.png
   grass-addons/grass7/vector/v.civil/img_a_plan.png
   grass-addons/grass7/vector/v.civil/img_a_tooladdrow.png
   grass-addons/grass7/vector/v.civil/img_a_topotools_1.png
   grass-addons/grass7/vector/v.civil/img_a_vcivilroad_7.png
   grass-addons/grass7/vector/v.civil/img_a_vert.png
   grass-addons/grass7/vector/v.civil/img_tables1.png
   grass-addons/grass7/vector/v.civil/img_tables2.png
   grass-addons/grass7/vector/v.civil/img_tables2_2.png
   grass-addons/grass7/vector/v.civil/img_tables2_3.png
   grass-addons/grass7/vector/v.civil/img_tables3.png
   grass-addons/grass7/vector/v.civil/img_tables3_1.png
   grass-addons/grass7/vector/v.civil/img_tables3_2.png
   grass-addons/grass7/vector/v.civil/img_tables4_1.png
   grass-addons/grass7/vector/v.civil/img_tables4_2.png
   grass-addons/grass7/vector/v.civil/img_tables5_1.png
   grass-addons/grass7/vector/v.civil/img_tables6_1.png
   grass-addons/grass7/vector/v.civil/img_tables7_1.png
   grass-addons/grass7/vector/v.civil/road_base.py
   grass-addons/grass7/vector/v.civil/road_crosstools.py
   grass-addons/grass7/vector/v.civil/road_displ.py
   grass-addons/grass7/vector/v.civil/road_marks.py
   grass-addons/grass7/vector/v.civil/road_plant.py
   grass-addons/grass7/vector/v.civil/road_profiles.py
   grass-addons/grass7/vector/v.civil/road_road.py
   grass-addons/grass7/vector/v.civil/road_tables.py
   grass-addons/grass7/vector/v.civil/road_terr.py
   grass-addons/grass7/vector/v.civil/road_topotools.py
   grass-addons/grass7/vector/v.civil/road_trans.py
   grass-addons/grass7/vector/v.civil/road_vertical.py
   grass-addons/grass7/vector/v.civil/v.road.html
   grass-addons/grass7/vector/v.civil/v.road.py
Modified:
   grass-addons/grass7/vector/v.civil/Makefile
Log:
v.civil.road: Rewritten using pygrass to v.road

Modified: grass-addons/grass7/vector/v.civil/Makefile
===================================================================
--- grass-addons/grass7/vector/v.civil/Makefile	2016-07-01 22:16:30 UTC (rev 68830)
+++ grass-addons/grass7/vector/v.civil/Makefile	2016-07-01 22:30:22 UTC (rev 68831)
@@ -1,13 +1,14 @@
+# fix this relative to include/
+# or use absolute path to the GRASS source code
+
 MODULE_TOPDIR = ../..
+PGM = v.road
 
-SUBDIRS = \
-        v.civil.river \
-        v.civil.road \
-        v.civil.tools \
-        v.civil.topo
+ETCFILES = road_road road_base road_plant road_vertical road_displ \
+	   road_terr road_profiles road_trans road_tables road_marks \
+	   road_crosstools road_topotools
 
-include $(MODULE_TOPDIR)/include/Make/Dir.make
+include $(MODULE_TOPDIR)/include/Make/Script.make
+include $(MODULE_TOPDIR)/include/Make/Python.make
 
-default: parsubdirs
-
-install: installsubdirs
+default: script

Added: grass-addons/grass7/vector/v.civil/img1.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img1.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img2.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img2.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img2_1.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img2_1.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img2_2.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img2_2.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img3.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img3.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img3_2.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img3_2.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img4.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img4.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img4_1.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img4_1.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img4_2.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img4_2.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img4_3.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img4_3.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img5.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img5.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img6.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img6.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img6_1.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img6_1.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img7.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img7.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img8.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img8.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img8_1.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img8_1.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img8_2.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img8_2.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img_a_plan.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img_a_plan.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img_a_tooladdrow.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img_a_tooladdrow.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img_a_topotools_1.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img_a_topotools_1.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img_a_vcivilroad_7.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img_a_vcivilroad_7.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img_a_vert.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img_a_vert.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img_tables1.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img_tables1.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img_tables2.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img_tables2.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img_tables2_2.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img_tables2_2.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img_tables2_3.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img_tables2_3.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img_tables3.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img_tables3.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img_tables3_1.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img_tables3_1.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img_tables3_2.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img_tables3_2.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img_tables4_1.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img_tables4_1.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img_tables4_2.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img_tables4_2.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img_tables5_1.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img_tables5_1.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img_tables6_1.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img_tables6_1.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/img_tables7_1.png
===================================================================
(Binary files differ)


Property changes on: grass-addons/grass7/vector/v.civil/img_tables7_1.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass-addons/grass7/vector/v.civil/road_base.py
===================================================================
--- grass-addons/grass7/vector/v.civil/road_base.py	                        (rev 0)
+++ grass-addons/grass7/vector/v.civil/road_base.py	2016-07-01 22:30:22 UTC (rev 68831)
@@ -0,0 +1,1343 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Thu Jul 31 12:02:25 2014
+
+ at author: meskal
+"""
+
+#
+# import pygrass modules
+#
+import math
+import re
+# from grass.pygrass.vector import VectorTopo
+from grass.pygrass.vector import VectorTopo
+from grass.pygrass.vector.geometry import Point
+from grass.pygrass.vector.geometry import Line
+
+
+def azimut(p_ini=None, p_end=None):
+    """Return Azimut of two point (x1,y1) (x2,y2), Rad from North
+       to clockwise
+
+        >>> azimut(Point(0,0), Point(10,10))
+        0.7853981633974483
+    """
+    if p_ini.x > p_end.x and p_ini.y == p_end.y:
+        azi = 3 * math.pi / 2
+    elif p_ini.x < p_end.x and p_ini.y == p_end.y:
+        azi = math.pi / 2
+    elif p_ini.x == p_end.x and p_ini.y > p_end.y:
+        azi = math.pi
+    elif p_ini.x == p_end.x and p_ini.y < p_end.y:
+        azi = 2 * math.pi
+    elif p_ini.x == p_end.x and p_ini.y == p_end.y:
+        azi = 0
+    else:
+        azi = math.atan((p_end.x - p_ini.x) / (p_end.y - p_ini.y))
+        # if x1> x2 and y1 == y2: az = az + pi # az>0 -> az > 0
+        if p_ini.x < p_end.x and p_ini.y > p_end.y:
+            azi = azi + math.pi  # az<0 -> az > 100
+        elif p_ini.x > p_end.x and p_ini.y > p_end.y:
+            azi = azi + math.pi  # az>0 -> az > 200
+        elif p_ini.x > p_end.x and p_ini.y < p_end.y:
+            azi = azi + 2 * math.pi  # az<0 -> az > 300
+    return azi
+
+
+# def fix_azimuth(azi):
+#    """ Return
+#    """
+#    if azi > 2 * math.pi:
+#        return azi - 2 * math.pi
+#    else:
+#        return azi + 2 * math.pi
+
+
+def aprox_coord(leng, tau):
+    """Return coord (x1,y1) of a clothoid given the angle Tau and length
+    ::
+    >>> aprox_coord(10, 5)
+    [-50, -50]
+    """
+    n_iter = 10
+    c_x = 0
+    c_y = 0
+    for n_i in range(n_iter):
+        c_x += (((-1) ** n_i * tau ** (2 * n_i)) /
+                ((4 * n_i + 1) * math.factorial(2 * n_i)))
+        c_y += (((-1) ** n_i * tau ** (2 * n_i + 1)) /
+                ((4 * n_i + 3) * math.factorial(2 * n_i + 1)))
+    c_x = c_x * leng
+    c_y = c_y * leng
+    return [c_x, c_y]
+
+
+def aprox_coord2(radio, tau):
+    """Return coord (x1,y1) of a clothoid given the angle Tau and Radio
+    ::
+    >>> aprox_coord(100, 50)
+    [-1411567899002100L, -3476091295999800L]
+    """
+    n_iter = 10
+    c_x = 0
+    c_y = 0
+    for n_i in range(n_iter):
+        c_x += (((-1) ** n_i * (2 * tau ** (2 * n_i + 1) /
+                 ((4 * n_i + 1) * math.factorial(2 * n_i)))) -
+                ((-1) ** n_i * (tau ** (2 * n_i + 1) /
+                 math.factorial(2 * n_i + 1))))
+
+        c_y += (((-1) ** n_i * (2 * tau ** (2 * n_i + 2) /
+                 ((4 * n_i + 3) * math.factorial(2 * n_i + 1)))) +
+                ((-1) ** n_i * (tau ** (2 * n_i) / math.factorial(2 * n_i))))
+
+    c_x = c_x * radio
+    c_y = c_y * radio - radio
+    return [c_x, c_y]
+
+
+def cloth_local(radio, a_clot):
+    """Return clothoid parameters in local coord
+    ::
+    >>> cloth_local(40,20)
+    {'tau': 0, 'x_e': 10, 'leng': 10, 'x_o': 10.0, 'y_o': 0.0, 'y_e': 0}
+    """
+    if radio == 0:
+        leng, tau = 0, 0
+    else:
+        leng = a_clot ** 2 / abs(radio)
+        tau = leng / (2 * radio)
+    x_e, y_e = aprox_coord(leng, tau)
+    x_o = x_e - radio * math.sin(tau)
+    y_o = y_e + radio * math.cos(tau) - radio
+
+    return {'x_o': x_o, 'y_o': y_o, 'tau': tau, 'leng': leng, 'x_e': x_e,
+            'y_e': y_e}
+
+
+def clotoide_get_a(radio, yo_ent, sobreancho, izq):
+    """Return param A of a clothoid in a curve with widening
+    """
+    inc = math.pi / 200
+    tau = 0.0001 * math.pi / 200
+    y_o = aprox_coord2(abs(radio), tau)[1]
+    if (izq and radio > 0) or (izq == 0 and radio < 0):
+        sobreancho = sobreancho
+    elif (izq and radio < 0) or (izq == 0 and radio > 0):
+        sobreancho = sobreancho * (-1)
+
+    # Comprobar que el sobreancho sea mayor que el retranqueo
+    while abs(y_o - (yo_ent - sobreancho)) > 0.0001:
+
+        y_o = aprox_coord2(abs(radio), tau)[1]
+        if y_o > yo_ent - sobreancho:
+            tau = tau - inc
+            inc = inc / 10
+        else:
+            tau = tau + inc
+
+    leng = tau * 2 * abs(radio)
+    return math.sqrt(leng * abs(radio))
+
+
+def bisecc(r_pnt, align):
+    """Return cutoff roadpoint of a straight, given by a roadpoint with its
+    azimuth, and a road object defined by the funct function
+    """
+    recta2 = r_pnt.normal(math.pi)
+    len_a = -0.00001
+    len_b = align.length()
+    eq_a = align.funct(len_a, recta2)
+    eq_b = align.funct(len_b, recta2)
+
+    if round(eq_a[0], 5) * round(eq_b[0], 5) > 0:
+        return None
+
+    len_c = (len_a + len_b) / 2.0
+    while (len_b - len_a) / 2.0 > 0.00001:
+        eq_c = align.funct(len_c, recta2)
+        eq_a = align.funct(len_a, recta2)
+        if eq_c[0] == 0:
+            continue
+        elif eq_a[0] * eq_c[0] <= 0:
+            len_b = len_c
+        else:
+            len_a = len_c
+        len_c = (len_a + len_b) / 2.0
+
+    return RoadPoint(Point(eq_c[1], eq_c[2], 0), len_c, r_pnt.azi, '')
+
+
+def format_pk(funcion_f):
+    """Return the pk format 10+000.001 of a funtion
+    """
+    def funcion_r(*arg):
+        """Return
+        """
+        ipk = funcion_f(*arg)
+        ipk = round(ipk, 4)
+        if str(ipk).find(".") == -1:
+            integer = str(ipk)
+            decimal = "0"
+        else:
+            integer, decimal = str(ipk).split(".")
+        integer = re.sub(r"\B(?=(?:\d{3})+$)", "+", "{:0>4}".format(integer))
+        return integer + "." + decimal
+    return funcion_r
+
+
+def write_objs(allrectas, radio):
+    """
+    """
+    new2 = VectorTopo('AAAAA__' + str(int(radio)))
+    # cols = [(u'cat',       'INTEGER PRIMARY KEY'),
+    #        (u'elev',      'INTEGER')]
+
+    new2.open('w')
+    for obj in allrectas:
+        new2.write(obj)
+    # new2.table.conn.commit()
+    new2.close()
+
+
+# =============================================
+# ROAD POINT
+# =============================================
+
+class RoadPoint(Point, object):
+    """RoadPoint object, is a Point with pk and azimuth, and others params
+    >>> r_pnt = RoadPoint(Point(1,1,0), 0, 0)
+    """
+    def __init__(self, point=None, npk=None, azi=None, p_type=None):
+        """ Return
+        """
+        super(RoadPoint, self).__init__(point.x, point.y, point.z)
+
+        self.x = point.x
+        self.y = point.y
+        self.z = point.z
+        self.point2d = Point(self.x, self.y)
+
+        self.npk = npk
+        self.azi = azi
+        self.p_type = p_type
+        self.align = ''
+        self.incli = 0
+
+        self.v_param = 0
+        self.v_type = 'none'
+
+        self.terr = 0
+        self.terr_type = 'none'
+
+        self.dist_displ = 0
+        self.acum_pk = 0
+
+        if self.z is None:
+            self.z = 0
+
+    def __repr__(self):
+        return ("RoadPoint(" + str(self.x) + ", " + str(self.y) + ", " +
+                str(self.z) + ", " +
+                str(self.npk) + ", " + str(self.azi) + ", " +
+                str(self.p_type) + ", " + str(self.align) + ", " +
+                str(self.v_param) + ", " + str(self.v_type) + ", " +
+                str(self.terr) + ", " + str(self.terr_type) + ", " +
+                str(self.dist_displ) + ")")
+
+    def get_wkt(self):
+        """Return a "well know text" (WKT) geometry string. ::
+
+        >>> pnt = Point(10, 100)
+        >>> pnt.get_wkt()
+        'POINT(10.000000 100.000000)'
+        """
+        return ("ROADPOINT(" + str(self.x) + ", " + str(self.y) + ", " +
+                str(self.z) + ", " +
+                str(self.npk) + ", " + str(self.azi) + ", " +
+                str(self.p_type) + ", " + str(self.align) + ", " +
+                str(self.v_param) + ", " + str(self.v_type) + ", " +
+                str(self.terr) + ", " + str(self.terr_type) + ", " +
+                str(self.dist_displ) + ")")
+
+    def get_info(self):
+        """Return point pk
+        """
+        sal = 'ROADPOINT( \n'
+        sal += ' Point(' + str(self.x) + ", " + str(self.y) + ", " + \
+               str(self.z) + ')\n'
+        sal += ' pk: ' + str(self.npk) + '\n'
+        sal += ' azimuth: ' + str(self.azi * 200 / math.pi) + '\n'
+        sal += ' p_type: ' + str(self.p_type) + '\n'
+        sal += ' align: ' + str(self.align) + '\n'
+        sal += ' v_param: ' + str(self.v_param) + '\n'
+        sal += ' v_type: ' + str(self.v_type) + '\n'
+        sal += ' z_terr: ' + str(self.terr) + '\n'
+        sal += ' terr_type: ' + str(self.terr_type) + '\n'
+        sal += ' dist displ: ' + str(self.dist_displ) + '\n)'
+
+        return sal
+
+    @format_pk
+    def get_pk(self):
+        """Return point pk
+        """
+        return float(self.npk)
+
+    def get_azi(self):
+        """Return azimuth of roadpoint in gon
+        >>> r_pnt = RoadPoint(Point(1,1,0), 0, 0.7853981633974483)
+        >>> r_pnt.get_azi()
+        50.0
+        """
+        return round(self.azi * 200 / math.pi, 4)
+
+    def azimuth(self, pnt2):
+        """Return azimuth of this roadpoint with another one
+        >>> r_pnt = RoadPoint(Point(1,1,0), 0, 0)
+        >>> r_pnt2 = RoadPoint(Point(2,2,0), 0, 0)
+        >>> r_pnt.azimuth(r_pnt2)
+        0.7853981633974483
+        """
+        return azimut(self, pnt2)
+
+    def distance2(self, pnt2):
+        """Return point pk
+        """
+        return math.sqrt((pnt2.x - self.x) ** 2 + (pnt2.y - self.y) ** 2)
+
+    def slope(self, pnt2):
+        """Return the slope between this point and the given one
+        """
+        # leng = Point.distance(pnt2)
+        leng = math.sqrt((pnt2.x - self.x) ** 2 + (pnt2.y - self.y) ** 2)
+        if leng == 0:
+            return 0
+        else:
+            return (pnt2.z - self.z) / leng
+
+    def slope2(self, pnt2):
+        """Return the slope between this point and the given one
+        """
+        if self.npk == pnt2.npk:
+            return 0
+        else:
+            return (pnt2.z - self.z) / (pnt2.npk - self.npk)
+
+    def get_straight(self, dist=1):
+        """ Return
+        """
+        pto_2 = self.project(dist, self.azi)
+        return Straight(self, pto_2)
+
+    def project(self, dist, azi, sig=1):
+        """ Return
+        """
+        return RoadPoint(Point(self.x + sig * dist * math.sin(azi),
+                               self.y + sig * dist * math.cos(azi)),
+                         self.npk, azi, '')
+
+    def parallel(self, dist, g90):
+        """ Return
+        """
+        return RoadPoint(Point(self.x + dist * math.sin(self.azi + g90),
+                               self.y + dist * math.cos(self.azi + g90)),
+                         self.npk, self.azi, self.p_type)
+
+    def normal(self, g90):
+        """ Return
+        """
+        return Straight(self.point2d, None, self.azi + g90, 20)
+
+
+# =============================================
+# ROAD LINE
+# =============================================
+
+class RoadLine(object):
+    """Class to manage list of roadpoints
+    """
+    def __init__(self, list_r_pnts, attrs=None, name=None):
+        """ Return
+        """
+#        super(RoadLine, self).__init__(list_r_pnts)
+#        if isinstance(list_r_pnts[0], list):
+#            self.list_r_pnts = list_r_pnts
+#        else:
+#            self.list_r_pnts = [list_r_pnts]
+
+        self.r_pnts = list_r_pnts
+        self.attrs = attrs
+        self.name = name
+#        self.pnts_char = pnts_char
+
+    def __getitem__(self, index):
+        return self.r_pnts[index]
+
+    def __setitem__(self, index, value):
+        self.r_pnts[index] = value
+
+    def __delitem__(self, index):
+        del self.r_pnts[index]
+
+    def __len__(self):
+        return len(self.r_pnts)
+
+    def __repr__(self):
+        return str(self.r_pnts)
+
+    def length(self):
+        """ Return
+        """
+        return len(self.r_pnts)
+
+    def is_in(self, r_pnt):
+        """ Return
+        """
+        if r_pnt.npk in [pnt.npk for pnt in self.r_pnts]:
+            return True
+        else:
+            return False
+
+    def insert(self, r_pnt):
+        """Insert a roadpoint with pk like index
+        """
+#        if not self.is_in(r_pnt):
+        for i, pnt in enumerate(self.r_pnts[:-1]):
+            if pnt.npk < r_pnt.npk < self.r_pnts[i + 1].npk:
+                self.r_pnts.insert(i + 1, r_pnt)
+
+#    def get_segments(self, charline):
+#        """Return
+#        """
+
+    def get_by_pk(self, npk):
+        """Return the roadpoint with npk
+        """
+        for pnt in self.r_pnts:
+            if pnt is not None:
+                if pnt.npk == npk:
+                    return pnt
+
+    def get_pnts_attrs(self):
+        """Return all roadpoints and their attributes
+        """
+        list_pnts = []
+        list_attrs = []
+        for r_pnt in self.r_pnts:
+            if r_pnt is not None:
+                list_pnts.append(r_pnt)
+                list_attrs.append([r_pnt.npk, self.name, r_pnt.azi,
+                                   r_pnt.p_type, r_pnt.align, r_pnt.v_param,
+                                   r_pnt.v_type, float(r_pnt.terr),
+                                   r_pnt.terr_type, r_pnt.dist_displ,
+                                   r_pnt.x, r_pnt.y, r_pnt.z, ''])
+        return list_pnts, list_attrs
+
+    def get_line_attrs(self, set_leng=None):
+        """Return Line or list of Lines, split if some roadpoint of the
+        roadline is None, and attributes
+        """
+        list_lines = [[]]
+        list_attrs = []
+        lista_lineas = []
+        for r_pnt in self.r_pnts:
+            if r_pnt is not None:
+                list_lines[-1].append(r_pnt)
+            elif list_lines[-1] != []:
+                list_lines.append([])
+        for i, lin in enumerate(list_lines):
+            if len(lin) != 0:
+                lista_lineas.append(Line(lin))
+                if set_leng:
+                    self.attrs[set_leng] = round(lista_lineas[-1].length(), 6)
+                list_attrs.append(self.attrs)
+        return lista_lineas, list_attrs
+
+#    def get_segm_attrs(self):
+#        """Return
+#        """
+#        list_lines = []
+#        list_attrs = []
+#        for i, pnt_char in enumerate(self.pnts_char[1:]):
+#            list_lines.append([self.pnts_char[i - 1]])
+#            for r_pnt in self.r_pnts:
+#                if r_pnt is not None:
+#                    if round(self.pnts_char[i - 1].npk, 6) < r_pnt.npk < \
+#                            pnt_char.npk:
+#                        list_lines[-1].append(r_pnt)
+#            list_lines[-1].append(pnt_char)
+#
+#            list_attrs.append([pnt_char.npk, pnt_char.p_type])
+#
+#        return list_lines, list_attrs
+
+
+#    def get_ras(self, r_line):
+#        """Return
+#        """
+#        line = []
+#        for r_pnt in r_line:
+#            line.append(Point(r_pnt.npk + self.zero_x,
+#                              (r_pnt.z - self.min_elev) * self.scale +
+#                              self.zero_y))
+#        return Line(line)
+#
+#    def get_terr(self, r_line):
+#        """Return
+#        """
+#        line = []
+#        for r_pnt in r_line:
+#            line.append(Point(r_pnt.npk + self.zero_x,
+#                              (r_pnt.terr - self.min_elev) * self.scale +
+#                              self.zero_y))
+#        return Line(line)
+
+    def get_area(self, pnts_line2):
+        """Return a closed polyline with this roadline and the reverse of the
+        given roadline
+        """
+        list_lines = []
+        pnts_line1 = self.r_pnts
+        line1, line2 = [[]], [[]]
+        for i in range(len(pnts_line1)):
+            if pnts_line1[i] is None or pnts_line2[i] is None:
+                if line1[-1] != [] and line2[-1] != []:
+                    line1.append([])
+                    line2.append([])
+            else:
+                line1[-1].append(pnts_line1[i])
+                line2[-1].append(pnts_line2[i])
+
+        line1 = [lin for lin in line1 if lin != []]
+        line2 = [lin for lin in line2 if lin != []]
+
+        for i in range(len(line1)):
+
+            line2[i] = line2[i][::-1]
+            line2[i].append(line1[i][0])
+            line1[i].extend(line2[i])
+
+            line = Line(line1[i])
+            list_lines.append(line)
+
+        return list_lines
+
+
+# =============================================
+# ROAD OBJ
+# =============================================
+
+class RoadObj(object):
+    """Road object, base of straight, curve, clothoid and parallel
+    """
+    def __init__(self, leng_obj):
+        """ Return
+        """
+        self.leng_obj = leng_obj
+        self.leng_accum = 0
+
+        self.pts_rest = 0
+        self.pts_accum = 0
+
+    def param(self):
+        """Return string with length of the object
+        """
+        return 'L=' + str(round(self.leng_obj, 4))
+
+    @format_pk
+    def get_leng_accum(self):
+        """Return the length accum
+        """
+        return self.leng_accum
+
+    @format_pk
+    def get_leng_accum2(self):
+        """Return the length accum and length of this
+        """
+        return self.leng_accum + self.leng_obj
+
+    def is_in(self, r_pnt):
+        """
+        """
+        if self.leng_accum <= r_pnt.npk < self.leng_accum + self.leng_obj:
+            return True
+        else:
+            return False
+
+    def grassrgb(self):
+        """Return the default rgb color for each object
+        """
+        if isinstance(self, Straight):
+            return '0:0:255'
+        elif isinstance(self, Curve):
+            return '0:255:0'
+        elif isinstance(self, Clothoid):
+            return '255:0:0'
+        else:
+            return '255:255:255'
+
+    def get_roadpoint(self, start):
+        """Return a roadpoint found by pk
+        """
+        if start == -1:
+            start = self.leng_obj
+        self.pts_accum = start
+        r_pnt = self.get_roadpnts(start, start, 1)[0]
+        r_pnt.npk = self.leng_accum + start
+        if start == 0:
+            # r_pnt.p_type = self.pto_ini()
+            r_pnt.p_type = self.__class__.__name__ + '_in'
+        elif start == self.leng_obj:
+            # r_pnt.p_type = self.pto_end()
+            r_pnt.p_type = self.__class__.__name__ + '_out'
+        return [r_pnt]
+
+#    def pto_ini(self):
+#        """ Return
+#        """
+#        if isinstance(self, Straight):
+#            return 'Straight_in'
+#        elif isinstance(self, Curve):
+#            return 'Curve_tan_in'
+#        elif isinstance(self, Clothoid):
+#            return 'Clothoid_tan_in'
+#        else:
+#            return 'No_name'
+#
+#    def pto_end(self):
+#        """ Return
+#        """
+#        if isinstance(self, Straight):
+#            return 'Straight_end'
+#        elif isinstance(self, Curve):
+#            return 'Curve_tan_out'
+#        elif isinstance(self, Clothoid):
+#            return 'Clothoid_tan_out'
+#        else:
+#            return 'No_name'
+
+#    def get_line(self, start, end, interv):
+#        """ Return
+#        """
+#        pnts = self.get_roadpnts(start, end, interv)
+#        lastpnt = self.get_roadpoint(-1)[0]
+#        if lastpnt not in pnts:
+#            pnts.append(lastpnt)
+#        return Line(pnts)
+
+
+# =============================================
+# STRAIGHT
+# =============================================
+
+class Straight(RoadObj, object):
+    """Object straight, line with two points or point azimuth and leng
+    ::
+    >>> line = Straight(Point(0,0,0), Point(10,10,0), 0, 0)
+    >>> line.length()
+    14.142135623730951
+    """
+    def __init__(self, pstart=None, pend=None, azi=None, leng=None):
+        """ Return
+        """
+        self.pstart = pstart
+        self.pend = pend
+        self.azi = azi
+        self.leng = leng
+
+#        self.pts_rest = 0
+#        self.pts_accum = 0
+
+        if self.azi and self.leng:
+            self.pend = Point(self.pstart.x + self.leng * math.sin(self.azi),
+                              self.pstart.y + self.leng * math.cos(self.azi))
+
+        super(Straight, self).__init__(self.length())
+
+    def __str__(self):
+        if not self.pstart.z:
+            self.pstart.z = 0.0
+        return self.get_wkt()
+
+    def __repr__(self):
+        if not self.pstart.z:
+            self.pstart.z = 0.0
+        return ("Straight(" + str(self.pstart.x) + ", " + str(self.pstart.y) +
+                ", " + str(self.pstart.z) + ", " + str(self.length()) + ", " +
+                str(self.azimuth()) + ", " + str(self.pend.x) + ", " +
+                str(self.pend.y) + ")")
+
+    def get_wkt(self):
+        """Return a "well know text" (WKT) geometry string. ::
+        ::
+        >>> pnt = Point(10, 100)
+        >>> pnt.get_wkt()
+        'POINT(10.000000 100.000000)'
+        """
+        return ("STRAIGHT(" + str(self.pstart.x) + ", " + str(self.pstart.y) +
+                ", " + str(self.pstart.z) + ", " + str(self.length()) + ", " +
+                str(self.azimuth()) + ", " + str(self.pend.x) + ", " +
+                str(self.pend.y) + ")")
+
+    def get_line(self):
+        """Return length of the straight
+        """
+        return Line([self.pstart, self.pend])
+
+    def length(self):
+        """Return length of the straight
+        """
+        return self.pstart.distance(self.pend)
+
+    def get_roadpnts(self, start, end, interv):
+        """Return list of axis points of a straight
+        ::
+        >>> line = Straight(Point(0,0,0), Point(10,10,0), 0, 0)
+        >>> line.get_roadpnts(3,7,1) # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
+        [RoadPoint(2.12132034356, 2.12132034356, 0.0, 0, 0.785398163397,
+        ...
+        """
+        accum = self.pts_accum
+        if end == -1:
+            end = self.length()
+
+        azi = self.azimuth()
+        list_pts = []
+        while start <= end:
+            pnt = Point(self.pstart.x + start * math.sin(azi),
+                        self.pstart.y + start * math.cos(azi), self.pstart.z)
+
+            list_pts.append(RoadPoint(pnt, accum, round(azi, 6), 'Line'))
+            accum += interv
+            start += interv
+
+        self.pts_rest = end - (start - interv)
+        self.pts_accum = accum - interv
+        return list_pts
+
+    def azimuth(self):
+        """Return azimut of the straight
+        ::
+        >>> line = Straight(Point(0,0,0), Point(10,10,0), 0, 0)
+        >>> line.azimuth()
+        0.7853981633974483
+        """
+        return azimut(self.pstart, self.pend)
+
+    def slope(self):
+        """Return slope of the straight
+        ::
+        >>> line = Straight(Point(0,0,0), Point(10,10,10), 0, 0)
+        >>> line.slope()
+        1.0
+        """
+        return (self.pend.z - self.pstart.z) / (self.pend.x - self.pstart.x)
+
+    def angle(self, recta2):
+        """Return angle between two straights
+        ::
+        >>> line = Straight(Point(0,0,0), Point(10,10,10), 0, 0)
+        >>> line2 = Straight(Point(30,0,0), Point(20,10,10), 0, 0)
+        >>> line.angle(line2) * 200 / math.pi
+        100.0
+        """
+        az_ent = azimut(self.pstart, self.pend)
+        az_sal = azimut(recta2.pstart, recta2.pend)
+        a_w = abs(azimut(self.pstart, self.pend) -
+                  azimut(recta2.pstart, recta2.pend))
+        if((self.pstart.x <= self.pend.x and self.pstart.y <= self.pend.y) or
+           (self.pstart.x <= self.pend.x and self.pstart.y >= self.pend.y)):
+            if az_ent < az_sal and az_ent + math.pi < az_sal:
+                a_w = 2 * math.pi - abs(az_ent - az_sal)
+
+        if((self.pstart.x >= self.pend.x and self.pstart.y >= self.pend.y) or
+           (self.pstart.x >= self.pend.x and self.pstart.y <= self.pend.y)):
+            # "3er o 4to cuadrante"
+            if az_ent > az_sal and az_ent - math.pi > az_sal:
+                a_w = 2 * math.pi - abs(az_ent - az_sal)
+        return a_w
+
+    def cutoff(self, recta2):
+        """Return the cutoff point between this straight an a given one.
+        ::
+        >>> line = Straight(Point(0,0,0), Point(10,10,10), 0, 0)
+        >>> line2 = Straight(Point(30,0,0), Point(20,10,10), 0, 0)
+        >>> line.cutoff(line2)
+        RoadPoint(15.0, 15.0, 0.0, 21.2132034356, 0, , , 0, none, 0, none, 0)
+        """
+        if self.pstart.x == self.pend.x:
+            m_2 = (recta2.pend.y - recta2.pstart.y) / \
+                  (recta2.pend.x - recta2.pstart.x)
+            coord_x = self.pstart.x
+            coord_y = recta2.pstart.y + m_2 * (self.pstart.x - recta2.pstart.x)
+        elif recta2.pstart.x == recta2.pend.x:
+            m_1 = (self.pend.y - self.pstart.y) / (self.pend.x - self.pstart.x)
+            coord_x = recta2.pstart.x
+            coord_y = self.pstart.y + m_1 * (recta2.pstart.x - self.pstart.x)
+        else:
+            m_1 = (self.pend.y - self.pstart.y) / (self.pend.x - self.pstart.x)
+            m_2 = (recta2.pend.y - recta2.pstart.y) / \
+                  (recta2.pend.x - recta2.pstart.x)
+            coord_x = (m_1 * self.pstart.x - m_2 * recta2.pstart.x -
+                       self.pstart.y + recta2.pstart.y) / (m_1 - m_2)
+            coord_y = m_1 * (coord_x - self.pstart.x) + self.pstart.y
+
+        return RoadPoint(Point(coord_x, coord_y),
+                         self.pstart.distance(Point(coord_x, coord_y)),
+                         self.azi, '')
+
+    def funct(self, leng, recta2):
+        """Funtion for use with bisecc
+        """
+        x_1 = self.pstart.x + leng * math.sin(self.azimuth())
+        y_1 = self.pstart.y + leng * math.cos(self.azimuth())
+        eq1 = y_1 - (recta2.pstart.y - math.tan(recta2.azimuth()) *
+                     (x_1 - recta2.pstart.x))
+        return [eq1, x_1, y_1]
+
+    def find_cutoff(self, r_pnt):
+        """Return the cutoff between this straight and other, given a r_pnt
+        with its azimuth.
+        >>> line = Straight(Point(0,0,0), Point(20,20,10), 0, 0)
+        >>> r_pnt = RoadPoint(Point(30,0,0), 0, line.azimuth(), 0)
+        >>> line.find_cutoff(r_pnt) # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
+        RoadPoint(14.9999997412, 14.9999997412, 0.0, 21.2132039637,
+        ...
+        """
+        r_pnt_d = bisecc(r_pnt, self)
+        if r_pnt_d is not None:
+            r_pnt_d.p_type = 'Line'
+        return r_pnt_d
+
+    def distance(self, pnt):
+        """Return distace from a point to this straight
+        >>> line = Straight(Point(0,0,0), Point(20,20,10), 0, 0)
+        >>> line.distance(Point(10,0,0))
+        7.071067811865475
+        """
+        if self.pstart.x == self.pend.x:
+            slope = 0
+        else:
+            slope = (self.pend.x - self.pstart.x) / \
+                    (self.pend.y - self.pstart.y)
+        rest = self.pstart.y + slope * self.pstart.x
+        return (slope * pnt.x + pnt.y - rest) / math.sqrt(slope ** 2 + 1)
+
+    def parallel(self, dist, radio):
+        """Return a parallel straight with a given distance and side given by
+        the sing of radio.
+        >>> line = Straight(Point(0,0,0), Point(20,20,10), 0, 0)
+        >>> line.parallel(10, -1) # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
+        Straight(-7.07106781187, 7.07106781187, 0.0, 28.2842712475,
+        ...
+        """
+        if radio > 0:
+            g90 = math.pi / 2
+        else:
+            g90 = -math.pi / 2
+
+        x_1 = self.pstart.x + dist * math.sin(self.azimuth() + g90)
+        y_1 = self.pstart.y + dist * math.cos(self.azimuth() + g90)
+
+        x_2 = self.pend.x + dist * math.sin(self.azimuth() + g90)
+        y_2 = self.pend.y + dist * math.cos(self.azimuth() + g90)
+
+        return Straight(Point(x_1, y_1), Point(x_2, y_2))
+
+
+# =============================================
+# CURVE
+# =============================================
+
+class Curve(RoadObj, object):
+    """Object Curve, curve with radio, angle, initial azimuth and center
+    ::
+    >>> r_pnt = RoadPoint(Point(50,50,0), 0, 0, 0)
+    >>> curve = Curve(10.0, 1.5707963268, 0.7853981633974483, r_pnt)
+    >>> curve.length()
+    15.707963268
+    """
+    def __init__(self, radio=0, alpha=0, az_ini=0, p_center=None):
+
+        self.radio = radio
+        self.alpha = alpha
+        self.az_ini = az_ini
+
+        self.p_center = p_center
+
+        self.pts_rest = 0
+        self.pts_accum = 0
+
+        if self.radio > 0:
+            self.az_fin = self.az_ini + self.alpha
+        else:
+            self.az_fin = self.az_ini - self.alpha
+
+        if self.az_fin > 2 * math.pi:
+            self.az_fin = self.az_fin - 2 * math.pi
+        elif self.az_fin < 0:
+            self.az_fin = self.az_fin + 2 * math.pi
+
+        super(Curve, self).__init__(self.length())
+
+    def __str__(self):
+        return self.get_wkt()
+
+    def __repr__(self):
+
+        return ("Curve(" + str(self.radio) + ", " + str(self.alpha) + ", " +
+                str(self.p_center.x) + ", " + str(self.p_center.y) + ", " +
+                str(self.az_ini) + ", " + str(self.az_fin) + ", " +
+                str(self.length()) + ", " + str(self.pnt_ar()) + ", " +
+                str(self.pnt_ra()) + ", " + ")")
+
+    def get_wkt(self):
+        """Return a "well know text" (WKT) geometry string. ::
+
+        >>> pnt = Point(10, 100)
+        >>> pnt.get_wkt()
+        'POINT(10.000000 100.000000)'
+        """
+        return ("CURVE(" + str(self.radio) + ", " + str(self.alpha) + ", " +
+                str(self.p_center.x) + ", " + str(self.p_center.y) + ", " +
+                str(self.az_ini) + ", " + str(self.az_fin) + ", " +
+                str(self.length()) + ", " + str(self.pnt_ar()) + ", " +
+                str(self.pnt_ra()) + ", " + ")")
+
+    def param(self):
+        """Return a string with the radio of the curve
+        """
+        return 'R=' + str(self.radio)
+
+    def length(self):
+        """Return length of the curve
+        """
+        return abs(self.radio) * self.alpha
+
+    def get_roadpnts(self, start, end, interv):
+        """ Return list of points of the curve, and set length of last point
+        to the end and accumulated length
+        ::
+        >>> r_pnt = RoadPoint(Point(50,50,0), 0, 0, 0)
+        >>> curve = Curve(10.0, 1.5707963268, 0.7853981633974483, r_pnt)
+        >>> curve.get_roadpnts(0, -1, 1.0) # doctest: +ELLIPSIS \
+                                                      +NORMALIZE_WHITESPACE
+        [RoadPoint(57.0710678119, 57.0710678119, 0.0, 0,
+        ...
+        """
+        accum = self.pts_accum
+        az_ini = self.az_ini
+        if end == -1:
+            end = self.length()
+        list_pts = []
+        interv = abs(float(interv) / float(self.radio))
+
+        az_ini = az_ini + start / self.radio
+        az_fin = az_ini + (end - start) / self.radio
+
+        inc = az_ini
+        if self.radio > 0:
+
+            while inc <= az_fin:
+                pnt_1 = self.p_center.project(self.radio, inc)
+                az1 = (inc + math.pi / 2)
+                inc += interv
+
+                if az1 > 2 * math.pi:
+                    az1 = az1 - 2 * math.pi
+
+                list_pts.append(RoadPoint(pnt_1, accum, round(az1, 6), 'Curve'))
+                accum += interv * abs(self.radio)
+            rest = (az_fin - (inc - interv)) * abs(self.radio)
+
+        elif self.radio < 0:
+
+            while inc >= az_fin:
+                pnt_1 = self.p_center.project(self.radio, inc, -1)
+                az1 = (inc - math.pi / 2)
+                inc -= interv
+
+                if az1 < 0:
+                    az1 = az1 + 2 * math.pi
+
+                list_pts.append(RoadPoint(pnt_1, accum, round(az1, 6), 'Curve'))
+                accum += interv * abs(self.radio)
+            rest = ((inc + interv) - az_fin) * abs(self.radio)
+
+        self.pts_rest = rest
+        self.pts_accum = accum - interv * abs(self.radio)
+        return list_pts
+
+    def distance(self, pnt):
+        """Return distance from a point to the curve
+        ::
+        >>> r_pnt = RoadPoint(Point(50,50,0), 0, 1.5707963268, 0)
+        >>> curve = Curve(10.0, 1.5707963268, 0.7853981633974483, r_pnt)
+        >>> curve.distance(Point(0,0))
+        60.710678118654755
+        """
+        line = Straight(self.p_center, pnt)
+        return line.length() - self.radio
+
+    def pnt_ar(self):
+        """Return the first point of the curve
+        """
+        return self.p_center.project(abs(self.radio), self.az_ini)
+
+    def pnt_ra(self):
+        """Return the last point of the curve
+        """
+        return self.p_center.project(abs(self.radio), self.az_fin)
+
+    def cutoff(self, recta2):
+        """Return the cutoff between this curve and a straight
+        """
+        dist = recta2.distance(self.p_center)
+        if dist == 0:
+            pnt_1 = self.p_center.project(self.radio, recta2.azimuth())
+        else:
+            phi = math.acos(dist / self.radio)
+            pnt_1 = self.p_center.project(self.radio, recta2.azimuth() +
+                                          math.pi / 2 + phi)
+        return pnt_1
+
+    def funct(self, leng, recta2):
+        """Funtion for use with bisecc
+        """
+        if self.radio > 0:
+            if self.az_ini > self.az_fin:
+                self.az_ini = self.az_ini - 2 * math.pi
+            x_1 = self.p_center.x + self.radio * \
+                math.sin(self.az_ini + leng / abs(self.radio))
+            y_1 = self.p_center.y + self.radio * \
+                math.cos(self.az_ini + leng / abs(self.radio))
+        elif self.radio < 0:
+            if self.az_ini < self.az_fin:
+                self.az_fin = self.az_fin - 2 * math.pi
+            x_1 = self.p_center.x - self.radio * \
+                math.sin(self.az_ini - leng / abs(self.radio))
+            y_1 = self.p_center.y - self.radio * \
+                math.cos(self.az_ini - leng / abs(self.radio))
+
+        eq1 = y_1 - (recta2.pstart.y - math.tan(recta2.azimuth()) *
+                     (x_1 - recta2.pstart.x))
+        return [eq1, x_1, y_1]
+
+    def find_cutoff(self, r_pnt):
+        """Return the cutoff between this curve and a straight, given by r_pnt
+        with its azimuth.
+        """
+        r_pnt_d = bisecc(r_pnt, self)
+        if r_pnt_d is not None:
+            r_pnt_d.p_type = 'Curve_'
+        return r_pnt_d
+
+
+# =============================================
+# CLOTHOID
+# =============================================
+
+class Clothoid(RoadObj, object):
+    """Object Clothoid, with param A, radio, initial azimuth, in or out,
+    and center of the curve. Other_local coord in local of other clothoid
+    ::
+    """
+    def __init__(self, a_clot=0, radio=0, azi=0, inout='', other_local=None,
+                 p_center=None):
+
+        self.radio = radio
+        self.a_clot = a_clot
+        self.other_local = other_local
+        self.azi = azi
+        self.inout = inout
+        self.p_center = p_center
+
+        self.pts_rest = 0
+        self.pts_accum = 0
+
+        if self.radio > 0:
+            self.g90 = math.pi / 2
+        else:
+            self.g90 = -math.pi / 2
+
+        if self.other_local:
+            self.leng_rest = self.other_local['leng']
+        else:
+            self.leng_rest = 0
+
+        self.pnt_r = None
+        self.pnt_d = None
+        self.pnt_p = None
+
+        self.local = cloth_local(self.radio, self.a_clot)
+
+        if self.inout == 'in':
+
+            if self.a_clot <= 0:
+                self.pnt_r = self._pnt_ar()
+                self.pnt_d = self.pnt_r
+                self.pnt_p = self.pnt_r
+            else:
+                self.pnt_d = self._pnt_ad()
+                self.pnt_r = self._pnt_ar()
+                self.pnt_p = self.pnt_d
+
+                if self.other_local:
+                    self.leng_rest = self.other_local['leng']
+                    self.pnt_p = self._pnt_adp()
+        else:
+            if self.a_clot <= 0:
+                self.pnt_r = self._pnt_ra()
+                self.pnt_d = self.pnt_r
+                self.pnt_p = self.pnt_r
+            else:
+                self.pnt_d = self._pnt_da()
+                self.pnt_r = self._pnt_ra()
+                self.pnt_p = self.pnt_d
+
+                if self.other_local:
+                    self.leng_rest = self.other_local['leng']
+                    self.pnt_p = self._pnt_dap()
+
+        super(Clothoid, self).__init__(self.length())
+
+    def __str__(self):
+        return self.get_wkt()
+
+    def __repr__(self):
+        return ("Clothoid(" + str(self.a_clot) + ", " + str(self.azi) +
+                ", " + str(self.pnt_d) + ", " +
+                str(self.pnt_r.x) + ", " + str(self.pnt_r.y) + ", " +
+                str(self.length()) + ", " +
+                str(self.radio) + ", " + str(self.leng_rest) + ", " +
+                str(self.pnt_p.x) + ", " + str(self.pnt_p.y) + ", " +
+                self.inout + ")")
+
+    def get_wkt(self):
+        """Return a "well know text" (WKT) geometry string. ::
+
+        >>> pnt = Point(10, 100)
+        >>> pnt.get_wkt()
+        'POINT(10.000000 100.000000)'
+        """
+        return ("CLOTHOID(" + str(self.a_clot) + ", " + str(self.azi) +
+                ", " + str(self.pnt_d) + ", " + str(self.pnt_r) + ", " +
+                str(self.length()) + ", " +
+                str(self.radio) + ", " + str(self.leng_rest) + ", " +
+                str(self.pnt_p) + ", " + self.inout + ")")
+
+    def param(self):
+        """Return a string with the parameter A of the clothoid
+        """
+        return 'A=' + str(self.a_clot)
+
+    def length(self):
+        """Return length of the clothoid
+        """
+        if self.a_clot <= 0:
+            return 0
+        elif self.other_local:
+            return self.other_local['leng'] - self.leng_rest
+        else:
+            return self.local['leng']
+
+    def get_roadpnts(self, start, end, interv):
+        """Return list of points of the curve, and set length of last point
+        to the end and accumulated length
+        ::
+        >>> r_pnt = RoadPoint(Point(50,50,0), 0, 0, 0)
+        >>> cloth = Clothoid(20, 40, 0, 'in', None, r_pnt)
+        >>> cloth.get_roadpnts(0, -1, 1) # doctest: +ELLIPSIS \
+                                                      +NORMALIZE_WHITESPACE
+        [RoadPoint(10.0, 40.0000001, 0.0, 0,
+        ...
+        """
+        if end == -1:
+            end = self.length()
+
+        if self.inout == 'in':
+            return self._get_pts_clot_in(start, end, interv)
+        elif self.inout == 'out':
+            return self._get_pts_clot_out(start, end, interv)
+
+    def _get_pts_clot_in(self, start, end, interv):
+        """ Return list of axis points of clothoid in, and set the rest to
+        the end of the clothoid and accum length
+        """
+        accum = self.pts_accum
+        list_pts = []
+        while start <= end:
+            if start == 0:
+                start = 0.0000001
+            rad_clo = self.a_clot ** 2 / start
+            tau_clo = start / (2 * rad_clo)
+            x_o, y_o = aprox_coord(start, tau_clo)
+            x_1, y_1 = self.cloth_global(x_o, y_o)
+            azi1 = self.pnt_azimuth(tau_clo)
+            list_pts.append(RoadPoint(Point(x_1, y_1, 0), accum,
+                                      round(azi1, 6), 'Clot_in'))
+            accum += interv
+            start = start + interv
+
+        self.pts_rest = end - (start - interv)
+        self.pts_accum = accum - interv
+        return list_pts
+
+    def _get_pts_clot_out(self, start, end, interv):
+        """ Return list of axis points of clothoid out, and set the rest to
+        the end of the clothoid and accum length
+        """
+        accum = self.pts_accum
+        list_pts = []
+        start2 = self.length() - end
+        end2 = self.length() - start
+
+        while start2 <= end2:
+            if end2 == 0:
+                end2 = 0.0000001
+
+            rad_clo = self.a_clot ** 2 / end2
+            tau_clo = end2 / (2 * rad_clo)
+            x_o, y_o = aprox_coord((end2), tau_clo)
+            x_1, y_1 = self.cloth_global(x_o, y_o)
+            azi1 = self.pnt_azimuth(tau_clo)
+            list_pts.append(RoadPoint(Point(x_1, y_1, 0), accum,
+                                      round(azi1, 6), 'Clot_out'))
+            accum += interv
+            end2 = end2 - interv
+
+        self.pts_rest = start2 + (end2 + interv)
+        self.pts_accum = accum - interv
+
+        return list_pts
+
+    def _pnt_ar(self):
+        """Return the first point of the clothoid in
+        """
+        return self.p_center.project(abs(self.radio),
+                                     self.azi - self.g90 + self.local['tau'])
+
+    def _pnt_ad(self):
+        """Return the last point of the clothoid in
+        """
+        pnt_t1 = self.p_center.project(abs(self.radio + self.local['y_o']),
+                                       self.azi - self.g90)
+
+        return pnt_t1.project(self.local['x_o'], self.azi + math.pi)
+
+    def _pnt_ra(self):
+        """Return the first point of the clothoid out
+        """
+        return self.p_center.project(abs(self.radio),
+                                     self.azi - self.g90 - self.local['tau'])
+
+    def _pnt_da(self):
+        """Return the last point of the clothoid out
+        """
+        pnt_t1 = self.p_center.project(abs(self.radio + self.local['y_o']),
+                                       self.azi - self.g90)
+        return pnt_t1.project(self.local['x_o'], self.azi)
+
+    def _pnt_adp(self):
+        """Return
+        """
+        if self.radio > 0:
+            xadp = self.pnt_d.x - self.other_local['x_e'] * \
+                math.sin(-self.azi) + self.local['y_e'] * math.cos(-self.azi)
+            yadp = self.pnt_d.y + self.other_local['x_e'] * \
+                math.cos(-self.azi) + self.local['y_e'] * math.sin(-self.azi)
+
+        elif self.radio < 0:
+            xadp = self.pnt_d.x + self.other_local['x_e'] * \
+                math.sin(-self.azi) - self.local['y_e'] * math.cos(-self.azi)
+            yadp = self.pnt_d.y + self.other_local['x_e'] * \
+                math.cos(-self.azi) + self.local['y_e'] * math.sin(-self.azi)
+        return Point(xadp, yadp)
+
+    def _pnt_dap(self):
+        """ Return
+        """
+        if self.radio > 0:
+            xdap = self.pnt_d.x - self.other_local['x_e'] * \
+                math.sin(-self.azi) + self.local['y_e'] * math.cos(-self.azi)
+            ydap = self.pnt_d.y - self.other_local['x_e'] * \
+                math.cos(-self.azi) - self.local['y_e'] * math.sin(-self.azi)
+
+        elif self.radio < 0:
+            xdap = self.pnt_d.x + self.other_local['x_e'] * \
+                math.sin(-self.azi) - self.local['y_e'] * math.cos(-self.azi)
+            ydap = self.pnt_d.y - self.other_local['x_e'] * \
+                math.cos(-self.azi) - self.local['y_e'] * math.sin(-self.azi)
+        return Point(xdap, ydap)
+
+    def pnt_azimuth(self, tau_clo):
+        """Return azimuth of a point of the clothoid, given the angle tau
+        """
+        if self.inout == 'in':
+            if self.radio > 0:
+                azi1 = self.azi + tau_clo
+            elif self.radio < 0:
+                azi1 = self.azi - tau_clo
+        elif self.inout == 'out':
+            if self.radio > 0:
+                azi1 = self.azi - tau_clo
+            elif self.radio < 0:
+                azi1 = self.azi + tau_clo
+        return azi1
+
+    def cloth_global(self, x_local, y_local):
+        """Return local coordinates in global coordinates
+        """
+        if self.inout == 'in':
+            if self.radio > 0:
+                x_1 = self.pnt_d.x - x_local * math.sin(-self.azi) + \
+                    y_local * math.cos(-self.azi)
+                y_1 = self.pnt_d.y + x_local * math.cos(-self.azi) + \
+                    y_local * math.sin(-self.azi)
+            elif self.radio < 0:
+                x_1 = self.pnt_d.x + x_local * math.sin(self.azi) - \
+                    y_local * math.cos(self.azi)
+                y_1 = self.pnt_d.y + x_local * math.cos(self.azi) + \
+                    y_local * math.sin(self.azi)
+        elif self.inout == 'out':
+            if self.radio > 0:
+                x_1 = self.pnt_d.x - x_local * math.sin(self.azi) + \
+                    y_local * math.cos(self.azi)
+                y_1 = self.pnt_d.y - x_local * math.cos(self.azi) - \
+                    y_local * math.sin(self.azi)
+            elif self.radio < 0:
+                x_1 = self.pnt_d.x + x_local * math.sin(-self.azi) - \
+                    y_local * math.cos(-self.azi)
+                y_1 = self.pnt_d.y - x_local * math.cos(-self.azi) - \
+                    y_local * math.sin(-self.azi)
+        return x_1, y_1
+
+    def funct(self, leng, recta2):
+        """Funtion for use with bisecc
+        """
+        rad_i = self.a_clot ** 2 / leng
+        tau_i = leng / (2 * rad_i)
+        x_o, y_o = aprox_coord(leng, tau_i)
+        x_1, y_1 = self.cloth_global(x_o, y_o)
+
+        eq1 = y_1 - (recta2.pstart.y - math.tan((recta2.azimuth())) *
+                     (x_1 - recta2.pstart.x))
+        return [eq1, x_1, y_1]
+
+    def find_cutoff(self, r_pnt):
+        """Return the cutoff between this clothoid and straight, given by r_pnt
+        with its azimuth.
+        """
+        r_pnt_d = bisecc(r_pnt, self)
+        if r_pnt_d is not None:
+            if self.inout == 'out':
+                r_pnt_d.npk = self.length() - r_pnt_d.npk
+            r_pnt_d.p_type = 'Cloth_' + self.inout
+#            r_pnt_d.dist_displ = r_pnt.distance(r_pnt_d)
+        return r_pnt_d
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()


Property changes on: grass-addons/grass7/vector/v.civil/road_base.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: grass-addons/grass7/vector/v.civil/road_crosstools.py
===================================================================
--- grass-addons/grass7/vector/v.civil/road_crosstools.py	                        (rev 0)
+++ grass-addons/grass7/vector/v.civil/road_crosstools.py	2016-07-01 22:30:22 UTC (rev 68831)
@@ -0,0 +1,589 @@
+#!/usr/bin/python
+
+"""
+Sample Python script to access vector data using GRASS Ctypes
+interface
+"""
+
+import sys
+import os
+
+import math
+import grass.script as grass
+from grass.pygrass.vector import VectorTopo
+from grass.pygrass.vector.geometry import Point
+# from grass.pygrass.vector.geometry import Line
+
+sys.path.insert(1, os.path.join(os.path.dirname(sys.path[0]), '', 'v.road'))
+import road_base as Base
+
+
+def write_objs(allrectas, radio):
+    """ Return
+    """
+    new2 = VectorTopo('bbbbb' + str(int(radio)))
+    # cols = [(u'cat',       'INTEGER PRIMARY KEY'),
+    #        (u'elev',      'INTEGER')]
+
+    new2.open('w')
+    for obj in allrectas:
+        new2.write(obj)
+    # new2.table.conn.commit()
+    new2.close()
+
+
+#########################################################
+
+def generate_ptsround(radio, radio2, azimut, center):
+    """ Return
+    """
+    x_o, y_o = center.split(',')
+    radio = float(radio)
+    radio2 = float(radio2)
+    azi = float(azimut)
+
+    x_1 = float(x_o) + radio2 * math.sin(azi)
+    y_1 = float(y_o) + radio2 * math.cos(azi)
+
+    x_2 = x_1+radio*math.sin(azi + math.pi/2)
+    y_2 = y_1+radio*math.cos(azi + math.pi/2)
+
+    x_3 = x_2 + 2 * radio2 * math.sin(azi + math.pi)
+    y_3 = y_2 + 2 * radio2 * math.cos(azi + math.pi)
+
+    x_4 = x_3 + 2 * radio * math.sin(azi+3*math.pi/2)
+    y_4 = y_3 + 2 * radio * math.cos(azi+3*math.pi/2)
+
+    x_5 = x_4 + 2 * radio2 * math.sin(azi)
+    y_5 = y_4 + 2 * radio2 * math.cos(azi)
+
+    x_6 = x_5 + (radio) * math.sin(azi+math.pi/2)
+    y_6 = y_5 + (radio) * math.cos(azi+math.pi/2)
+
+    return [[x_1, y_1, 0], [x_2, y_2, 0], [x_3, y_3, 0], [x_4, y_4, 0],
+            [x_5, y_5, 0], [x_6, y_6, 0]]
+
+
+class InterAlign(object):
+    """ Return
+    """
+    def __init__(self, name_map, cat):
+        """ Return
+        """
+        self.cat = cat
+        self.name = name_map
+        self.izq = ''
+
+        topo = VectorTopo(name_map)
+        topo.open('r', layer=1)
+        line1 = topo.read(cat)
+
+        self.type = line1.attrs['type']
+        self.pk_ini = float(''.join(line1.attrs['pk'].split('+')))
+        self.pto_ini = Base.RoadPoint(line1[0])
+        self.pto_fin = line1[-1]
+        self.param = float(line1.attrs['param'].split('=')[1])
+        self.center = None
+        self.recta = None
+
+        self.out = {'pks_in': [], 'pks_out': [], 'radios': [], 'dif': []}
+
+        topo.close()
+
+        topo.open('r', layer=2)
+        self.azimut_ini = topo.read(cat).attrs['azimut']
+        topo.close()
+
+        if self.type == 'Curve':
+            self.init_curve(topo)
+
+        elif self.type == 'Straight':
+            self.init_straight()
+        else:
+            grass.message(' not yet implemented')
+
+    def init_curve(self, topo):
+        """ Return
+        """
+        topo.open('r', layer=3)
+        for center in range(1, topo.number_of("points") + 1):
+            if isinstance(topo.read(center), Point):
+                cat_curve = topo.read(center).attrs['param'][1:]
+                if self.cat == int(cat_curve):
+                    self.center = Base.RoadPoint(topo.read(center))
+                    self.azimut_ini = self.center.azimuth(self.pto_ini)
+
+        topo.close()
+
+    def init_straight(self):
+        """ Return
+        """
+        self.azimut_ini = self.pto_ini.azimuth(self.pto_fin)
+        self.recta = Base.Straight(self.pto_ini, None, self.azimut_ini, 10)
+
+
+class Intersections(object):
+    """ Return
+    """
+    def __init__(self, name_map1, cat1, izq1, name_map2, cat2, izq2,
+                 inout=None, rounda=None):
+        """ Return
+        """
+        self.plant1 = InterAlign(name_map1, cat1)
+        self.plant2 = InterAlign(name_map2, cat2)
+
+        self.set_izq1(izq1)
+        self.set_izq2(izq2)
+
+        self.dist1 = []
+        self.dist2 = []
+        self.radios = []
+
+        self.rounda = rounda
+
+        if inout == 'In':  # options 'In' or 'Out'
+            self.inout = -1
+        else:
+            self.inout = 1
+
+    def _get_dif(self, d_1, d_2, radio):
+        """ Return
+        """
+        if d_1 > d_2:
+            dtmp = d_1
+            d_1 = d_2
+            d_2 = dtmp
+            dif = round(d_2 - d_1, 6)
+        else:
+            dif = 0
+        return [round(d_1, 6), round(d_2, 6), radio, dif]
+
+    def _get_radio_leng(self, plant, radio, dist):
+        """ Return
+        """
+        if plant.param < 0:
+            if plant.izq == 'Izq':
+                r_b = abs(plant.param) - radio - dist
+            else:
+                r_b = abs(plant.param) + radio + dist
+        else:
+            if plant.izq == 'Izq':
+                r_b = abs(plant.param) + radio + dist
+            else:
+                r_b = abs(plant.param) - radio - dist
+        return r_b
+
+    def _get_azi_inout(self, plant, azi_c1c2, ang_a):
+        """ Return
+        """
+        if plant.param < 0:
+            azi = azi_c1c2 - ang_a * self.inout
+        else:
+            azi = azi_c1c2 + ang_a * self.inout
+        return azi
+
+    def _get_alpha(self, azi_1, azi_2):
+        """ Return
+        """
+        if azi_1 < 0:
+            azi_1 = self._azi_neg(abs(azi_1))
+        if azi_2 < 0:
+            azi_2 = self._azi_neg(abs(azi_2))
+        alpha = abs(azi_1 - azi_2)
+        if alpha > math.pi:
+            alpha = 2 * math.pi - alpha
+        return alpha
+
+    def _check_azimuth(self, azi):
+        """ Return
+        """
+        if azi > math.pi:
+            return azi - 2 * math.pi
+        elif azi < 0:
+            return azi + 2 * math.pi
+        return azi
+
+    def _azi_neg(self, azi):
+        """ Return
+        """
+        if azi <= math.pi:
+            return azi + math.pi
+        else:
+            return azi - math.pi
+
+    def _get_azi_inout2(self, azi):
+        """ Return
+        """
+        if self.inout == -1:
+            return self._azi_neg(azi)
+        else:
+            return azi
+
+    def set_izq1(self, izq):
+        """ Return
+        """
+        if izq == "Izq":
+            self.izq1 = -1
+        else:
+            self.izq1 = 1
+        self.plant1.izq = izq
+
+    def set_izq2(self, izq):
+        """ Return
+        """
+        if izq == "Izq":
+            self.izq2 = -1
+        else:
+            self.izq2 = 1
+        self.plant2.izq = izq
+
+    def get_intersect(self, ind):
+        """ Return
+        """
+        dist1 = [p for p in self.dist1 if p != -1]
+        dist2 = [p for p in self.dist2 if p != -1]
+        if self.plant1.type == 'Straight' and self.plant2.type == 'Curve':
+
+            grass.message('straight_curve')
+            return self.straight_curve(self.radios[ind], dist1[ind],
+                                       dist2[ind])
+
+        elif self.plant1.type == 'Straight' and self.plant2.type == 'Straight':
+
+            grass.message('straight_straight')
+            return self.straight_straight(self.radios[ind], dist1[ind],
+                                          dist2[ind])
+
+        elif self.plant1.type == 'Curve' and self.plant2.type == 'Curve':
+
+            grass.message('curve_curve')
+            return self.curve_curve(self.radios[ind], dist1[ind],
+                                    dist2[ind])
+
+    def straight_straight(self, radio, dist1, dist2):
+        """ Return
+        """
+        # Buscamos el centro del circulo
+        recta11 = self.plant1.recta.parallel(dist1 + radio, self.izq1)
+        recta22 = self.plant2.recta.parallel(dist2 + radio, self.izq2)
+        pto_c = recta11.cutoff(recta22)
+
+        recta_r1 = self.plant1.recta.parallel(dist1, self.izq1)
+        recta_r2 = self.plant2.recta.parallel(dist2, self.izq2)
+        pto_v = recta_r1.cutoff(recta_r2)
+
+        # Punto de corte de la recta centro-vertice con el circulo
+        pto_p = pto_c.project(radio, pto_c.azimuth(pto_v))
+
+        # Rectas perpendiculares de xc,yc y xp,yp al eje 1
+        azi_1 = recta11.azimuth() - self.izq1 * math.pi / 2
+        pto_t1 = pto_c.project(dist1 + radio, azi_1)
+        recta_p1 = Base.Straight(pto_p, None, azi_1, 10)
+        pto_p1 = self.plant1.recta.cutoff(recta_p1)
+
+        # Rectas perpendiculares de xc,yc y xp,yp al eje 2
+        azi_2 = recta22.azimuth() - self.izq2 * math.pi / 2
+        pto_t2 = pto_c.project(dist2 + radio, azi_2)
+        recta_p2 = Base.Straight(pto_p, None, azi_2, 10)
+        pto_p2 = self.plant2.recta.cutoff(recta_p2)
+
+        d_1 = self.plant1.pto_ini.distance(pto_t1) + self.plant1.pk_ini
+        d_2 = self.plant1.pto_ini.distance(pto_p1) + self.plant1.pk_ini
+        d_3 = self.plant2.pto_ini.distance(pto_t2) + self.plant2.pk_ini
+        d_4 = self.plant2.pto_ini.distance(pto_p2) + self.plant2.pk_ini
+
+        return [self._get_dif(d_1, d_2, radio), self._get_dif(d_3, d_4, radio)]
+
+    def curve_curve(self, radio, dist1, dist2):
+        """ Return
+        """
+        azi_c1c2 = self.plant1.center.azimuth(self.plant2.center)
+
+        r_b = self._get_radio_leng(self.plant1, radio, dist1)
+        r_a = self._get_radio_leng(self.plant2, radio, dist2)
+        r_c = self.plant1.center.distance(self.plant2.center)
+
+        ang_a = math.acos((r_b ** 2 + r_c ** 2 - r_a ** 2) / (2 * r_b * r_c))
+        # ang_b = math.acos((r_a ** 2 + r_c ** 2 - r_b ** 2) / (2 * r_a * r_c))
+        # ang_c = math.pi - ang_a - ang_b
+
+        azi_c1c = self._get_azi_inout(self.plant1, azi_c1c2, ang_a)
+
+        pto_c = self.plant1.center.project(r_b, azi_c1c)
+
+        alpha = self._get_alpha(azi_c1c, self.plant1.azimut_ini)
+        pk_1 = self.plant1.pk_ini + alpha * abs(self.plant1.param)
+
+        azi_c2c = self.plant2.center.azimuth(pto_c)
+        alpha = self._get_alpha(azi_c2c, self.plant2.azimut_ini)
+        pk_2 = self.plant2.pk_ini + alpha * abs(self.plant2.param)
+
+        # roundabout
+        if self.rounda:
+            pto_p = pto_c.project(radio, azi_c2c, self.izq2)
+        else:
+            if self.plant1.param * self.plant2.param > 0:
+                beta = self._get_alpha(-self.izq1 * azi_c1c,
+                                       -self.izq2 * azi_c2c) / 2
+            else:
+                beta = -self._get_alpha(-self.izq1 * azi_c1c,
+                                        self.izq2 * azi_c2c) / 2
+            if self.plant1.izq == 'Izq':
+                pto_p = pto_c.project(radio, azi_c1c -
+                                      self.izq2 * self.izq1 * self.inout *
+                                      beta)
+            else:
+                pto_p = pto_c.project(radio, self._azi_neg(azi_c1c) -
+                                      self.izq2 * self.izq1 * self.inout *
+                                      beta)
+
+        azi_c1p = self.plant1.center.azimuth(pto_p)
+        azi_c2p = self.plant2.center.azimuth(pto_p)
+
+        alpha = self._get_alpha(azi_c1p, self.plant1.azimut_ini)
+        pk_11 = self.plant1.pk_ini + alpha * abs(self.plant1.param)
+
+        alpha = self._get_alpha(azi_c2p, self.plant2.azimut_ini)
+        pk_22 = self.plant2.pk_ini + alpha * abs(self.plant2.param)
+
+        #
+        recta_c2c = Base.Straight(self.plant2.center, pto_c)
+        recta_c1c = Base.Straight(self.plant1.center, pto_c)
+
+        write_objs([pto_c, pto_p, recta_c1c.get_line(), recta_c2c.get_line()],
+                   radio)
+
+        return [self._get_dif(pk_1, pk_11, radio),
+                self._get_dif(pk_2, pk_22, radio)]
+
+    def straight_curve(self, radio, dist1, dist2):
+        """ Return
+        """
+        azi_ini = self._get_azi_inout2(self.plant1.azimut_ini)
+        # Giro a la der
+        azi_1 = self._check_azimuth(self.plant1.azimut_ini + math.pi / 2)
+
+        recta1 = Base.Straight(self.plant2.center, None, azi_1, 10)
+        pto_c2 = self.plant1.recta.cutoff(recta1)
+        d_2 = self.plant2.center.distance(pto_c2)
+        azi_center = pto_c2.azimuth(self.plant2.center)
+
+        if azi_1 == azi_center:
+            l_s = abs(radio + dist1 + d_2 * self.izq1)
+        else:
+            l_s = abs(radio + dist1 - d_2 * self.izq1)
+
+        hip = self._get_radio_leng(self.plant2, radio, dist2)
+        alpha = math.asin(l_s / hip)
+
+        l_t1 = hip * math.cos(alpha)
+        pto_t1 = pto_c2.project(l_t1, azi_ini)
+
+        pto_c = self.plant2.center.project(hip, azi_ini - self.inout * alpha)
+        azi_c1c = self.plant2.center.azimuth(pto_c)
+
+        if self.rounda:
+            pto_p = pto_c.project(radio, azi_c1c, -self.izq2)
+        else:
+            if self.plant2.param < 0:
+                beta = -1 * self.izq1 * self.izq2 * \
+                       self._get_alpha(azi_c1c, pto_t1.azimuth(pto_c))
+            else:
+                beta = self.izq1 * self.izq2 * \
+                       self._get_alpha(azi_c1c, pto_c.azimuth(pto_t1))
+
+            pto_p = pto_c.project(radio, pto_c.azimuth(pto_t1) + beta / 2)
+
+        recta_p = Base.Straight(pto_p, None, azi_ini - self.inout *
+                                self.izq1 * math.pi / 2, 10)
+        pto_t2 = self.plant1.recta.cutoff(recta_p)
+
+        d_1 = self.plant1.pto_ini.distance(pto_t1) + self.plant1.pk_ini
+        d_2 = self.plant1.pto_ini.distance(pto_t2) + self.plant1.pk_ini
+
+        azi_c1p = self.plant2.center.azimuth(pto_p)
+
+        alpha = self._get_alpha(azi_c1c, self.plant2.azimut_ini)
+        pk1 = self.plant2.pk_ini + alpha * abs(self.plant2.param)
+
+        alpha = self._get_alpha(azi_c1p, self.plant2.azimut_ini)
+        pk2 = self.plant2.pk_ini + alpha * abs(self.plant2.param)
+
+        write_objs([pto_c2, self.plant2.center, pto_c, pto_t1, pto_p, pto_t2],
+                   radio)
+
+        return [self._get_dif(d_1, d_2, radio), self._get_dif(pk1, pk2, radio)]
+
+    def get_pklist(self):
+        """ Return
+        """
+        dist1 = [p for p in self.dist1 if p != -1]
+        dist2 = [p for p in self.dist2 if p != -1]
+
+        if len(dist1) <= len(dist2):
+            side = len(dist1)
+        else:
+            side = len(dist2)
+
+        pklist = [[], []]
+        pklist2 = [[], []]
+        pklist_ini = [[], []]
+        pklist_ini2 = [[], []]
+        for i in range(side):
+
+            intersec = self.get_intersect(i)
+
+            for j, inter in enumerate(intersec):
+                dista = dist1[i]
+                if j == 1:
+                    dista = dist2[i]
+                if inter[0] not in pklist:
+                    pklist[j].append(inter[0])
+                    pklist_ini[j].append([inter[0], [inter[2]], [inter[3]],
+                                          [dista], i])
+                else:
+                    ind = pklist[j].index(inter[0])
+                    pklist_ini[j][ind][1].append(inter[2])
+                    pklist_ini[j][ind][2].append(inter[3])
+                    pklist_ini[j][ind][3].append(dista)
+
+                if inter[1] not in pklist2:
+                    pklist2[j].append(inter[1])
+                    pklist_ini2[j].append([inter[1], [dista], i])
+                else:
+                    ind = pklist2[j].index(inter[1])
+                    pklist_ini2[j][ind][1].append(dista)
+
+        return [pklist, pklist2, pklist_ini, pklist_ini2]
+
+    def make_intersect(self, write=False):
+        """ Return
+        """
+        pklist, pklist2, pklist_ini, pklist_ini2 = self.get_pklist()
+
+        sal1 = self.get_tablesql_in(pklist_ini[0], self.plant1, self.dist1)
+        sal2 = self.get_tablesql_out(pklist_ini2[0], self.plant1, self.dist1)
+
+        all_pklist1 = pklist[0] + pklist2[0]
+        all_sal0 = sal1 + sal2
+
+        sal0 = 'v.road add=row name=' + self.plant1.name.split('__')[0] + \
+               ' tab_type=Displ pklist="' + \
+               ','.join([str(p) for p in all_pklist1]) + '"'
+
+        grass.message(sal0)
+        grass.message(all_sal0)
+        if write:
+            os.system(sal0)
+            os.system(all_sal0)
+
+        if self.plant1.izq != self.plant2.izq:
+            sal1 = self.get_tablesql_in(pklist_ini[1], self.plant2,
+                                        self.dist2[::-1])
+            sal2 = self.get_tablesql_out(pklist_ini2[1], self.plant2,
+                                         self.dist2[::-1])
+        else:
+            sal1 = self.get_tablesql_in(pklist_ini[1], self.plant2,
+                                        self.dist2)
+            sal2 = self.get_tablesql_out(pklist_ini2[1], self.plant2,
+                                         self.dist2)
+
+        all_pklist2 = pklist[1] + pklist2[1]
+        all_sal0 = sal1 + sal2
+
+        sal0 = 'v.road add=row name=' + self.plant2.name.split('__')[0] + \
+               ' tab_type=Displ pklist="' + \
+               ','.join([str(p) for p in all_pklist2]) + '"'
+
+        grass.message(sal0)
+        grass.message(all_sal0)
+        if write:
+            os.system(sal0)
+            os.system(all_sal0)
+
+    def get_tablesql_in(self, pklist_ini, plant, distances):
+        """ Return
+        """
+        name = plant.name.split('__')[0]
+
+        sal = 'echo " \n'
+        for i, npk in enumerate([p[0] for p in pklist_ini]):
+
+            sal += 'UPDATE ' + name + '_Displ SET '
+            if plant.izq == 'Izq':
+                sal += 'sec_left=\''
+            else:
+                sal += 'sec_right=\''
+
+            for dist in distances:
+
+                for len_d in pklist_ini[i][3]:
+                    if dist == len_d:
+                        sal += str(len_d) + ' 0;'
+                    else:
+                        sal += '-1 0;'
+            sal = sal[:-1] + '\''
+
+            if plant.izq == 'Izq':
+                sal += ', type_left=\''
+            else:
+                sal += ', type_right=\''
+
+            for dist in distances:
+
+                for j, len_d in enumerate(pklist_ini[i][3]):
+                    if dist == len_d:
+                        sal += 'r' + str(pklist_ini[i][1][j]) + ',' + \
+                               str(pklist_ini[i][2][j]) + ';'
+                    else:
+                        sal += 'l;'
+            sal = sal[:-1] + '\''
+
+            sal += ' WHERE pk=' + str(npk) + ';\n'
+        sal += '" | db.execute input=- \n'
+        return sal
+
+    def get_tablesql_out(self, pklist_ini2, plant, distances):
+        """ Return
+        """
+        name = plant.name.split('__')[0]
+        sal = 'echo " \n'
+        for i, npk in enumerate([p[0] for p in pklist_ini2]):
+
+            sal += 'UPDATE ' + name + '_Displ SET '
+            if plant.izq == 'Izq':
+                sal += 'sec_left=\''
+            else:
+                sal += 'sec_right=\''
+
+            for dist in distances:
+
+                for len_d in pklist_ini2[i][1]:
+                    if dist == len_d:
+                        sal += str(len_d) + ' 0;'
+                    else:
+                        sal += '-1 0;'
+            sal = sal[:-1] + '\''
+
+            if plant.izq == 'Izq':
+                sal += ', type_left=\''
+            else:
+                sal += ', type_right=\''
+
+            for dist in distances:
+                sal += 'l;'
+            sal = sal[:-1] + '\''
+
+            sal += ' WHERE pk=' + str(npk) + ';\n'
+        sal += '" | db.execute input=- \n'
+        return sal
+
+
+# =============================================
+# Main
+# =============================================
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()
+#

Added: grass-addons/grass7/vector/v.civil/road_displ.py
===================================================================
--- grass-addons/grass7/vector/v.civil/road_displ.py	                        (rev 0)
+++ grass-addons/grass7/vector/v.civil/road_displ.py	2016-07-01 22:30:22 UTC (rev 68831)
@@ -0,0 +1,720 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Sat Aug  2 16:52:30 2014
+
+ at author: meskal
+"""
+
+#
+# import pygrass modules
+#
+import math
+# import grass.script as grass
+import re
+from grass.pygrass.vector import VectorTopo
+import road_base as Base
+from road_plant import Aligns
+# from grass.pygrass.vector.geometry import Point
+from grass.pygrass.vector.geometry import Line
+# from grass.pygrass.vector.geometry import Boundary
+# from grass.pygrass.vector.geometry import Area
+import road_plant as Plant
+
+
+def write_objs(allrectas, radio):
+    """
+    """
+    new2 = VectorTopo('AACC__' + str(int(radio)))
+    # cols = [(u'cat',       'INTEGER PRIMARY KEY'),
+    #        (u'elev',      'INTEGER')]
+
+    new2.open('w')
+    for obj in allrectas:
+        new2.write(obj)
+    # new2.table.conn.commit()
+    new2.close()
+
+
+# =============================================
+# Parallel
+# =============================================
+
+class Parallel(Base.RoadObj, object):
+    """ Return
+    """
+    def __init__(self, pk1, pk2, dist1, dist2, g90, plant=None):
+        """ Return
+        """
+        self.pk1 = pk1
+        self.dist1 = dist1
+        self.pk2 = pk2
+        self.dist2 = dist2
+        self.plant = plant
+
+        self.g90 = g90
+
+        self.line = None
+
+        super(Parallel, self).__init__(self.length())
+
+    def __str__(self):
+        return ("PARALLEL(" + str(self.pk1) + ", " + str(self.pk2) +
+                ", " + str(self.dist1) + ", " + str(self.dist2) + ", " +
+                str(self.g90) + ")")
+
+    def __repr__(self):
+
+        return ("Parallel(" + str(self.pk1) + ", " + str(self.pk2) +
+                ", " + str(self.dist1) + ", " + str(self.dist2) + ", " +
+                str(self.g90) + ")")
+
+    def length(self):
+        """ Return
+        """
+        if self.line:
+            return self.line.length()
+        else:
+            return -1
+
+    def param(self):
+        """ Return
+        """
+        return 'L=' + str(round(self.length(), 3))
+
+    def get_roadpoint(self, start, r_pnt=None):
+        """ Return
+        """
+        distx = self.dist1 + ((start - self.pk1) *
+                              (self.dist2 - self.dist1)) / (self.pk2 -
+                                                            self.pk1)
+        if not r_pnt:
+            r_pnt = self.plant.get_roadpoint(start)
+        if r_pnt.azi == 0:
+            r_pnt.azi = math.pi/2
+        r_pnt_d = r_pnt.parallel(distx, self.g90)
+
+        r_pnt_d.dist_displ = distx
+        return [r_pnt_d]
+
+    def get_roadpnts(self, start, end, interv):
+        """ Return
+        """
+        if start == 0:
+            start = int(self.pk1)
+        if end == -1:
+            end = int(self.pk2)
+        list_pts = []
+        for pki in range(start, end, interv):
+            list_pts.append(self.get_roadpoint(pki)[0])
+        self.line = Line(list_pts)
+        return list_pts
+
+    def find_cutoff(self, r_pnt):
+        """ Return
+        """
+        return self.get_roadpoint(r_pnt.npk, r_pnt)[0]
+
+
+# =============================================
+# Parallel
+# =============================================
+
+class DisplLine(Aligns, object):
+    """ Return
+    """
+    contador = 0
+    contador_left = 0
+    contador_right = 0
+
+    def __init__(self, lists, left=True, polygon=None, plant=None):
+        """ Return
+        """
+        DisplLine.contador += 1
+        if left:
+            DisplLine.contador_left += 1
+        else:
+            DisplLine.contador_right += 1
+
+        self.pks = lists[0]
+        self.dist = lists[1]
+        self.elev = lists[2]
+        self.typeline = lists[3]
+
+        self.left = left
+        self.polygon = polygon
+        self.plant = plant
+
+        self.list_lim = []
+        self.elev_lim = []
+
+        self.g90 = -math.pi / 2
+        self.num = DisplLine.contador_left
+        if not left:
+            self.g90 = math.pi / 2
+            self.num = DisplLine.contador_right
+
+        self._fix_line()
+        d_alings = self._init_aligns()
+
+        super(DisplLine, self).__init__(d_alings)
+
+    def __str__(self):
+        """ Return
+        """
+        return str(self.dist)
+
+#    @staticmethod
+#    def total():
+#        """ Return
+#        """
+#        return DisplLine.contador
+
+    def _intbool(self):
+        """Return
+        """
+        if self.left is True:
+            return -1
+        else:
+            return 1
+
+    def _fix_line(self):
+        """ Return
+        """
+        dist = []
+        pks = []
+        elev = []
+        typeline = []
+        for j in range(len(self.dist)):
+            if self.dist[j] == -1:
+                continue
+            if j != len(self.dist) - 1:
+                if self.dist[j] == 0 and self.dist[j + 1] == 0:
+                    continue
+            dist.append(self.dist[j])
+            pks.append(self.pks[j])
+            elev.append(self.elev[j])
+            typeline.append(self.typeline[j])
+        self.dist = dist
+        self.pks = pks
+        self.elev = elev
+        self.typeline = typeline
+
+    def _polyg_parall(self, dist):
+        """ Return
+        """
+#        line = self.polygon.read(1)
+        self.polygon.open('r')
+        line = self.polygon.cat(1, 'lines', 1)[0]
+        self.polygon.close()
+
+        pnts = []
+        for i in range(len(line) - 1):
+
+            straight = Base.Straight(line[i], line[i + 1])
+            pnts.append(straight.parallel(dist, self._intbool()))
+
+        parallel = Line([pnts[0].pstart])
+        for i in range(len(pnts) - 1):
+            parallel.append(pnts[i].cutoff(pnts[i + 1]))
+        parallel.append(pnts[-1].pend)
+        return parallel
+
+    def _table_parall(self, dist):
+        """ Return
+        """
+        layer = 2
+        self.polygon.open('r')
+        tabla_plant = self.polygon.dblinks.by_layer(layer).table()
+        tabla_plant_sql = "SELECT * FROM {name};".format(name=tabla_plant.name)
+        tabla_plant_iter = tabla_plant.execute(tabla_plant_sql)
+        self.polygon.close()
+        if self.left:
+            contador = DisplLine.contador_left
+        else:
+            contador = DisplLine.contador_right
+
+        tabla = []
+        for dat in tabla_plant_iter:
+
+            cat, pk, radio, ain, aout, sobre, superelev, dc, lr = dat
+
+            if radio == 0:
+                tabla.append({'a_out': 0, 'dc_': 0, 'cat2': cat,
+                              'radio': 0, 'pk_eje': 0,
+                              'superelev': superelev, 'a_in': 0,
+                              'lr_': 0, 'widening': sobre})
+                continue
+
+            local_in = Base.cloth_local(abs(radio), ain)
+            local_out = Base.cloth_local(abs(radio), aout)
+
+            if self.left and radio < 0:
+                radio = radio + dist - (contador * sobre)
+            elif self.left and radio > 0:
+                radio = radio + dist + (contador * sobre)
+            elif not self.left and radio > 0:
+                radio = radio - dist - (contador * sobre)
+            elif not self.left and radio < 0:
+                radio = radio - dist + (contador * sobre)
+
+            if ain != 0:
+                ain = Base.clotoide_get_a(radio, local_in['y_o'],
+                                          contador * sobre, self.left)
+            if aout != 0:
+                aout = Base.clotoide_get_a(radio, local_out['y_o'],
+                                           contador * sobre, self.left)
+
+#            tabla.append((0, 0, radio, ain, aout, sobre, ''))
+            tabla.append({'a_out': aout, 'dc_': 0, 'cat2': cat,
+                          'radio': radio, 'pk_eje': 0,
+                          'superelev': superelev, 'a_in': ain,
+                          'lr_': 0, 'widening': sobre})
+        return tabla
+
+    def _get_limits_plant(self, plant_d):
+        """ Return
+        """
+        list_pnts = []
+        pnts_charc = plant_d.get_charact()
+
+        for i, pnt in enumerate(pnts_charc[:-1]):
+            pnt2 = self.plant.list_aligns[i].find_cutoff(pnt)
+            if pnt2:
+                pnt2.npk += self.plant.leng_accum[i]
+
+            if not pnt2:
+                pnt2 = self.plant.list_aligns[i + 1].find_cutoff(pnt)
+                if pnt2:
+                    pnt2.npk += self.plant.leng_accum[i + 1]
+
+            if not pnt2:
+                pnt2 = self.plant.list_aligns[i - 1].find_cutoff(pnt)
+                if pnt2:
+                    pnt2.npk += self.plant.leng_accum[i - 1]
+            list_pnts.append(pnt2)
+        pnt2 = self.plant.list_aligns[-1].get_roadpoint(-1)[0]
+        pnt2.npk = self.plant.leng_accum[-1]
+        list_pnts.append(pnt2)
+
+        return list_pnts
+
+    def _mode_exact(self, index):
+        """ Return
+        """
+        polyg = self._polyg_parall(self.dist[index])
+        table = self._table_parall(self.dist[index])
+
+        plantalignd = Plant.Plant(polyg, table)
+        d_alings = []
+        pnts_limits = self._get_limits_plant(plantalignd)
+
+        for j, r_pnt in enumerate(pnts_limits):
+            if self.pks[index] <= r_pnt.npk <= self.pks[index + 1]:
+                self.list_lim.append(r_pnt.npk)
+                self.elev_lim.append(self.elev[index])
+                d_alings.append(plantalignd[j])
+
+        return d_alings
+
+    def _distx(self, rad, pc_d, pstart):
+        """ Return
+        """
+        recta_pnt = pstart.normal(math.pi / 2)
+        recta_c = Base.Straight(pc_d, None, pstart.azi, 10)
+        pto_corte = recta_pnt.cutoff(recta_c)
+        distxx = pc_d.distance(pto_corte)
+        seno = math.sqrt(rad ** 2 - distxx ** 2)
+        distx = pstart.distance(pto_corte) - seno
+        return distx
+
+    def _mode_curve(self, index):
+        """ Return
+        """
+        rad, center = self.typeline[index].split(",")
+
+        rad = float(rad[1:])
+        center = float(center)
+
+        pcenter = self.plant.get_roadpoint(self.pks[index] + center)
+        pc_d = pcenter.parallel(self.dist[index] + rad, self.g90)
+
+        pstart = self.plant.get_roadpoint(self.pks[index])
+        distx = self._distx(rad, pc_d, pstart)
+
+        p1_d = pstart.parallel(distx, self.g90)
+
+        pend = self.plant.get_roadpoint(self.pks[index + 1])
+
+        distx = self._distx(rad, pc_d, pend)
+        p2_d = pend.parallel(distx, self.g90)
+
+        az1 = pc_d.azimuth(p1_d)
+        az2 = pc_d.azimuth(p2_d)
+
+        alpha = abs(az2 - az1)
+        if alpha > math.pi:
+            alpha = 2 * math.pi - alpha
+
+        curve = Base.Curve(self._intbool() * rad, alpha, az1, pc_d)
+
+        return curve
+
+    def _init_aligns(self):
+        """ Return
+        """
+        d_alings = []
+        for i in range(len(self.dist) - 1):
+
+            if self.dist[i] == 0 or self.dist[i + 1] == 0:
+                self.list_lim.append(self.pks[i])
+                self.elev_lim.append(self.elev[i])
+                d_alings.append(None)
+                continue
+
+            if self.typeline[i] == 'e':
+                self.list_lim.append(self.pks[i])
+                self.elev_lim.append(self.elev[i])
+                d_alings.extend(self._mode_exact(i))
+
+            elif self.typeline[i] == 'l':
+                self.list_lim.append(self.pks[i])
+                self.elev_lim.append(self.elev[i])
+
+                paral = Parallel(self.pks[i], self.pks[i + 1], self.dist[i],
+                                 self.dist[i + 1], self.g90, self.plant)
+                d_alings.append(paral)
+
+            elif self.typeline[i] == 's':
+                raise ValueError('s')
+#                pstart = plant.get_roadpoint(self.pks[i])
+#                p1_x = pstart.x + self.dist[i]*math.sin(pstart.azi+self.g90)
+#                p1_y = pstart.y + self.dist[i]*math.cos(pstart.azi+self.g90)
+#
+#                pend = plant.get_roadpoint(self.pks[i+1])
+#                p2_x = pend.x + self.dist[i]*math.sin(pend.azi+self.g90)
+#                p2_y = pend.y + self.dist[i]*math.cos(pend.azi+self.g90)
+#
+#                recta = Base.Straight(Point(p1_x, p1_y), Point(p2_x, p2_y))
+
+            elif re.search(r'^r', self.typeline[i]):
+                self.list_lim.append(self.pks[i])
+                self.elev_lim.append(self.elev[i])
+                d_alings.append(self._mode_curve(i))
+
+            else:
+                raise ValueError('Type not suported:' + self.typeline[i])
+
+        if self.pks[-1] not in self.list_lim:
+            self.list_lim.append(self.pks[-1])
+            self.elev_lim.append(self.elev[-1])
+
+        return d_alings
+
+    def get_left(self):
+        """ Return
+        """
+        if self.left:
+            return 'left'
+        else:
+            return 'right'
+
+    def _find_superelev(self, index, r_pnt, elev, dist_displ):
+        """Return
+        """
+        for line in self.plant.superelev_lim:
+
+            if line == []:
+                continue
+
+            dist1, dist2, bom1, peralte, bom2, radio = line
+            pks_1 = dist1 + dist2
+
+            if (pks_1[0] < r_pnt.npk < pks_1[-1]):
+                break
+
+#        pend_1 = [-bom1, 0, bom1, peralte, peralte, bom2, 0, -bom2]
+#        pend_2 = [-bom1, -bom1, -bom1, -peralte, -peralte, -bom2, -bom2, -bom2]
+
+#        elev2 = elev / dist_displ
+        bom1 = bom1 * dist_displ * 0.01
+        bom2 = bom2 * dist_displ * 0.01
+        peralte = peralte * dist_displ * 0.01
+        pend_11 = [elev, elev + bom1, elev + bom1 + bom1,
+                   elev + bom1 + peralte, elev + bom1 + peralte,
+                   elev + bom2 + bom2, elev + bom2, elev]
+        pend_22 = [elev, elev, elev, elev - peralte, elev - peralte,
+                   elev, elev, elev]
+
+        pkini, pkfin = 0, 1
+#        z_1 = - bombeo * dist_displ * 0.01
+#        z_2 = - bombeo * dist_displ * 0.01
+        z_1 = elev
+        z_2 = elev
+
+        if (self.left and radio > 0) or (not self.left and radio < 0):
+
+            for i in range(len(pks_1) - 1):
+
+                if pks_1[i] < r_pnt.npk < pks_1[i + 1]:
+                    pkini, pkfin = pks_1[i], pks_1[i + 1]
+                    z_1 = pend_11[i]
+                    z_2 = pend_11[i + 1]
+                    break
+
+        elif (not self.left and radio > 0) or (self.left and radio < 0):
+
+            for i in range(0, len(pks_1) - 1, 1):
+
+                if pks_1[i] < r_pnt.npk < pks_1[i + 1]:
+                    pkini, pkfin = pks_1[i], pks_1[i + 1]
+                    z_1 = pend_22[i]
+                    z_2 = pend_22[i + 1]
+                    break
+
+        z_x = z_1 + ((r_pnt.npk - pkini) * ((z_2 - z_1) / (pkfin - pkini)))
+
+        return z_x
+
+    def get_elev(self, index, r_pnt, dist_displ):
+        """ Return
+        """
+#        calzadas = 1
+#        if self.plant.bombeo:
+#            elev = self._find_superelev(index, r_pnt, self.plant.bombeo,
+#                                        dist_displ)
+#
+#        else:
+        elev = self.elev_lim[index] + ((r_pnt.npk - self.list_lim[index]) *
+                                       (self.elev_lim[index + 1] -
+                                       self.elev_lim[index])) / \
+                                      (self.list_lim[index + 1] -
+                                       self.list_lim[index])
+        if self.plant.bombeo:
+            elev = self._find_superelev(index, r_pnt, elev, dist_displ)
+
+        return elev
+
+    def find_cutoff(self, r_pnt):
+        """ Return
+        """
+
+        for i in range(len(self.list_lim) - 1):
+            if isinstance(self.list_aligns[i], Base.Curve):
+                cuv_lim = r_pnt.npk <= self.list_lim[i + 1]
+            else:
+                cuv_lim = r_pnt.npk < self.list_lim[i + 1]
+
+            if self.list_lim[i] <= r_pnt.npk and cuv_lim:
+
+                if self.list_aligns[i] is not None:
+                    r_pnt_d = self.list_aligns[i].find_cutoff(r_pnt)
+
+                    if r_pnt_d is not None:
+                        r_pnt_d.dist_displ = \
+                            round(r_pnt_d.distance2(r_pnt.point2d), 4)
+                        elev = self.get_elev(i, r_pnt, r_pnt_d.dist_displ)
+                        r_pnt_d.z = elev + r_pnt.z
+                        if r_pnt_d.dist_displ == 0:
+                            r_pnt_d.incli = 0
+                        else:
+                            r_pnt_d.incli = math.atan(elev/r_pnt_d.dist_displ)
+
+                        r_pnt_d.acum_pk = self.list_lim[i] + r_pnt_d.npk
+
+                    return r_pnt_d
+
+    def get_pnts_displ(self, list_r_pnts, line=False):
+        """ Return a displaced line of a given axis
+        """
+        list_pnts_d = []
+
+        for r_pnt in list_r_pnts:
+            list_pnts_d.append(self.find_cutoff(r_pnt))
+
+        if line:
+            return Line(list_pnts_d)
+        else:
+            return list_pnts_d
+
+    def set_roadline(self, roadline):
+        """ Return
+        """
+        puntos = self.get_pnts_displ(roadline, line=False)
+
+        # Name lenght type param rgb
+        attrs = ['Displ_' + str(self.num), self.length(), self.get_left(),
+                 self.num, '0:128:128']
+        self.roadline = Base.RoadLine(puntos, attrs, 'Displ_' + str(self.num))
+
+
+# =============================================
+# Parallel
+# =============================================
+
+class Displaced(object):
+    """ Return
+    """
+    def __init__(self, polygon, tabla_iter, plant):
+        """ Return
+        """
+        self.polygon = polygon
+        self.tabla_iter = tabla_iter
+        self.plant = plant
+
+        self.displines = []
+        self.displines_left = []
+        self.displines_right = []
+        self.pks = []
+
+        self._init_displ()
+
+    def __getitem__(self, index):
+        return self.displines[index]
+
+    def __setitem__(self, index, value):
+        self.displines[index] = value
+
+    def __delitem__(self, index):
+        del self.displines[index]
+
+    def __len__(self):
+        return len(self.displines)
+
+    def __str__(self):
+        """ Return
+        """
+        return "LINESTRING(%s)"
+
+    def _init_displ(self):
+        """ Return
+        """
+        d_left = []
+        type_left = []
+        d_right = []
+        type_right = []
+
+        for i, dat in enumerate(self.tabla_iter):
+
+            self.pks.append(dat['pk'])
+            if ';' in dat['sec_left']:
+                d_left.append(dat['sec_left'].split(';'))
+            else:
+                d_left.append(dat['sec_left'])
+
+            if ';' in dat['sec_right']:
+                d_right.append(dat['sec_right'].split(';'))
+            else:
+                d_right.append(dat['sec_right'])
+
+            if dat['type_left'] != '':
+                type_left.append(dat['type_left'].split(';'))
+            else:
+                type_left.append(['l'] * len(d_left[i]))
+
+            if dat['type_right'] != '':
+                type_right.append(dat['type_right'].split(';'))
+            else:
+                type_right.append(['l'] * len(d_right[i]))
+
+        self._generate(d_left, type_left, left=True)
+        self._generate(d_right, type_right, left=False)
+
+    def _generate(self, disp, types, left):
+        """ Return
+        """
+        rango1 = range(len(types[0]))
+
+        disp = [[[float(p) for p in row[i].split()] for row in disp]
+                for i in range(len(disp[0]))]
+        types = [[row[i] for row in types] for i in rango1]
+
+        if left:
+            disp = disp[::-1]
+            types = types[::-1]
+
+        for i, lin in enumerate(disp):
+            types2 = types[:]
+            lin2 = [[row[j] for row in lin] for j in range(len(lin[0]))]
+
+            displine = DisplLine([self.pks[:], lin2[0], lin2[1], types2[i][:]],
+                                 left, self.polygon, self.plant)
+
+            self.displines.append(displine)
+            if left:
+                self.displines_left.append(displine)
+            else:
+                self.displines_right.append(displine)
+
+    def find_cutoff(self, r_pnt):
+        """ Return all displaced points of a given axis point
+        """
+        list_pnts_d_left = []
+        list_pnts_d_right = []
+        for d_line in self.displines:
+            pnt = d_line.find_cutoff(r_pnt)
+            if d_line.left:
+#                if pnt is not None:
+                list_pnts_d_left.append(pnt)
+            else:
+#                if pnt is not None:
+                list_pnts_d_right.append(pnt)
+        return [list_pnts_d_left, list_pnts_d_right]
+
+    def get_pnts_trans(self, list_r_pnts):
+        """ Return
+        """
+        list_pnts_d = []
+        for r_pnt in list_r_pnts:
+            list_pnts_d.append(self.find_cutoff(r_pnt))
+        return list_pnts_d
+
+    def get_lines(self):
+        """ Return
+        """
+        list_attrs = []
+        list_lines = []
+        for i, displ in enumerate(self.displines):
+
+            objs, values = displ.roadline.get_line_attrs(1)
+            list_lines.extend(objs)
+            list_attrs.extend(values)
+        return list_lines, list_attrs
+
+    def get_charact(self):
+        """ Return
+        """
+        list_lines = []
+        list_attrs = []
+        for i, displ in enumerate(self.displines):
+            obj, attr = displ.get_charact_pnts()
+            list_lines.extend(obj)
+            for att in attr:
+                att.append('Displ=' + str(i + 1))
+            list_attrs.extend(attr)
+        return list_lines, list_attrs
+
+    def set_roadlines(self, roadline):
+        """ Return
+        """
+        for displ in self.displines:
+            displ.set_roadline(roadline)
+
+    def get_areas(self, opts):
+        """ Return
+        """
+        opts = [opt.split('-') for opt in opts.split(',') if ',' in opts]
+
+        list_lines = []
+        list_attrs = []
+        for j, opt in enumerate(opts):
+
+            lines = self[int(opt[0]) - 1].roadline.get_area(
+                self[int(opt[1]) - 1].roadline)
+            list_attrs.extend([str(j + 1) for _ in range(len(lines))])
+            list_lines.extend(lines)
+
+        return list_lines, list_attrs
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()


Property changes on: grass-addons/grass7/vector/v.civil/road_displ.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: grass-addons/grass7/vector/v.civil/road_marks.py
===================================================================
--- grass-addons/grass7/vector/v.civil/road_marks.py	                        (rev 0)
+++ grass-addons/grass7/vector/v.civil/road_marks.py	2016-07-01 22:30:22 UTC (rev 68831)
@@ -0,0 +1,85 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Thu Oct 23 01:06:18 2014
+
+ at author: meskal
+"""
+
+#
+# import pygrass modules
+#
+import math
+
+# from grass.pygrass.vector import VectorTopo
+# import road_base as Base
+
+# from grass.pygrass.vector.geometry import Point
+# from grass.pygrass.vector.geometry import Line
+
+
+class Marks(object):
+    """ Return
+    """
+    def __init__(self, polygon, tabla, plant, vert):
+        """ Return
+        """
+        self.polygon = polygon
+#        self.tabla_iter = tabla_iter
+        self.plant = plant
+        self.vert = vert
+
+        self.tabla = tabla
+#        self.init_marks()
+
+    def __str__(self):
+        """ Return
+        """
+        return "TransLine(" + str(self.tabla) + ")"
+
+#    def init_marks(self):
+#        """ Return
+#        """
+#        for dats in self.tabla_iter:
+#
+#            if dats[5] is not None:
+#                self.list_dats.append(dict(zip(['pk', 'dist', 'elev', 'azi',
+#                                                'name', 'cod'], dats[1:7])))
+
+    def num_marks(self):
+        """ Return
+        """
+
+    def get_pnts(self):
+        """ Return
+        """
+        list_pnts = []
+        list_attrs = []
+        for i, dats in enumerate(self.tabla):
+
+            r_pnt = self.plant.get_roadpoint(dats['pk'])
+
+            self.vert.set_elev(r_pnt)
+
+            if ',' in dats['dist']:
+                distances = dats['dist'].split(',')
+                elevations = dats['elev'].split(',')
+            else:
+                distances = dats['dist']
+                elevations = dats['elev']
+
+            if dats['azi'] != '':
+                azi = dats['azi'].split(',')
+            else:
+                azi = ['1'] * len(distances)
+
+            for i, dist in enumerate(distances):
+                m_pnt = r_pnt.parallel(float(dist), math.pi / 2)
+                m_pnt.z = r_pnt.z + float(elevations[i])
+                m_pnt.dist_displ = dist
+                if azi[i] == '-1':
+                    m_pnt.azi = m_pnt.azi + math.pi
+                list_pnts.append(m_pnt)
+                list_attrs.append([m_pnt.npk, round(90-m_pnt.azi * 180 / math.pi+360+90,
+                                                    4), dats['name'],
+                                   dats['cod'], m_pnt.dist_displ, m_pnt.z])
+        return list_pnts, list_attrs


Property changes on: grass-addons/grass7/vector/v.civil/road_marks.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: grass-addons/grass7/vector/v.civil/road_plant.py
===================================================================
--- grass-addons/grass7/vector/v.civil/road_plant.py	                        (rev 0)
+++ grass-addons/grass7/vector/v.civil/road_plant.py	2016-07-01 22:30:22 UTC (rev 68831)
@@ -0,0 +1,800 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Wed Jul 23 18:37:36 2014
+
+ at author: meskal
+"""
+
+import math
+import time
+import road_base as Base
+
+# import grass.script as grass
+# from grass.pygrass.vector.geometry import Point
+from grass.pygrass.vector.geometry import Line
+# from grass.pygrass.vector.geometry import Attrs
+
+
+def time_func(funcion_f):
+    """Return
+    """
+    def funcion_r(*arg):
+        """Return
+        """
+        t_1 = time.clock()
+        res = funcion_f(*arg)
+        t_2 = time.clock()
+        print('%s tarda %0.5f ms' % (funcion_f.__name__, (t_2 - t_1) * 1000.0))
+        return res
+    return funcion_r
+
+
+# =============================================
+# ALIGNS
+# =============================================
+
+class Aligns(object):
+    """ Return
+    """
+    def __init__(self, list_aligns=None):
+        """ Return
+        """
+        self.list_aligns = list_aligns
+
+        self.leng_accum = [0]
+
+        self.length_accums()
+
+        self.roadline = None
+
+    def __getitem__(self, index):
+        return self.list_aligns[index]
+
+    def __setitem__(self, index, value):
+        self.list_aligns[index] = value
+
+    def __delitem__(self, index):
+        del self.list_aligns[index]
+
+    def __len__(self):
+        return len(self.list_aligns)
+
+    def __str__(self):
+        return self.__repr__()
+
+    def __repr__(self):
+        string = "["
+
+        for i in self.list_aligns:
+            string += str(i) + '\n'
+
+        string += "]"
+        return string
+
+    def length_accums(self):
+        """ Return
+        """
+        lon = 0
+        for ali in self.list_aligns:
+            if ali is not None:
+                ali.leng_accum = lon
+                lon += ali.length()
+                self.leng_accum.append(lon)
+
+    def length(self):
+        """ Return
+        """
+        return self.leng_accum[-1]
+
+    def get_roadpoint(self, npk):
+        """ Return
+        """
+        if npk == -1:
+            npk = self.length()
+        for i in range(len(self.leng_accum) - 1):
+
+            if self.leng_accum[i] <= npk <= self.leng_accum[i + 1]:
+
+                pnt = self.list_aligns[i].get_roadpoint(npk -
+                                                        self.leng_accum[i])[0]
+                pnt.npk = npk
+
+                pnt.align = self.list_aligns[i].__class__.__name__ + '_' + \
+                    str(i + 1)
+                return pnt
+
+#    def get_line(self, list_r_pnts):
+#        """ Return
+#        """
+#        return Line([r_pnt for r_pnt in list_r_pnts
+#                     if r_pnt is not None])
+
+    def get_roadpnts(self, start, end, interv, interv_c=None):
+        """ Return
+        """
+        if not interv_c:
+            interv_c = interv
+
+        if end == -1:
+            end = self.length()
+        resto = interv
+        accum = start
+        list_pts = []
+        ini = 0
+        fin = len(self.leng_accum)
+        for i in range(len(self.leng_accum) - 1):
+            if self.leng_accum[i] <= start <= self.leng_accum[i + 1]:
+                ini = i
+            if self.leng_accum[i] <= end <= self.leng_accum[i + 1]:
+                fin = i + 1
+
+        rang_int = range(0, int(self.leng_accum[-1]), int(interv))
+        rang_int_c = range(0, int(self.leng_accum[-1]), int(interv_c))
+
+        # int_ant = interv
+        rango_ant = []
+        for i in range(ini, fin):
+
+            rango = []
+            if isinstance(self.list_aligns[i], Base.Straight):
+                inter = interv
+                for j in range(len(rang_int) - 1):
+                    if self.leng_accum[i] <= rang_int[j] <= self.leng_accum[i + 1]:
+                        rango.append(rang_int[j])
+            else:
+                inter = interv_c
+                for j in range(len(rang_int_c) - 1):
+                    if self.leng_accum[i] <= rang_int_c[j] <= self.leng_accum[i + 1]:
+                        rango.append(rang_int_c[j])
+
+            if inter > self.list_aligns[i].length() + resto:
+                resto = resto + self.list_aligns[i].length()
+                continue
+
+            if rango == []:
+                rango = [rango_ant[-1] + inter]
+            accum = rango[0]
+            start2 = rango[0] - self.leng_accum[i]
+
+            if i == ini:
+                start2 = start - self.leng_accum[i]
+
+            end2 = -1
+            if i == fin:
+                end2 = end - self.leng_accum[i]
+
+            self.list_aligns[i].pts_accum = accum
+
+            pnts = self.list_aligns[i].get_roadpnts(start2, end2, inter)
+            for pnt in pnts:
+                pnt.align = self.list_aligns[i].__class__.__name__ + '_' + \
+                    str(i + 1)
+            list_pts.extend(pnts)
+
+            resto = self.list_aligns[i].pts_rest
+            accum = self.list_aligns[i].pts_accum
+            # int_ant = inter
+            rango_ant = rango
+
+        r_pnt = self.list_aligns[-1].get_roadpoint(-1)[0]
+        r_pnt.align = self.list_aligns[-1].__class__.__name__ + '_' + \
+            str(len(self.list_aligns))
+        if list_pts[-1].npk != r_pnt.npk:
+            r_pnt.npk = round(r_pnt.npk, 6)
+            list_pts.append(r_pnt)
+
+        return list_pts
+
+    def get_segments_pnts(self, puntos, vert=None, line=False):
+        """ Return
+        """
+        list_lines = []
+        list_attrs = []
+        for i, ali in enumerate(self.list_aligns):
+            pnt_ini = ali.get_roadpoint(0)[0]
+            pnt_ini.align = i + 1
+            pnts_align = [pnt_ini]
+            pnts_align.extend([r_pnt for r_pnt in puntos if ali.is_in(r_pnt)])
+            pnt_end = ali.get_roadpoint(-1)[0]
+            pnt_end.align = i + 1
+            pnts_align.append(pnt_end)
+
+            if vert is not None:
+                vert.set_pnts_elev(pnts_align)
+            if line:
+                list_lines.append(Line(pnts_align))
+            else:
+                list_lines.append(pnts_align)
+            list_attrs.append([ali.get_leng_accum(), ali.__class__.__name__,
+                               round(ali.length(), 3), ali.param(),
+                               ali.grassrgb()])
+        return list_lines, list_attrs
+
+    def get_charact_pnts(self, lines=False):
+        """ Return
+        """
+        list_attrs = []
+        list_obj = []
+
+        for i, ali in enumerate(self.list_aligns):
+            if ali is not None:
+                r_pnt = ali.get_roadpoint(0)[0]
+                if lines:
+                    pnt2 = r_pnt.project(10, r_pnt.azi - math.pi / 2)
+                    list_obj.append(Line([r_pnt, pnt2]))
+                else:
+                    r_pnt.align = ali.__class__.__name__ + '_' + str(i + 1)
+                    list_obj.append(r_pnt)
+                list_attrs.append([r_pnt.get_pk(), r_pnt.get_azi(),
+                                   r_pnt.p_type, ali.param()])
+        for i, ali in enumerate(self.list_aligns[::-1]):
+            if ali is not None:
+                r_pnt = ali.get_roadpoint(-1)[0]
+                break
+        if lines:
+            pnt2 = r_pnt.project(10, r_pnt.azi - math.pi / 2)
+            list_obj.append(Line([r_pnt, pnt2]))
+        else:
+            r_pnt.align = self.list_aligns[-1].__class__.__name__ + '_' + \
+                str(len(self.list_aligns) + 1)
+            list_obj.append(r_pnt)
+        for i, ali in enumerate(self.list_aligns[::-1]):
+            if ali is not None:
+
+                list_attrs.append([ali.get_leng_accum2(),
+                           r_pnt.get_azi(), r_pnt.p_type, 'L=0'])
+                break
+        return list_obj, list_attrs
+
+#    def get_charact_pnts2(self):
+#        """ Return
+#        """
+#        list_obj = []
+#        r_pnt = self.list_aligns[0].get_roadpoint(0)[0]
+#        r_pnt.align = self.list_aligns[0].__class__.__name__ + '_' + str(1)
+#        list_obj.append(r_pnt)
+#        for i, ali in enumerate(self.list_aligns):
+#            if ali is not None:
+#                r_pnt = ali.get_roadpoint(-1)[0]
+#                r_pnt.align = ali.__class__.__name__ + '_' + str(i + 1)
+#                list_obj.append(r_pnt)
+#
+#        return list_obj
+
+    def get_curves_centers(self):
+        """ Return
+        """
+        list_centers = []
+        list_attrs = []
+        for i, ali in enumerate(self.list_aligns):
+            if isinstance(ali, Base.Curve):
+                list_centers.append(ali.p_center)
+                list_attrs.append(['C' + str(i + 1)])
+        return list_centers, list_attrs
+
+
+# =============================================
+# PLANT ALIGN
+# =============================================
+
+class PlantAlign(object):
+    """ Return
+    """
+    def __init__(self, dat, dat1=None, dat2=None, recta1=None, recta2=None):
+        """ Return
+        """
+        self.radio = dat['radio']
+        self.a_in = dat['a_in']
+        self.a_out = dat['a_out']
+        self.dat = dat
+        self.recta1 = recta1
+        self.recta2 = recta2
+        self.dat1 = dat1
+        self.dat2 = dat2
+
+        self.straight = None
+        self.cloth_in = None
+        self.curve = None
+        self.cloth_out = None
+
+        self.in_local = None
+        self.out_local = None
+
+        self._init_align()
+
+    def __str__(self):
+        return self.get_wkt()
+
+    def __repr__(self):
+        return ("PlantAlign( \n" + str(self.straight) + ", \n" +
+                str(self.cloth_in) + ", \n" + str(self.curve) + ", \n" +
+                str(self.cloth_out) + ")\n")
+
+    def _alpha(self):
+        """ Return
+        """
+        a_w = self.recta1.angle(self.recta2)
+        if self.radio > 0:
+            return abs(a_w - self.in_local['tau'] - self.out_local['tau'])
+        else:
+            return abs(a_w + self.in_local['tau'] + self.out_local['tau'])
+
+    def _center(self):
+        """ Return the cutoff point between this straight an a given one.
+        """
+        if self.radio == 0:
+            return Base.RoadPoint(self.recta1.pend, 0, 0)
+        else:
+            recta11 = self.recta1.parallel(abs(self.radio +
+                                               self.in_local['y_o']),
+                                           self.radio)
+            recta22 = self.recta2.parallel(abs(self.radio +
+                                               self.out_local['y_o']),
+                                           self.radio)
+            return recta11.cutoff(recta22)
+
+    def _init_align(self):
+        """ Return
+        """
+        local2_in = False
+        local2_out = False
+
+        if self.radio != 0:
+            self.in_local = Base.cloth_local(self.radio, self.a_in)
+            self.out_local = Base.cloth_local(self.radio, self.a_out)
+
+            alpha = self._alpha()
+        else:
+            alpha = 0
+
+        p_center = self._center()
+
+        if self.dat1['a_out'] < 0 and self.radio != 0:
+            local2_out = Base.cloth_local(self.dat1['radio'],
+                                          self.dat1['a_out'])
+        self.cloth_in = Base.Clothoid(self.a_in, self.radio,
+                                      self.recta1.azimuth(), 'in', local2_out,
+                                      p_center)
+
+        self.recta1.pend = self.cloth_in.pnt_d
+
+        if self.dat1['a_out'] < 0 and self.radio != 0:
+            self.recta1.pstart = self.cloth_in.pnt_p
+
+        if self.radio == 0:
+            az_ini = self.recta1.azimuth()
+        else:
+            az_ini = Base.azimut(p_center, self.cloth_in.pnt_r)
+        self.curve = Base.Curve(self.radio, alpha, az_ini, p_center)
+
+        if self.dat2['a_in'] < 0:
+            local2_in = Base.cloth_local(self.dat2['radio'], self.dat2['a_in'])
+        self.cloth_out = Base.Clothoid(self.a_out, self.radio,
+                                       self.recta2.azimuth(), 'out', local2_in,
+                                       p_center)
+
+        self.straight = Base.Straight(self.recta1.pstart, self.recta1.pend,
+                                      None, None)
+
+    def set_lengs_accum(self, leng_accum):
+        """Return the lenght accum of the aling and set the superelev limits
+        """
+
+        self.straight.leng_accum = leng_accum
+        self.cloth_in.leng_accum = self.straight.leng_accum + \
+            self.straight.length()
+        self.curve.leng_accum = self.cloth_in.leng_accum + \
+            self.cloth_in.length()
+        self.cloth_out.leng_accum = self.curve.leng_accum + self.curve.length()
+
+        return self.cloth_out.leng_accum + self.cloth_out.length()
+
+    def get_aligns(self):
+        """Return
+        """
+        list_aligns = []
+        if self.straight.length() != 0:
+            list_aligns.append(self.straight)
+        if self.cloth_in.a_clot != 0:
+            list_aligns.append(self.cloth_in)
+        if self.curve.radio != 0:
+            list_aligns.append(self.curve)
+        if self.cloth_out.a_clot != 0:
+            list_aligns.append(self.cloth_out)
+
+        return list_aligns
+
+    def get_super_lim(self, bombeo):
+        """Return
+        """
+        super_lim = []
+        tot_accum = self.cloth_out.leng_accum + self.cloth_out.length()
+
+        if (self.dat['superelev'] != '' and self.dat['superelev'] != None and
+                self.dat['superelev'] != 'None'):
+
+            dist1, dist2, bom1, peral, bom2, dist3, dist4 = \
+                [float(p) for p in self.dat['superelev'].split(',')]
+            # d1, d2, b, p, b, d2, d1
+            super_lim = [[self.cloth_in.leng_accum - dist1,
+                          self.cloth_in.leng_accum,
+                          self.cloth_in.leng_accum + dist2,
+                          self.curve.leng_accum],
+                         [self.cloth_out.leng_accum,
+                          tot_accum - dist3,
+                          tot_accum,
+                          tot_accum + dist4], bom1, peral, bom2, self.radio]
+        elif bombeo != 0 and self.cloth_in.length() != 0 and \
+                self.cloth_out.length() != 0:
+
+            super_lim = [
+                [self.cloth_in.leng_accum - self.cloth_in.length() / 2,
+                 self.cloth_in.leng_accum,
+                 self.cloth_in.leng_accum + self.cloth_in.length() / 2,
+                 self.curve.leng_accum],
+                [self.cloth_out.leng_accum,
+                 tot_accum - self.cloth_out.length() / 2,
+                 tot_accum,
+                 tot_accum + self.cloth_out.length() / 2],
+                bombeo, bombeo, bombeo,
+                self.radio]
+
+        return super_lim
+
+    def get_endpnt(self):
+        """ Return
+        """
+        return self.cloth_out.pnt_d
+
+    def length(self):
+        """ Return
+        """
+        return self.straight.length() + self.cloth_in.length() + \
+            self.curve.length() + self.cloth_out.length()
+
+
+# =============================================
+# PLANT
+# =============================================
+
+class Plant(Aligns, object):
+    """ Return
+    """
+    def __init__(self, polygon=None, road_table=None,
+                 table_to_plan=False, bombeo=0):
+        """ Return
+        """
+        self.bombeo = bombeo
+        self.polygon = polygon
+        self.road_table = road_table
+
+        self.straight_curve_lengs = [0]
+        self.list_aligns = []
+        self.superelev_lim = []
+
+        if table_to_plan is False:
+            self._init_poly_to_plant()
+        else:
+            self._init_table_to_plant()
+
+        super(Plant, self).__init__(self.list_aligns)
+
+    def __str__(self):
+        return self.get_wkt()
+
+#    def __repr__(self):
+#        return "[" + self.align + "]"
+
+#    def get_wkt(self):
+#        """Return a "well know text" (WKT) geometry string. ::
+#        """
+#        return "[" + str(self.align) + "]"
+
+    def _init_poly_to_plant(self):
+        """ Return
+        """
+        dat1 = []
+        dat2 = []
+
+        line = self.polygon
+        leng_accum = 0
+
+        for i, dat3 in enumerate(self.road_table):
+
+            if i >= 2:
+                if i == 2:
+                    end_pnt = line[0]
+
+                recta1 = Base.Straight(end_pnt, line[i - 1])
+                recta2 = Base.Straight(line[i - 1], line[i])
+
+                alig = PlantAlign(dat2, dat1, dat3, recta1, recta2)
+
+                leng_accum = alig.set_lengs_accum(leng_accum)
+                self.list_aligns.extend(alig.get_aligns())
+                end_pnt = alig.get_endpnt()
+
+                self.straight_curve_lengs.append(alig.straight.length())
+                self.straight_curve_lengs.append(alig.curve.length())
+
+                self.superelev_lim.append(alig.get_super_lim(self.bombeo))
+
+            dat1 = dat2
+            dat2 = dat3
+
+            if i == len(self.road_table) - 1:
+                if len(self.road_table) == 2:
+                    end_pnt = line[i - 1]
+
+                recta1 = Base.Straight(end_pnt, line[-1])
+                recta1.leng_accum = leng_accum
+                self.list_aligns.append(recta1)
+                self.straight_curve_lengs.append(recta1.length())
+
+    def _init_table_to_plant(self):
+        """ Return
+        """
+        pnt_center = Base.RoadPoint(self.polygon[0])
+        pnt_1 = Base.RoadPoint(self.polygon[1])
+        recta_1 = Base.Straight(pnt_center, pnt_1)
+
+        rectas = []
+        new_rows = []
+
+        for i, dat in enumerate(self.road_table):
+
+            new_rows.append(dat)
+
+            if dat['lr_'] != 0:
+                new_rows.append({'radio': 0.0, 'a_in': 0.0, 'a_out': 0.0,
+                                 'dc_': dat['dc_'], 'lr_': dat['lr_']})
+
+        for i, dat in enumerate(new_rows[:-1]):
+
+            dat1 = new_rows[i]
+            dat2 = new_rows[i + 1]
+
+            if dat1['radio'] == 0 and dat2['radio'] == 0:
+                continue
+            elif dat1['radio'] == 0:
+                pnt_center, pnt_1, recta_1 = \
+                    self._staight_curve(pnt_center, pnt_1, dat1, dat2)
+                if i == 1:
+                    self.list_aligns.insert(0, recta_1)
+                    self.straight_curve_lengs.insert(1, recta_1.length())
+            elif dat2['radio'] == 0:
+                pnt_center, pnt_1, recta_1 = \
+                    self._curve_straight(pnt_center, pnt_1, dat1, dat2)
+
+            elif abs(dat1['radio']) > abs(dat2['radio']) and dat1['a_out'] < 0:
+                pnt_center, pnt_1, recta_1 = \
+                    self._curve_high_low(pnt_center, pnt_1, dat1, dat2)
+
+            elif abs(dat1['radio']) > abs(dat2['radio']) and dat2['a_in'] < 0:
+                pnt_center, pnt_1, recta_1 = \
+                    self._curve_low_high(pnt_center, pnt_1, dat1, dat2)
+            else:
+                raise ValueError('Error')
+
+            rectas.append(recta_1)
+
+        new_polygon = [rectas[0].pstart]
+        for i, recta in enumerate(rectas[:-1]):
+            if round(recta.azimuth(), 8) == round(rectas[i + 1].azimuth(), 8):
+                continue
+            new_polygon.append(recta.cutoff(rectas[i + 1]))
+        new_polygon.append(rectas[-1].pend)
+        self.polygon = Line(new_polygon)
+        self.road_table.polyline = new_polygon
+
+    def _curve_high_low(self, pnt_center, pnt_1, dat1, dat2):
+        """ Return
+        """
+        # R1>R2
+        # Calculamos los puntos de tangencia de la clotoide con los dos circulo
+        out_local = Base.cloth_local(dat1['radio'], dat1['a_out'])
+        in_local = Base.cloth_local(dat2['radio'], dat2['a_in'])
+
+        azi_in = pnt_center.azimuth(pnt_1)
+        alpha = dat2['dc_'] / dat2['radio']
+
+        if dat1['radio'] > 0 and dat2['radio'] > 0:
+            g90 = math.pi / 2
+        elif dat1['radio'] < 0 and dat2['radio'] < 0:
+            g90 = -math.pi / 2
+        else:
+            raise ValueError("Error: For change the radio sing a straight must be \
+                             between the radios")
+            return None, None, None
+
+        pnt_t1 = pnt_center.project(abs(dat1['radio'] + out_local['y_o']),
+                                    azi_in - out_local['tau'])
+
+        pnt_t2 = pnt_t1.project(in_local['x_o'] - out_local['x_o'],
+                                azi_in - out_local['tau'] + g90)
+
+        pnt_ad2 = pnt_t1.project(out_local['x_o'], azi_in - out_local['tau'] +
+                                 g90)
+
+        pnt_c2 = pnt_t2.project(abs(dat2['radio'] + in_local['y_o']),
+                                azi_in - out_local['tau'] + 2 * g90)
+
+        pnt_ar2 = pnt_c2.project(abs(dat2['radio'], azi_in - out_local['tau'] +
+                                     in_local['tau']))
+
+        pnt_ra2 = pnt_c2.project(abs(dat2['radio']), azi_in -
+                                 out_local['tau'] + in_local['tau'] + alpha)
+
+        if dat2['a_in'] != 0:
+            cloth = Base.Clothoid(dat2['a_in'], dat2['radio'],
+                                  pnt_ad2.azimuth(pnt_t2), 'in', None, pnt_c2)
+            self.list_aligns.append()
+            self.straight_curve_lengs.append(cloth.length())
+
+        curve = Base.Curve(dat2['radio'], alpha, pnt_c2.azimuth(pnt_ar2),
+                           pnt_c2)
+        self.list_aligns.append(curve)
+        self.straight_curve_lengs.append(curve.length())
+
+        return pnt_c2, pnt_ra2, Base.Straight(pnt_ad2, pnt_t1)
+
+    def _curve_low_high(self, pnt_center, pnt_1, dat1, dat2):
+        """ Return
+        """
+        # R1<R2
+        out_local = Base.cloth_local(dat1['radio'], dat1['a_out'])
+        in_local = Base.cloth_local(dat2['radio'], dat2['a_in'])
+
+        azi_in = pnt_center.azimuth(pnt_1)
+        alpha = dat2['dc_'] / dat2['radio']
+
+        if dat1['radio'] > 0 and dat2['radio'] > 0:
+            g90 = math.pi / 2
+        elif dat1['radio'] < 0 and dat2['radio'] < 0:
+            g90 = -math.pi / 2
+        else:
+            raise ValueError("Error: For change the radio sing a straight \
+                             must be between the radios")
+            return None, None, None
+
+        pnt_t1 = pnt_center.project(abs(dat1['radio'] + out_local['y_o']),
+                                    azi_in + out_local['tau'])
+
+        pnt_t2 = pnt_t1.project(in_local['x_o'] - out_local['x_o'],
+                                azi_in + out_local['tau'] + g90)
+
+        pnt_da1 = pnt_t1.project(out_local['x_o'], azi_in + out_local['tau'] +
+                                 g90)
+
+        pnt_c2 = pnt_t2.project(abs(dat2['radio'] + in_local['y_o']),
+                                azi_in + out_local['tau'] + 2 * g90)
+
+        pnt_ra2 = pnt_c2.project(abs(dat2['radio']), azi_in + out_local['tau']
+                                 - in_local['tau'] + alpha)
+
+        if dat1['a_out'] != 0:
+            cloth = Base.Clothoid(dat1['a_out'], dat1['radio'],
+                                  pnt_t1.azimuth(pnt_da1), 'out', None, pnt_c2)
+            self.list_aligns.append(cloth)
+            self.straight_curve_lengs.append(cloth.length())
+
+        curve = Base.Curve(dat2['radio'], alpha, pnt_c2.azimuth(pnt_ra2),
+                           pnt_c2)
+        self.list_aligns.append(curve)
+        self.straight_curve_lengs.append(curve.length())
+
+        return pnt_c2, pnt_ra2, Base.Straight(pnt_t1, pnt_da1)
+
+    def _curve_straight(self, pnt_center, pnt_1, dat1, dat2):
+        """ Return
+        """
+        # R1 != 0 y R2 = 0
+        out_local = Base.cloth_local(dat1['radio'], dat1['a_out'])
+
+        azi_in = pnt_center.azimuth(pnt_1)
+        # pnt_ra = pnt_1
+
+        if dat1['radio'] > 0:
+            g90 = math.pi / 2
+        else:
+            g90 = -math.pi / 2
+
+        pnt_t1 = pnt_center.project(abs(dat1['radio'] + out_local['y_o']),
+                                    azi_in + out_local['tau'])
+
+        pnt_da = pnt_t1.project(out_local['x_o'], azi_in + out_local['tau'] +
+                                g90)
+
+        azi_out = pnt_center.azimuth(pnt_t1) + g90
+
+        if dat1['a_out'] == 0:
+            # pnt_da = pnt_ra
+            pnt_da = pnt_1
+        else:
+            cloth = Base.Clothoid(dat1['a_out'], dat1['radio'], azi_out, 'out',
+                                  None, pnt_center)
+            self.list_aligns.append(cloth)
+            self.straight_curve_lengs.append(cloth.length())
+
+        pnt_out = pnt_da.project(dat2['lr_'], azi_in + out_local['tau'] +
+                                 g90)
+
+        recta = Base.Straight(pnt_da, pnt_out)
+        self.list_aligns.append(recta)
+        self.straight_curve_lengs.append(recta.length())
+
+        return pnt_da, pnt_out, Base.Straight(pnt_da, pnt_out)
+
+    def _staight_curve(self, pnt_center, pnt_1, dat1, dat2):
+        """ Return
+        """
+        # R1 = 0 y R2 != 0
+        in_local = Base.cloth_local(dat2['radio'], dat2['a_in'])
+
+        alpha = dat2['dc_'] / dat2['radio']
+
+        azi_in = pnt_center.azimuth(pnt_1)
+        pnt_ad = pnt_center.project(dat1['lr_'], azi_in)
+
+        pnt_t2 = pnt_ad.project(in_local['x_o'], azi_in)
+
+        if dat2['radio'] > 0:
+            g90 = math.pi / 2
+        else:
+            g90 = -math.pi / 2
+
+        pnt_c2 = pnt_t2.project(abs(dat2['radio'] + in_local['y_o']), azi_in +
+                                g90)
+        pnt_c2.npk = dat1['lr_']
+
+        az_in_c = azi_in + in_local['tau'] - g90
+        if az_in_c < 0:
+            az_in_c += 2 * math.pi
+
+        pnt_ra = pnt_c2.project(abs(dat2['radio']),
+                                az_in_c + alpha)
+        pnt_ra.npk = dat1['lr_']
+
+        if dat2['a_in'] != 0:
+            cloth = Base.Clothoid(dat2['a_in'], dat2['radio'], azi_in, 'in',
+                                  None, pnt_c2)
+            self.list_aligns.append(cloth)
+            self.straight_curve_lengs.append(cloth.length())
+
+        curve = Base.Curve(dat2['radio'], abs(alpha), az_in_c, pnt_c2)
+        self.list_aligns.append(curve)
+        self.straight_curve_lengs.append(curve.length())
+
+        return pnt_c2, pnt_ra, Base.Straight(pnt_center, pnt_ad)
+
+    def get_charact(self):
+        """ Return
+        """
+        list_pnt = []
+#        list_pnt.append(self.list_aligns[0].get_roadpoint(0)[0])
+        for i, ali in enumerate(self.list_aligns):
+            pnt = ali.get_roadpoint(-1)[0]
+            pnt.npk = self.leng_accum[i + 1]
+            list_pnt.append(pnt)
+        return list_pnt
+
+    @time_func
+    def set_roadline(self, start, end, intr, intc):
+        """ Return
+        """
+        puntos = self.get_roadpnts(start, end, intr, intc)
+#        pnts_char = self.get_charact_pnts2()
+        # Name lenght type param rgb
+        attrs = ['Central_Axis', self.length(), 'axis', 0, '255:0:0']
+        self.roadline = Base.RoadLine(puntos, attrs, 'Central_Axis')
+
+    def add_pks(self, list_pks):
+        """ Return
+        """
+        for pk in list_pks:
+            self.roadline.insert(self.get_roadpoint(pk))
+
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()


Property changes on: grass-addons/grass7/vector/v.civil/road_plant.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: grass-addons/grass7/vector/v.civil/road_profiles.py
===================================================================
--- grass-addons/grass7/vector/v.civil/road_profiles.py	                        (rev 0)
+++ grass-addons/grass7/vector/v.civil/road_profiles.py	2016-07-01 22:30:22 UTC (rev 68831)
@@ -0,0 +1,478 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Thu Sep 11 00:29:15 2014
+
+ at author: meskal
+"""
+
+#
+# import pygrass modules
+#
+import math
+
+# import road_base as Base
+# from grass.pygrass.raster import RasterRow
+
+from grass.pygrass.vector.geometry import Point
+from grass.pygrass.gis.region import Region
+from grass.pygrass.vector.geometry import Line
+
+
+class LongProfile(object):
+    """ Return
+    """
+    def __init__(self, options, scale, offset='0,0'):
+        """ Return
+        """
+        opts = options.split(',')
+        self.mark_lon = float(opts[0])
+        self.mark_x_dist = int(opts[1])
+        self.mark_y_dist = int(opts[2])
+        self.dist_ejes_x = float(opts[3])
+        self.scale = float(scale)
+
+        reg = Region()
+        self.zero_x = int(reg.west) + int(offset.split(',')[0])
+        self.zero_y = int(reg.south) + int(offset.split(',')[1])
+
+        self.max_elev = 0
+        self.min_elev = 0
+        self.alt_y = 0
+
+    def set_maxmin(self, r_line):
+        """Return
+        """
+        max_z = max([r_pnt.z for r_pnt in r_line])
+        max_t = max([r_pnt.terr for r_pnt in r_line])
+        min_z = min([r_pnt.z for r_pnt in r_line])
+        min_t = min([r_pnt.terr for r_pnt in r_line])
+
+        self.max_elev = math.ceil(max(max_z, max_t))
+        self.min_elev = math.floor(min(min_z, min_t))
+
+        self.alt_y = int((self.max_elev - self.min_elev) * self.scale +
+                         self.zero_y)
+#        if self.alt_y % int(self.mark_y_dist * self.scale) != 0:
+#            self.alt_y += int(self.mark_y_dist * self.scale)
+
+    def _axis_y(self):
+        """Return
+        """
+        return [Line([Point(self.zero_x, self.zero_y),
+                      Point(self.zero_x, self.alt_y)])], [['Axis Y', '', '']]
+
+    def _axis_x(self, r_line):
+        """Return
+        """
+        lines = []
+        for j in range(0, 4):
+            lines.append(Line([Point(self.zero_x,
+                                     self.zero_y - j * self.dist_ejes_x),
+                               Point(self.zero_x + r_line[-1].npk,
+                                     self.zero_y - j * self.dist_ejes_x)]))
+        return lines, [['Axis X', '', ''], ['Elevation', '', ''],
+                       ['Terrain', '', ''], ['Red elevation', '', '']]
+
+    def get_axes(self, puntos):
+        """Return
+        """
+        prof_axes, prof_axes_attrs = self._axis_y()
+        prof_axes_x, prof_axes_attrs_x = self._axis_x(puntos)
+        prof_axes.extend(prof_axes_x)
+        prof_axes_attrs.extend(prof_axes_attrs_x)
+
+        return prof_axes, prof_axes_attrs
+
+    def _axis_y_marks(self):
+        """Return
+        """
+        mark_y = []
+        labels = []
+        lim_sup = self.alt_y
+        if lim_sup % int(self.mark_y_dist * self.scale) != 0:
+            lim_sup += int(self.mark_y_dist * self.scale)
+        for i in range(self.zero_y, lim_sup, int(self.mark_y_dist *
+                                                 self.scale)):
+            # labels.append(self.min_elev + i / self.scale)
+            labels.append(self.min_elev + (i - self.zero_y) / self.scale)
+            mark_y.append(Line([Point(self.zero_x - self.mark_lon, i),
+                                Point(self.zero_x + self.mark_lon, i)]))
+        return mark_y, labels
+
+    def _axis_x_marks(self, r_line):
+        """Return
+        """
+        lim_sup = int(r_line[-1].npk)
+        if lim_sup % self.mark_x_dist != 0:
+            lim_sup += self.mark_x_dist
+        rang = range(0, lim_sup, self.mark_x_dist)
+
+        label_npk, label_z, label_terr, label_cotaroja = [], [], [], []
+        for r_pnt in r_line:
+            if r_pnt.npk in rang:
+                # pnts_marks.append(r_pnt)
+                label_npk.append(r_pnt.npk)
+                label_z.append(round(r_pnt.z, 4))
+                label_terr.append(round(r_pnt.terr, 4))
+                label_cotaroja.append(round(r_pnt.z - r_pnt.terr, 4))
+        label_npk.append(int(r_line[-1].npk))
+        label_z.append(r_line[-1].z)
+        label_terr.append(r_line[-1].terr)
+        label_cotaroja.append(r_line[-1].z - r_line[-1].terr)
+        labels_lines = label_npk + label_z + label_terr + label_cotaroja
+
+        rang = range(self.zero_x, self.zero_x + lim_sup, self.mark_x_dist)
+
+        lines = []
+        for j in range(0, 4):
+            mark_x = []
+            for i in rang:
+                mark_x.append(Line([
+                    Point(i, self.zero_y - self.mark_lon - j *
+                          self.dist_ejes_x),
+                    Point(i, self.zero_y + self.mark_lon - j *
+                          self.dist_ejes_x)]))
+            lines.extend(mark_x)
+
+        return lines, labels_lines
+
+    def get_axes_marks(self, puntos):
+        """Return
+        """
+        prof_ticks, prof_ticks_attrs = self._axis_y_marks()
+        prof_ticks_x, prof_ticks_attrs_x = self._axis_x_marks(puntos)
+        prof_ticks.extend(prof_ticks_x)
+        prof_ticks_attrs.extend(prof_ticks_attrs_x)
+        prof_ticks_attrs = [[str(tick)] for tick in prof_ticks_attrs]
+        return prof_ticks, prof_ticks_attrs
+
+    def _ras_segments(self, vert_segs):
+        """Return
+        """
+        lines = []
+        for r_line in vert_segs:
+
+            lines.append(self._ras(r_line))
+        return lines
+
+    def _ras(self, r_line):
+        """Return(self.max_elev - self.min_elev)
+        """
+        line = []
+        for r_pnt in r_line:
+            line.append(Point(r_pnt.npk + self.zero_x,
+                              (r_pnt.z - self.min_elev) * self.scale +
+                              self.zero_y))
+        return Line(line)
+
+    def _terr(self, r_line):
+        """Return
+        """
+        line = []
+        for r_pnt in r_line:
+            line.append(Point(r_pnt.npk + self.zero_x,
+                              (r_pnt.terr - self.min_elev) * self.scale +
+                              self.zero_y))
+        return Line(line)
+
+    def get_ras_terr(self, puntos, vert):
+        """Return
+        """
+        vert_segs, vert_attrs = vert.get_segments_pnts(puntos)
+        prof_segs = self._ras_segments(vert_segs)
+
+        prof_terr = self._terr(puntos)
+        prof_terr_attrs = ['0+000.0', 'Terrain', '0', '0', '']
+        prof_segs.append(prof_terr)
+        vert_attrs.append(prof_terr_attrs)
+
+        return prof_segs, vert_attrs
+
+    def charact_pnts(self, vert):
+        """Return
+        """
+        char_r_pnts, char_r_pnts_attrs = vert.get_charact_pnts()
+        list_r_pnts = []
+        for r_pnt in char_r_pnts:
+            list_r_pnts.append(Point(r_pnt.npk + self.zero_x,
+                                     (r_pnt.z - self.min_elev) * self.scale +
+                                     self.zero_y))
+        return list_r_pnts, char_r_pnts_attrs
+
+
+class TransProfiles(object):
+    """ Return
+    """
+    def __init__(self, options1, options2, scale, offset='0,0'):
+        """ Return
+        """
+        self.opts1 = dict(zip(['mark_lon', 'mark_x_dist', 'mark_y_dist'],
+                              [int(opt) for opt in options1.split(',')]))
+
+        self.opts2 = dict(zip(['rows', 'dist_axis_x', 'dist_axis_y'],
+                              [int(opt) for opt in options2.split(',')]))
+
+        self.scale = float(scale)
+
+        self.cols = 0
+        reg = Region()
+        self.zero_x = int(reg.west) + int(offset.split(',')[0])
+        self.zero_y = int(reg.south) + int(offset.split(',')[1])
+
+        self.mat_trans = []
+
+        self.rows_height = []
+        self.cols_width_left = [0]
+        self.cols_width_right = [0]
+
+        self.centers = []
+
+    def set_maxmin(self, trans, terr):
+        """Return
+        """
+        self.cols = int(math.ceil(len(trans) / self.opts2['rows']))
+        step = 0
+        maxtix = []
+        for i in range(self.cols):
+            row = []
+            for j in range(self.opts2['rows']):
+                trans[step].set_terr_pnts(terr)
+                row.append(trans[step])
+                step = step + 1
+            maxtix.append(row)
+
+        transp = [[row1[i] for row1 in maxtix] for i in range(len(maxtix[0]))]
+        for row in maxtix:
+            max_col_left = math.ceil(max([tran.max_left_width()
+                                          for tran in row]))
+            max_col_right = math.ceil(max([tran.max_right_width()
+                                           for tran in row]))
+            if max_col_left % self.opts1['mark_x_dist']:
+                max_col_left += self.opts1['mark_x_dist']
+                max_col_left -= max_col_left % self.opts1['mark_x_dist']
+            if max_col_right % self.opts1['mark_x_dist']:
+                max_col_right += self.opts1['mark_x_dist']
+                max_col_right -= max_col_right % self.opts1['mark_x_dist']
+
+            self.cols_width_left.append(max_col_left)
+            self.cols_width_right.append(max_col_right)
+
+        for row in transp:
+
+            difer = [tran.max_height() - tran.min_height() for tran in row]
+            max_height = max(difer) * self.scale
+            lim_sup = max([self._get_trans_lim_sup(tran) for tran in row])
+            self.rows_height.append(max([max_height, lim_sup]))
+
+        total_height = sum(self.rows_height) + (self.opts2['dist_axis_y'] *
+                                                self.opts2['rows'])
+        self.zero_y += total_height
+        self.mat_trans = maxtix
+
+    def set_centers(self):
+        """Return
+        """
+        orig_x = self.zero_x
+        for i in range(self.cols):
+            orig_x += self.cols_width_left[i] + self.cols_width_right[i]
+            row = []
+            orig_y = self.zero_y
+            for j in range(self.opts2['rows']):
+                orig_y -= self.rows_height[j] + self.opts2['dist_axis_y']
+                row.append(Point(orig_x, orig_y))
+            orig_x += self.opts2['dist_axis_x']
+            self.centers.append(row)
+
+    def _get_trans_lim_sup(self, trans):
+        """Return
+        """
+        lim_sup = ((trans.max_height() - trans.min_height()) * self.scale)
+
+        if lim_sup % int(self.opts1['mark_y_dist'] * self.scale) != 0:
+            lim_sup += int(self.opts1['mark_y_dist'] * self.scale)
+            lim_sup -= lim_sup % int(self.opts1['mark_y_dist'] * self.scale)
+        return lim_sup
+
+    def _axes_y(self):
+        """Return
+        """
+        list_lines = []
+        list_attrs = []
+        for i in range(self.cols):
+            for j in range(self.opts2['rows']):
+                lim_sup = self._get_trans_lim_sup(self.mat_trans[i][j])
+                pnt2 = Point(self.centers[i][j].x, self.centers[i][j].y +
+                             lim_sup)
+                list_lines.append(Line([self.centers[i][j], pnt2]))
+                list_attrs.append(['Axis Y', '', ''])
+        return list_lines, list_attrs
+
+    def _axes_y_marks(self):
+        """Return
+        """
+        mark_y = []
+        labels = []
+
+        for i in range(self.cols):
+            for j in range(self.opts2['rows']):
+                lim_sup = self._get_trans_lim_sup(self.mat_trans[i][j])
+
+                for k in range(0, int(lim_sup) + 1,
+                               int(self.opts1['mark_y_dist'] * self.scale)):
+
+                    labels.append([self.mat_trans[i][j].min_height() + k /
+                                   self.scale])
+                    mark_y.append(Line([Point(self.centers[i][j].x -
+                                              self.opts1['mark_lon'], k +
+                                              self.centers[i][j].y),
+                                        Point(self.centers[i][j].x +
+                                              self.opts1['mark_lon'], k +
+                                              self.centers[i][j].y)]))
+        return mark_y, labels
+
+    def _axes_x(self):
+        """Return
+        """
+        list_lines = []
+        list_attrs = []
+        for i in range(self.cols):
+            for j in range(self.opts2['rows']):
+                pnt2 = Point(self.centers[i][j].x +
+                             self.cols_width_left[i + 1] +
+                             self.cols_width_right[i + 1],
+                             self.centers[i][j].y)
+                list_lines.append(Line([self.centers[i][j], pnt2]))
+                list_attrs.append(['Axis X', '', ''])
+        return list_lines, list_attrs
+
+    def _axes_x_marks(self):
+        """Return
+        """
+        mark_x = []
+        labels = []
+        for i in range(self.cols):
+            for j in range(self.opts2['rows']):
+
+                for k in range(int(self.cols_width_left[i + 1]), 0,
+                               -int(self.opts1['mark_x_dist'])):
+                    pnt1 = Point(self.centers[i][j].x +
+                                 self.cols_width_left[i + 1] - k,
+                                 self.centers[i][j].y - self.opts1['mark_lon'])
+                    pnt2 = Point(self.centers[i][j].x +
+                                 self.cols_width_left[i + 1] - k,
+                                 self.centers[i][j].y + self.opts1['mark_lon'])
+                    mark_x.append(Line([pnt1, pnt2]))
+                    labels.append([-k])
+
+                pnt1 = Point(self.centers[i][j].x +
+                             self.cols_width_left[i + 1],
+                             self.centers[i][j].y - self.opts1['mark_lon'] - 1)
+                pnt2 = Point(self.centers[i][j].x +
+                             self.cols_width_left[i + 1],
+                             self.centers[i][j].y + self.opts1['mark_lon'] + 1)
+                mark_x.append(Line([pnt1, pnt2]))
+                labels.append([0])
+
+                for k in range(int(self.opts1['mark_x_dist']),
+                               int(self.cols_width_right[i + 1]) + 1,
+                               int(self.opts1['mark_x_dist'])):
+                    pnt1 = Point(self.centers[i][j].x +
+                                 self.cols_width_left[i + 1] + k,
+                                 self.centers[i][j].y - self.opts1['mark_lon'])
+                    pnt2 = Point(self.centers[i][j].x +
+                                 self.cols_width_left[i + 1] + k,
+                                 self.centers[i][j].y + self.opts1['mark_lon'])
+                    mark_x.append(Line([pnt1, pnt2]))
+                    labels.append([k])
+
+        return mark_x, labels
+
+    def get_axes(self):
+        """Return
+        """
+        axes, axes_attrs = self._axes_y()
+        axes_x, axes_x_attrs = self._axes_x()
+        axes.extend(axes_x)
+        axes_attrs.extend(axes_x_attrs)
+
+        return axes, axes_attrs
+
+    def get_axes_marks(self):
+        """Return
+        """
+        prof_ticks, prof_ticks_attrs = self._axes_y_marks()
+        prof_ticks_x, prof_ticks_attrs_x = self._axes_x_marks()
+        prof_ticks.extend(prof_ticks_x)
+        prof_ticks_attrs.extend(prof_ticks_attrs_x)
+
+        return prof_ticks, prof_ticks_attrs
+
+    def _ras(self):
+        """Return
+        """
+        list_lines = []
+        list_attrs = []
+        for i, col in enumerate(self.mat_trans):
+            for j, tran in enumerate(col):
+                line = []
+                for r_pnt in tran.get_ras_pnts():
+                    diff = self.cols_width_left[i + 1] - tran.max_left_width()
+                    line.append(Point(r_pnt.npk + self.centers[i][j].x + diff,
+                                      (r_pnt.z - tran.min_height()) *
+                                      self.scale + self.centers[i][j].y))
+                list_lines.append(Line(line))
+                list_attrs.append([tran.r_pnt.npk, 'Ras', tran.length(), '',
+                                   '0:0:255'])
+        return list_lines, list_attrs
+
+    def ras_pnts(self):
+        """Return
+        """
+        list_pnts = []
+        list_attrs = []
+        for i, col in enumerate(self.mat_trans):
+            for j, tran in enumerate(col):
+                for r_pnt in tran.get_ras_pnts():
+
+                    diff = self.cols_width_left[i + 1] - tran.max_left_width()
+                    list_pnts.append(Point(r_pnt.npk + self.centers[i][j].x +
+                                           diff,
+                                           (r_pnt.z - tran.min_height()) *
+                                           self.scale +
+                                           self.centers[i][j].y))
+                    list_attrs.append([r_pnt.dist_displ, round(r_pnt.z, 4),
+                                       round(r_pnt.z - tran.r_pnt.z, 4)])
+
+        return list_pnts, list_attrs
+
+    def _terr(self):
+        """Return
+        """
+        list_lines = []
+        list_attrs = []
+        for i, col in enumerate(self.mat_trans):
+            for j, tran in enumerate(col):
+                line = []
+                for r_pnt in tran.terr_pnts:
+                    diff = self.cols_width_left[i + 1] - tran.max_left_width()
+                    line.append(Point(r_pnt.npk + self.centers[i][j].x + diff,
+                                      (r_pnt.terr - tran.min_height()) *
+                                      self.scale + self.centers[i][j].y))
+                list_lines.append(Line(line))
+                list_attrs.append([tran.r_pnt.npk, 'Terr', tran.length(), '',
+                                   '166:75:45'])
+        return list_lines, list_attrs
+
+    def get_ras_terr(self):
+        """Return
+        """
+        ras, ras_attrs = self._ras()
+        ras_terr, ras_terr_attrs = self._terr()
+        ras.extend(ras_terr)
+        ras_attrs.extend(ras_terr_attrs)
+
+        return ras, ras_attrs
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()


Property changes on: grass-addons/grass7/vector/v.civil/road_profiles.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: grass-addons/grass7/vector/v.civil/road_road.py
===================================================================
--- grass-addons/grass7/vector/v.civil/road_road.py	                        (rev 0)
+++ grass-addons/grass7/vector/v.civil/road_road.py	2016-07-01 22:30:22 UTC (rev 68831)
@@ -0,0 +1,342 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Tue Sep 23 11:34:58 2014
+
+ at author: meskal
+"""
+
+# import math
+import time
+# import grass.script as grass
+from grass.pygrass.vector import VectorTopo
+
+# from grass.pygrass.vector.table import Link
+
+# import road_base as Base
+import road_plant as Plant
+import road_vertical as Vert
+import road_displ as Displ
+import road_trans as Trans
+import road_terr as Terr
+import road_tables as Tables
+import road_profiles as Profile
+import road_marks as Marks
+# import road_topotools as Topotools
+
+
+def time_func(funcion_f):
+    """Return
+    """
+    def funcion_r(*arg):
+        """Return
+        """
+        t_1 = time.clock()
+        res = funcion_f(*arg)
+        t_2 = time.clock()
+        print('%s tarda %0.5f ms' % (funcion_f.__name__, (t_2 - t_1) * 1000.0))
+        return res
+    return funcion_r
+
+
+# =============================================
+# PLANT
+# =============================================
+
+
+class Road(object):
+    """Instantiate a new road with a polygon map and instantiate. For run
+    doctest you must to execute the example backup in the documentation
+    >>> import road_road as Road
+    >>> road = Road.Road('Circuit')
+    >>> road
+    Circuit
+    """
+    def __init__(self, mapa=None):
+
+        self.mapa = mapa.split('@')[0]
+
+        self.polygon = VectorTopo(self.mapa)
+
+#        super(Road, self).__init__(self.mapa, self.polygon)
+        self.rtab = Tables.RoadTables(self.mapa, self.polygon)
+
+
+        self.plant = None
+        self.vert = None
+        self.displ = None
+        self.trans = None
+        self.terr = None
+        self.taludes = None
+        self.long_prof = None
+        self.trans_prof = None
+        self.marks = None
+
+    def __str__(self):
+        return str(self.mapa)
+
+    def __repr__(self):
+        return str(self.mapa)
+
+    @time_func
+    def plant_generate(self, table_to_plant=False, bombeo=0):
+        """Set plant.
+        """
+        tabla = self.rtab.tables['_Plan']
+
+        if table_to_plant:
+            self.plant = Plant.Plant(self.rtab.polyline, tabla,
+                                     table_to_plan=True, bombeo=bombeo)
+            self.rtab.tables['first'].rewrite_obj(
+                self.plant.polygon, self.rtab.tables['first'].rows[0])
+        else:
+            self.plant = Plant.Plant(self.rtab.polyline, tabla,
+                                     table_to_plan=False, bombeo=bombeo)
+            tabla.update_plan_dists(self.plant)
+
+#        self.update_tables_pnts(self.plant)
+
+    def plant_write(self):
+        """Write axis road
+        """
+        map_out = self.mapa + Tables.OUT_TABLES_NAMES['__Plant']
+
+        objs, values = self.plant.get_segments_pnts(self.plant.roadline,
+                                                    self.vert, line=True)
+        self.rtab.new_map(map_out, 1, '__Plant', objs, values)
+#        self.vert.set_lines_elev(segs)
+
+        objs, values = self.plant.get_charact_pnts(lines=False)
+        self.rtab.new_map(map_out, 2, '__Plant_PC', objs, values)
+
+        objs, values = self.plant.get_curves_centers()
+        self.rtab.new_map(map_out, 3, '__Plant_C', objs, values)
+
+    @time_func
+    def elev_generate(self):
+        """ Return
+        """
+        tabla = self.rtab.tables['_Vert']
+        self.vert = Vert.Vert(self.rtab.polyline, tabla, self.plant)
+
+    def elev_write(self):
+        """ Return
+        """
+        map_out = self.mapa + Tables.OUT_TABLES_NAMES['__Vertical']
+
+        objs, values = self.vert.get_segments_pnts(self.plant.roadline,
+                                                   line=True)
+        self.rtab.new_map(map_out, 1, '__Vertical', objs, values)
+
+        objs, values = self.vert.get_charact_pnts()
+        self.rtab.new_map(map_out, 2, '__Vertical_PC', objs, values)
+
+    @time_func
+    def displ_generate(self, tab_subname=''):
+        """ Return
+        """
+        tabla = self.rtab.tables['_Displ' + tab_subname]
+        self.displ = Displ.Displaced(self.polygon, tabla, self.plant)
+
+    def displ_write(self, tab_subname=''):
+        """ Return
+        """
+        map_out = self.mapa + Tables.OUT_TABLES_NAMES['__Displaced'] + \
+            tab_subname
+
+        objs, values = self.displ.get_lines()
+        self.rtab.new_map(map_out, 1, '__Displaced', objs, values, tab_subname)
+
+        objs, values = self.displ.get_charact()
+        self.rtab.new_map(map_out, 2, '__Displaced_PC', objs, values,
+                          tab_subname)
+
+    def displ_areas_write(self, opts, tab_subname=''):
+        """ Return
+        """
+        tab_sufix = '__Displaced_Areas'
+        map_out = self.mapa + tab_sufix + tab_subname
+
+        objs, values = self.displ.get_areas(opts)
+        self.rtab.new_map(map_out, 1, tab_sufix, objs, values, tab_subname)
+
+    @time_func
+    def terr_generate(self, dem_map):
+        """ Return
+        """
+        self.terr = Terr.Terrain(dem_map)
+
+    @time_func
+    def trans_generate(self):
+        """ Return
+        """
+        tabla = self.rtab.tables['_Trans']
+        self.trans = Trans.Trans(self.polygon, tabla, self.plant, self.vert,
+                                 self.terr)
+
+    def trans_write_pks(self, startend, opts):
+        """ Return
+        """
+        map_out = self.mapa + Tables.OUT_TABLES_NAMES['__Pks']
+
+        objs, values = self.trans.generate_pks(startend[0], startend[1],
+                                               opts[0], opts[1], opts[2],
+                                               opts[3])
+        self.rtab.new_map(map_out, 1, '__Pks', objs, values)
+
+    def trans_write(self):
+        """ Return
+        """
+        map_out = self.mapa + Tables.OUT_TABLES_NAMES['__Trans']
+
+        objs, values = self.trans.get_trans()
+        self.rtab.new_map(map_out, 1, '__Trans', objs, values)
+
+        objs, values = self.trans.get_pnts_trans(self.displ)
+        self.rtab.new_map(map_out, 2, '__Trans_PC', objs, values)
+
+        objs, values = self.trans.get_pnts_trans_terr(self.displ, self.taludes,
+                                                      self.terr)
+        self.rtab.new_map(map_out, 3, '__Trans_PT', objs, values)
+
+    @time_func
+    def taludes_generate(self):
+        """ Return
+        """
+        tabla = self.rtab.tables['_Terr']
+        self.taludes = Terr.Taludes(self.polygon, tabla, self.terr)
+
+    def taludes_write(self):
+        """ Return
+        """
+        map_out = self.mapa + Tables.OUT_TABLES_NAMES['__Slopes']
+
+        objs, values = self.taludes.get_lines()
+        self.rtab.new_map(map_out, 1, '__Slopes', objs, values)
+
+    def taludes_areas_write(self):
+        """ Return
+        """
+        map_out = self.mapa + Tables.OUT_TABLES_NAMES['__Slopes_Areas']
+
+        objs, values = self.taludes.get_areas(self.displ)
+        self.rtab.new_map(map_out, 1, '__Slopes_Areas', objs, values)
+
+    @time_func
+    def long_profile_generate(self, options, scale, offset):
+        """Return
+        """
+        self.long_prof = Profile.LongProfile(options, scale, offset)
+
+    def long_profile_write(self):
+        """ Return
+        """
+        map_out = self.mapa + Tables.OUT_TABLES_NAMES['__LongProfile']
+
+#        self.terr.set_pnts_terr(puntos)
+        self.long_prof.set_maxmin(self.plant.roadline)
+
+        objs, vals = self.long_prof.get_ras_terr(self.plant.roadline,
+                                                 self.vert)
+        self.rtab.new_map(map_out, 1, '__LongProfile', objs, vals)
+
+        objs, vals = self.long_prof.charact_pnts(self.vert)
+        self.rtab.new_map(map_out, 2, '__LProfile_PC', objs, vals)
+
+        objs, vals = self.long_prof.get_axes(self.plant.roadline)
+        self.rtab.new_map(map_out, 3, '__LProfile_Axis', objs, vals)
+
+        objs, vals = self.long_prof.get_axes_marks(self.plant.roadline)
+        self.rtab.new_map(map_out, 4, '__LProfile_Ticks', objs, vals)
+
+    @time_func
+    def trans_profiles_generate(self, options1, options2, scale, offset):
+        """Return
+        """
+        self.trans_prof = Profile.TransProfiles(options1, options2, scale)
+
+    def trans_profiles_write(self):
+        """ Return
+        """
+        map_out = self.mapa + Tables.OUT_TABLES_NAMES['__TransProfiles']
+
+        if len(self.trans) == 0:
+            return None
+
+        self.trans_prof.set_maxmin(self.trans, self.terr)
+        self.trans_prof.set_centers()
+
+        objs, vals = self.trans_prof.get_ras_terr()
+        self.rtab.new_map(map_out, 1, '__TransProfiles', objs, vals)
+
+        objs, vals = self.trans_prof.ras_pnts()
+        self.rtab.new_map(map_out, 2, '__TProfile_PC', objs, vals)
+
+        objs, vals = self.trans_prof.get_axes()
+        self.rtab.new_map(map_out, 3, '__TProfile_Axis', objs, vals)
+
+        objs, vals = self.trans_prof.get_axes_marks()
+        self.rtab.new_map(map_out, 4, '__TProfile_Ticks', objs, vals)
+
+    @time_func
+    def marks_generate(self, tab_subname=''):
+        """ Return
+        """
+        tabla = self.rtab.tables['_Marks' + tab_subname]
+        self.marks = Marks.Marks(self.polygon, tabla, self.plant, self.vert)
+
+    def marks_write(self, tab_subname=''):
+        """ Return
+        """
+        tab_sufix = '__Marks'
+        map_out = self.mapa + Tables.OUT_TABLES_NAMES['__Marks'] + tab_subname
+
+        objs, values = self.marks.get_pnts()
+        self.rtab.new_map(map_out, 1, tab_sufix, objs, values, tab_subname)
+
+    def tri_write(self):
+        """ Return
+        """
+        map_out = self.mapa + Tables.OUT_TABLES_NAMES['__Topo']
+
+        objs, values = self.plant.roadline.get_pnts_attrs()
+
+        for displ in self.displ.displines:
+            objs2, values2 = displ.roadline.get_pnts_attrs()
+            for i, obj in enumerate(objs2):
+                values2[i][0] = obj.acum_pk
+
+            objs.extend(objs2)
+            values.extend(values2)
+
+        for r_line in self.taludes.talud_left.roadlines:
+            objs2, values2 = r_line.get_pnts_attrs()
+            objs.extend(objs2)
+            values.extend(values2)
+
+        for r_line in self.taludes.talud_right.roadlines:
+            objs2, values2 = r_line.get_pnts_attrs()
+            objs.extend(objs2)
+            values.extend(values2)
+
+        self.rtab.new_map(map_out, 1, '__Topo', objs, values)
+
+        objs, values = self.plant.roadline.get_line_attrs()
+
+        objs2, values2 = self.displ.get_lines()
+        objs.extend(objs2)
+        values.extend(values2)
+
+        objs2, values2 = self.taludes.get_lines()
+        objs.extend(objs2)
+        values.extend(values2)
+
+        self.rtab.new_map(map_out, 2, '__Topo_BreakLines', objs, values)
+
+        map_out = self.mapa + Tables.OUT_TABLES_NAMES['__Topo_Hull']
+        objs, values = self.taludes.get_hull(self.displ)
+        self.rtab.new_map(map_out, 1, '__Topo_Hull', objs, values)
+
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()


Property changes on: grass-addons/grass7/vector/v.civil/road_road.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: grass-addons/grass7/vector/v.civil/road_tables.py
===================================================================
--- grass-addons/grass7/vector/v.civil/road_tables.py	                        (rev 0)
+++ grass-addons/grass7/vector/v.civil/road_tables.py	2016-07-01 22:30:22 UTC (rev 68831)
@@ -0,0 +1,933 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Thu Oct  2 18:24:22 2014
+
+ at author: meskal
+"""
+
+# from grass.pygrass.vector.table import Link
+import time
+import grass.script as grass
+from grass.pygrass.vector.geometry import Point
+from grass.pygrass.vector import sql
+from grass.pygrass.vector.table import Link
+from grass.pygrass.vector import VectorTopo
+
+# from grass.pygrass.vector.geometry import Line
+
+
+def time_func(funcion_f):
+    """Return
+    """
+    def funcion_r(*arg):
+        """Return
+        """
+        t_1 = time.clock()
+        res = funcion_f(*arg)
+        t_2 = time.clock()
+        print('%s tarda %0.5f ms' % (funcion_f.__name__, (t_2 - t_1) * 1000.0))
+        return res
+    return funcion_r
+
+# =============================================
+# PLANT
+# =============================================
+
+# TABLES_NAMES
+TABLES_NAMES = ('first', '_Plan', '_Vert', '_Displ', '_Terr', '_Trans',
+                '_Marks')
+
+# OUT_TABLES_NAMES
+OUT_TABLES_NAMES = {'__Plant':           '__Plant',
+                    '__Plant_PC':        '__Plant_PC',
+                    '__Plant_C':         '__Plant_C',
+                    '__Vertical':        '__Vertical',
+                    '__Vertical_PC':     '__Vertical_PC',
+                    '__Displaced':       '__Displaced',
+                    '__Displaced_PC':    '__Displaced_PC',
+                    '__Displaced_Areas': '__Displaced_Areas',
+                    '__Pks':             '__Pks',
+                    '__Trans':           '__Trans',
+                    '__Trans_PC':        '__Trans_PC',
+                    '__Trans_PT':        '__Trans_PT',
+                    '__Slopes':          '__Slopes',
+                    '__Marks':           '__Marks',
+                    '__Slopes_Areas':    '__Slopes_Areas',
+                    '__LongProfile':     '__LongProfile',
+                    '__LProfile_PC':     '__LProfile_PC',
+                    '__LProfile_Axis':   '__LProfile_Axis',
+                    '__LProfile_Ticks':  '__LProfile_Ticks',
+                    '__TransProfiles':   '__TransProfiles',
+                    '__TProfile_PC':     '__TProfile_PC',
+                    '__TProfile_Axis':   '__TProfile_Axis',
+                    '__TProfile_Ticks':  '__TProfile_Ticks',
+                    '__Topo':             '__Topo',
+                    '__Topo_BreakLines':  '__Topo_BreakLines',
+                    '__Topo_Hull':        '__Topo_Hull'}
+
+# TABLES
+TABLES = {
+
+    'first': [(u'cat', u'INTEGER PRIMARY KEY'),
+              (u'name', u'TEXT')],
+
+    '_Plan': [(u'cat2', u'INTEGER PRIMARY KEY'),
+              (u'pk_eje', u'DOUBLE PRECISION'),
+              (u'radio', u'DOUBLE PRECISION'),
+              (u'a_in', u'DOUBLE PRECISION'),
+              (u'a_out', u'DOUBLE PRECISION'),
+              (u'widening', u'DOUBLE PRECISION'),
+              (u'superelev', u'TEXT'),
+              (u'dc_', u'DOUBLE PRECISION'),
+              (u'lr_', u'DOUBLE PRECISION')],
+
+    '_Vert': [(u'cat3', u'INTEGER PRIMARY KEY'),
+              (u'pk', u'DOUBLE PRECISION'),
+              (u'elev', u'DOUBLE PRECISION'),
+              (u'kv', u'DOUBLE PRECISION'),
+              (u'l', u'DOUBLE PRECISION'),
+              (u'b', u'DOUBLE PRECISION')],
+
+    '_Displ': [(u'cat4', u'INTEGER PRIMARY KEY'),
+               (u'pk', u'DOUBLE PRECISION'),
+               (u'sec_left', u'TEXT'),
+               (u'sec_right', u'TEXT'),
+               (u'type_left', u'TEXT'),
+               (u'type_right', u'TEXT')],
+
+    '_Terr': [(u'cat5', u'INTEGER PRIMARY KEY'),
+              (u'pk', u'DOUBLE PRECISION'),
+              (u'cut_left', u'DOUBLE PRECISION'),
+              (u'cut_right', u'DOUBLE PRECISION'),
+              (u'fill_left', u'DOUBLE PRECISION'),
+              (u'fill_right', u'DOUBLE PRECISION'),
+              (u'height', u'DOUBLE PRECISION'),
+              (u'leng', u'DOUBLE PRECISION')],
+
+    '_Trans': [(u'cat6', u'INTEGER PRIMARY KEY'),
+               (u'pk', u'DOUBLE PRECISION'),
+               (u'dist_left', u'DOUBLE PRECISION'),
+               (u'dist_right', u'DOUBLE PRECISION'),
+               (u'npk', u'DOUBLE PRECISION')],
+
+    '_Marks': [(u'cat7', u'INTEGER PRIMARY KEY'),
+               (u'pk', u'DOUBLE PRECISION'),
+               (u'dist', u'TEXT'),
+               (u'elev', u'TEXT'),
+               (u'azi', u'TEXT'),
+               (u'name', u'TEXT'),
+               (u'cod', u'TEXT')]
+}
+
+
+OUT_TABLES = {
+    # Plant
+    '__Plant': [(u'cat', u'INTEGER PRIMARY KEY'),
+                (u'pk', u'TEXT'),
+                (u'type', u'TEXT'),
+                (u'long', u'DOUBLE PRECISION'),
+                (u'param', u'TEXT'),
+                (u'GRASSRGB', u'TEXT')],
+
+    '__Plant_PC': [(u'cat2', u'INTEGER PRIMARY KEY'),
+                   (u'pk', u'TEXT'),
+                   (u'azimut', u'DOUBLE PRECISION'),
+                   (u'type', u'TEXT'),
+                   (u'param', u'TEXT')],
+
+    '__Plant_C': [(u'cat3', u'INTEGER PRIMARY KEY'),
+                  (u'param', u'TEXT')],
+
+    # Vertical
+    '__Vertical': [(u'cat', u'INTEGER PRIMARY KEY'),
+                   (u'pk', u'TEXT'),
+                   (u'type', u'TEXT'),
+                   (u'long', u'DOUBLE PRECISION'),
+                   (u'param', u'TEXT'),
+                   (u'GRASSRGB', u'TEXT')],
+
+    '__Vertical_PC': [(u'cat2', u'INTEGER PRIMARY KEY'),
+                      (u'pk', u'TEXT'),
+                      (u'type', u'TEXT'),
+                      (u'param', u'TEXT')],
+
+    # Displaced
+    '__Displaced': [(u'cat', u'INTEGER PRIMARY KEY'),
+                    (u'name', u'TEXT'),
+                    (u'long', u'DOUBLE PRECISION'),
+                    (u'type', u'TEXT'),
+                    (u'param', u'DOUBLE PRECISIO'),
+                    (u'GRASSRGB', u'TEXT')],
+
+    '__Displaced_PC': [(u'cat2', u'INTEGER PRIMARY KEY'),
+                       (u'pk', u'TEXT'),
+                       (u'azimut', u'DOUBLE PRECISION'),
+                       (u'type', u'TEXT'),
+                       (u'param', u'TEXT'),
+                       (u'displ', u'TEXT')],
+
+    '__Displaced_Areas': [(u'cat', u'INTEGER PRIMARY KEY'),
+                          (u'num', u'TEXT')],
+    # Trans
+    '__Pks': [(u'cat', u'INTEGER PRIMARY KEY'),
+              (u'pk', u'TEXT'),
+              (u'azimut', u'DOUBLE PRECISION'),
+              (u'type', u'TEXT'),
+              (u'GRASSRGB', u'TEXT')],
+
+    '__Trans': [(u'cat', u'INTEGER PRIMARY KEY'),
+                (u'pk', u'TEXT'),
+                (u'azimut', u'DOUBLE PRECISION'),
+                (u'type', u'TEXT'),
+                (u'dist_left', u'DOUBLE PRECISION'),
+                (u'dist_right', u'DOUBLE PRECISION'),
+                (u'GRASSRGB', u'TEXT')],
+
+
+    '__Trans_PC': [(u'cat2', u'INTEGER PRIMARY KEY'),
+                   (u'pk', u'TEXT'),
+                   (u'azimut', u'DOUBLE PRECISION'),
+                   (u'trans', u'TEXT'),
+                   (u'param', u'TEXT'),
+                   (u'type', u'TEXT')],
+
+    '__Trans_PT': [(u'cat3', u'INTEGER PRIMARY KEY'),
+                   (u'pk', u'TEXT'),
+                   (u'azimut', u'DOUBLE PRECISION'),
+                   (u'trans', u'TEXT'),
+                   (u'param', u'TEXT'),
+                   (u'type', u'TEXT')],
+
+    # Taludes
+    '__Slopes': [(u'cat', u'INTEGER PRIMARY KEY'),
+                 (u'name', u'TEXT'),
+                 (u'long', u'DOUBLE PRECISION'),
+                 (u'type', u'TEXT'),
+                 (u'param', u'DOUBLE PRECISION'),
+                 (u'GRASSRGB', u'TEXT')],
+
+    # Marks
+    '__Marks': [(u'cat', u'INTEGER PRIMARY KEY'),
+                (u'pk', u'TEXT'),
+                (u'azimut', u'DOUBLE PRECISION'),
+                (u'name', u'TEXT'),
+                (u'cod', u'TEXT'),
+                (u'dist', u'DOUBLE PRECISION'),
+                (u'elev', u'DOUBLE PRECISION')],
+
+    # Taludes
+    '__Slopes_Areas': [(u'cat', u'INTEGER PRIMARY KEY'),
+                       (u'name', u'TEXT'),
+                       (u'long', u'DOUBLE PRECISION'),
+                       (u'type', u'TEXT'),
+                       (u'param', u'TEXT'),
+                       (u'GRASSRGB', u'TEXT')],
+
+    # LongProfile
+    '__LongProfile': [(u'cat', u'INTEGER PRIMARY KEY'),
+                      (u'pk', u'TEXT'),
+                      (u'type', u'TEXT'),
+                      (u'long', u'DOUBLE PRECISION'),
+                      (u'param', u'TEXT'),
+                      (u'GRASSRGB', u'TEXT')],
+
+    '__LProfile_PC': [(u'cat2', u'INTEGER PRIMARY KEY'),
+                      (u'pk', u'TEXT'),
+                      (u'type', u'TEXT'),
+                      (u'param', u'TEXT')],
+
+    '__LProfile_Axis': [(u'cat3', u'INTEGER PRIMARY KEY'),
+                        (u'name', u'TEXT'),
+                        (u'type', u'TEXT'),
+                        (u'param', u'TEXT')],
+
+    '__LProfile_Ticks': [(u'cat4', u'INTEGER PRIMARY KEY'),
+                         (u'param', u'TEXT')],
+
+    # TransProfiles
+    '__TransProfiles': [(u'cat', u'INTEGER PRIMARY KEY'),
+                        (u'pk', u'TEXT'),
+                        (u'type', u'TEXT'),
+                        (u'long', u'DOUBLE PRECISION'),
+                        (u'param', u'TEXT'),
+                        (u'GRASSRGB', u'TEXT')],
+
+    '__TProfile_PC': [(u'cat2', u'INTEGER PRIMARY KEY'),
+                      (u'dist', u'TEXT'),
+                      (u'elev', u'TEXT'),
+                      (u'rel_elev', u'TEXT')],
+
+    '__TProfile_Axis': [(u'cat3', u'INTEGER PRIMARY KEY'),
+                        (u'name', u'TEXT'),
+                        (u'type', u'TEXT'),
+                        (u'param', u'TEXT')],
+
+    '__TProfile_Ticks': [(u'cat4', u'INTEGER PRIMARY KEY'),
+                         (u'param', u'TEXT')],
+
+    # Tri
+    '__Topo': [(u'cat', u'INTEGER PRIMARY KEY'),
+               (u'pk', u'DOUBLE PRECISION'),
+               (u'name', u'TEXT'),
+               (u'azi', u'DOUBLE PRECISION'),
+               (u'p_type', u'TEXT'),
+               (u'align', u'INTEGER'),
+               (u'vparam', u'DOUBLE PRECISION'),
+               (u'v_type', u'TEXT'),
+               (u'terr', u'DOUBLE PRECISION'),
+               (u't_type', u'TEXT'),
+               (u'dist_d', u'DOUBLE PRECISION'),
+               (u'x', u'DOUBLE PRECISION'),
+               (u'y', u'DOUBLE PRECISION'),
+               (u'z', u'DOUBLE PRECISION'),
+               (u'action', u'TEXT')],
+
+    '__Topo_BreakLines': [(u'cat2', u'INTEGER PRIMARY KEY'),
+                          (u'name', u'TEXT'),
+                          (u'long', u'DOUBLE PRECISION'),
+                          (u'type', u'TEXT'),
+                          (u'param', u'DOUBLE PRECISION'),
+                          (u'GRASSRGB', u'TEXT')],
+
+    '__Topo_Hull': [(u'cat', u'INTEGER PRIMARY KEY'),
+                    (u'name', u'TEXT'),
+                    (u'long', u'DOUBLE PRECISION')]
+}
+
+INIT_VALUES = {
+
+    'first': ['name_road'],
+    '_Plan': [0, 0, 0, 0, 0, '', 0, 0],
+    '_Vert': [0, 0, 0, 0, 0],
+    '_Displ': [0, '', '', '', ''],
+    '_Trans': [0, 0, 0, 0],
+    '_Marks': [0, '', '', '', '', ''],
+    '_Terr': [0, 1, 1, 1, 1, 0, 0]
+}
+
+
+class RoadTable(object):
+    """ Return
+    """
+    def __init__(self, polygon, polyline, layer, map_name, tab_sufix):
+        """ Return
+        """
+        self.polygon = polygon
+        self.tab_name = map_name
+        self.name = tab_sufix
+#        self.tab_sufix2 = tab_sufix2
+
+        self.polyline = polyline
+        self.layer = layer
+        self.cols_names = None
+        self.rows = None
+
+        self._init_table()
+
+    def __getitem__(self, index):
+        return dict(zip(self.cols_names, self.rows[index]))
+
+    def __setitem__(self, index, name, value):
+        ind = self.cols_names.index(name)
+        self.rows[index][ind] = value
+
+    def __delitem__(self, index):
+        del self.rows[index]
+
+    def __len__(self):
+        return len(self.rows)
+
+#    @time_func
+    def _init_table(self):
+        """Return
+        """
+        link = self.polygon.dblinks.by_name(self.tab_name)
+
+        if link is None:
+            self.polygon.open('rw')
+            print('creating table')
+            self._create_table()
+            self.polygon.close()
+
+            self.polygon.open('rw', self.layer, with_z=True)
+            if self.name == '_Plan':
+                self._set_default(map_plant=True)
+            else:
+                self._set_default()
+            self.polygon.close()
+
+        self.polygon.open('r')
+        link = self.polygon.dblinks.by_name(self.tab_name)
+        self.layer = link.layer
+        self.cols_names = link.table().columns.names()
+        self.polygon.close()
+
+        self._check_columns()
+
+        self.polygon.open('r')
+        tabla_sql = "SELECT * FROM {name};".format(name=self.tab_name)
+        self.rows = link.table().execute(tabla_sql).fetchall()
+        self.rows = [list(row) for row in self.rows]
+        self.polygon.close()
+
+    def _create_table(self):
+        """Return
+        """
+        link = Link(self.layer, self.tab_name, self.tab_name,
+                    'cat' + str(self.layer))
+        self.polygon.dblinks.add(link)
+        table = link.table()
+
+        tab_sufix = self.name
+        if self.name == '':
+            tab_sufix = 'first'
+        TABLES[tab_sufix][0] = (u'cat' + str(self.layer),
+                                u'INTEGER PRIMARY KEY')
+        if not table.exist():
+            table.create(TABLES[tab_sufix])
+            table.conn.commit()
+
+    def _set_default(self, map_plant=False):
+        """Return
+        """
+        tab_sufix = self.name
+        if self.name == '':
+            tab_sufix = 'first'
+            values = INIT_VALUES[tab_sufix]
+            self.polygon.write(self.polyline[0], cat=1, attrs=values)
+            self.polygon.table.conn.commit()
+            self.polygon._cats = []
+            return 0
+        values = INIT_VALUES[tab_sufix]
+        values[0] = 0
+        dist2 = self.polyline[0].distance(self.polyline[1])
+        if map_plant:
+            values[-1] = dist2
+
+        self.polygon.write(self.polyline[0], cat=1, attrs=values)
+        dist = dist2
+
+        ult_i = 1
+        for i in range(1, len(self.polyline[:-1])):
+
+            dist2 = self.polyline[i].distance(self.polyline[i + 1])
+            if map_plant:
+                values[-1] = dist2
+                values[0] = dist
+                ult_i = i + 1
+                self.polygon.write(self.polyline[i], i + 1, values)
+            dist += dist2
+
+        if map_plant:
+            values[-1] = 0
+        values[0] = dist
+
+        self.polygon.write(self.polyline[-1], ult_i + 1, values)
+        self.polygon.table.conn.commit()
+        self.polygon._cats = []
+
+    def get_column(self, name):
+        """Return
+        """
+        index = self.cols_names.index(name)
+        return [row[index] for row in self.rows]
+
+    def _check_columns(self):
+        """Return
+        """
+        cols_out = []
+        tab_sufix = self.name
+        if self.name == '':
+            tab_sufix = 'first'
+        for col in TABLES[tab_sufix][1:]:
+            if col[0] not in self.cols_names:
+                cols_out.append(col)
+        if cols_out != []:
+            grass.warning("adding columns " + ','.join([p[0] for p in
+                                                        cols_out]))
+            self._add_columns(cols_out)
+
+    def _add_columns(self, columns):
+        """Return
+        """
+        self.polygon.open('rw')
+
+        table = self.polygon.dblinks.by_name(self.tab_name).table()
+
+        for col in columns:
+            table.execute(sql.ADD_COL.format(tname=self.tab_name, cname=col[0],
+                                             ctype=col[1]))
+        table.conn.commit()
+        self.polygon.close()
+
+#    @time_func
+    def rewrite_obj(self, obj, attrs):
+        """Return
+        """
+        self.polygon.open('rw', self.layer, with_z=True)
+
+        if isinstance(obj, Point):
+            type_obj = 'points'
+        else:
+            type_obj = 'lines'
+
+        obj_org = self.polygon.cat(attrs[0], type_obj, self.layer)[0]
+
+        self.polygon.rewrite(obj_org, obj, attrs[1:])
+        self.polygon.table.conn.commit()
+        self.polygon.close()
+
+    def rewrite_new(self, obj, attrs, cat_ind):
+        """Return
+        """
+        self.polygon.open('rw', self.layer, with_z=True)
+
+        tabla_sql = "DELETE FROM " + self.tab_name + " WHERE cat" + \
+                    str(self.layer) + "=" + str(attrs[0]) + ";"
+        self.polygon.table.execute(tabla_sql)
+
+        if isinstance(obj, Point):
+            type_obj = 'points'
+        else:
+            type_obj = 'lines'
+
+        obj_org = self.polygon.cat(attrs[0], type_obj, self.layer)
+
+        if obj_org:
+            obj_org = obj_org[0]
+            self.polygon.delete(obj_org.id)
+
+        self.polygon.write(obj, cat_ind, attrs[1:])
+
+        self.polygon.table.conn.commit()
+        self.polygon.close()
+
+    def _execute_update(self):
+        """Return
+        """
+        self.polygon.open('r')
+        tabla = self.polygon.dblinks.by_name(self.tab_name).table()
+
+        for row in self.rows:
+            vals = ','.join(["%s='%s'" % (k, v) for k, v in
+                             zip(self.cols_names[1:], row[1:])])
+            cond = "%s=%s" % (self.cols_names[0], row[0])
+
+            sql1 = "UPDATE {tname} SET {values} WHERE {condition};"
+            tabla_sql = sql1.format(tname=self.tab_name, values=vals,
+                                    condition=cond)
+            tabla.execute(tabla_sql)
+        tabla.conn.commit()
+        self.polygon.close()
+
+    def update_plan_dists(self, plant):
+        """Return
+        """
+        num = 0
+        for i in range(0, len(plant.straight_curve_lengs[:-1]), 2):
+            index = self.cols_names.index('dc_')
+            self.rows[num][index] = plant.straight_curve_lengs[i]
+            index = self.cols_names.index('lr_')
+            self.rows[num][index] = plant.straight_curve_lengs[i + 1]
+            num += 1
+        self._execute_update()
+
+#    def write_obj(self, objs, values):
+#        """Return
+#        """
+#        self.polygon.open('rw', self.layer, with_z=True,
+#                          tab_name=self.tab_name, tab_cols=self.cols_names)
+#        for obj, val in (objs, values):
+#            self.polygon.write(obj, val)
+#        self.polygon.table.conn.commit()
+#        self.polygon.close()
+
+    def displ_add_del_col(self, num_col, side, values, add):
+        """Return
+        """
+        num_col = int(num_col)
+        values = values.split(';')
+        if side == 'left':
+            name_sec = 'sec_left'
+            type_sec = 'type_left'
+        elif side == 'right':
+            name_sec = 'sec_right'
+            type_sec = 'type_right'
+
+        self._displ_check_type_col(name_sec, type_sec)
+
+        ind = self.cols_names.index(name_sec)
+        ind2 = self.cols_names.index(type_sec)
+        self.rows[0][ind] = self._displ_add_del_sec(self[0][name_sec], num_col,
+                                                    values[0], side, add)
+        self.rows[0][ind2] = self._displ_add_del_sec(self[0][type_sec],
+                                                     num_col, 'l', side, add)
+
+        self.rows[-1][ind] = self._displ_add_del_sec(self[-1][name_sec],
+                                                     num_col, values[1], side,
+                                                     add)
+        self.rows[-1][ind2] = self._displ_add_del_sec(self[-1][type_sec],
+                                                      num_col, 'l', side, add)
+        for i in range(1, len(self.rows) - 1):
+            self.rows[i][ind] = self._displ_add_del_sec(self[i][name_sec],
+                                                        num_col, '-1 0', side,
+                                                        add)
+            self.rows[i][ind2] = self._displ_add_del_sec(self[i][type_sec],
+                                                         num_col, 'l', side,
+                                                         add)
+        self._execute_update()
+
+    def _displ_check_type_col(self, name_sec, type_sec):
+        """Return
+        """
+        ind = self.cols_names.index(name_sec)
+        ind2 = self.cols_names.index(type_sec)
+        if self.rows[0][ind] != '':
+            if ';' in self.rows[0][ind]:
+                len_secc = len(self.rows[0][ind].split(';'))
+            else:
+                len_secc = 1
+        else:
+            return None
+
+        for i in range(len(self.rows)):
+            if self.rows[i][ind2] == '':
+                type_secc = ''
+                for _ in range(len_secc):
+                    type_secc += 'l;'
+                self.rows[i][ind2] = type_secc[:-1]
+
+    def _displ_add_del_sec(self, sec, index, values, side, add):
+        """Return
+        """
+        if sec != '':
+            if ';' in sec:
+                sec_out = sec.split(';')
+            else:
+                sec_out = [sec]
+            if index > len(sec_out):
+                index = len(sec_out)
+            if side == 'left':
+                index = len(sec_out) - index
+            if add:
+                sec_out.insert(index, values)
+                return ';'.join(sec_out)
+            else:
+                if index > len(sec_out) - 1:
+                    index = len(sec_out) - 1
+                del sec_out[index]
+                return ';'.join(sec_out)
+        else:
+            if add:
+                return values
+            else:
+                return ''
+
+    def _displ_init_vals(self):
+        """Return
+        """
+        values = INIT_VALUES[self.name]
+        if self[0]['sec_left'] != '':
+            num = '-1 0'
+            typ = 'l'
+            if ';' in self[0]['sec_left']:
+                for _ in range(len(self[0]['sec_left'].split(';')) - 1):
+                    num += ';-1 0'
+                    typ += ';l'
+            INIT_VALUES[self.name][1] = num
+            INIT_VALUES[self.name][3] = typ
+
+        if self[0]['sec_right'] != '':
+            num = '-1 0'
+            typ = 'l'
+            if ';' in self[0]['sec_right']:
+                for _ in range(len(self[0]['sec_right'].split(';')) - 1):
+                    num += ';-1 0'
+                    typ += ';l'
+            INIT_VALUES[self.name][2] = num
+            INIT_VALUES[self.name][4] = typ
+        return values
+
+    def add_row(self, list_pks, plant):
+        """Return
+        """
+        col_pks = self.get_column('pk')
+
+        list_pks2 = []
+        for npk in list_pks:
+            if float(npk) not in col_pks:
+                list_pks2.append(npk)
+
+        if list_pks2 == []:
+            return None
+
+        self.polygon.open('rw', self.layer, with_z=True,
+                          tab_name=self.tab_name)
+        if self.name == '_Displ':
+            self._displ_init_vals()
+
+        for npk in list_pks2:
+            INIT_VALUES[self.name][0] = float(npk)
+            r_pnt = plant.get_roadpoint(float(npk))
+            cat = len(self.rows) + 1
+            self.rows.append([cat] + INIT_VALUES[self.name])
+
+            self.polygon.write(r_pnt, cat, INIT_VALUES[self.name])
+        self.polygon.table.conn.commit()
+        self.polygon.close()
+
+        self.update_table(plant)
+
+    # Rewrite other tables
+    def update_table(self, plant=None):
+        """Return
+        """
+        self.rows.sort(key=lambda x: float(x[1]))
+        self.rows[0][1] = 0
+        cats = [row[0] for row in self.rows]
+
+        if plant:
+            self.rows[-1][1] = plant.length()
+            for i, row in enumerate(self.rows):
+                r_pnt = plant.get_roadpoint(row[1])
+                if row[0] > i + 1 and i + 1 not in cats:
+                    self.rewrite_new(r_pnt, row, i + 1)
+                    del cats[cats.index(row[0])]
+                # elif row[0] == i + 1:
+                else:
+                    row[0] = i + 1
+                    self.rewrite_obj(r_pnt, row)
+        else:
+            self.rows[-1][1] = self.polyline.length()
+            self.rewrite_obj(self.polyline[0], self.rows[0])
+            self.rewrite_obj(self.polyline[-1], self.rows[-1])
+
+    def update_table_plan(self):
+        """Return None
+           Polygon to table plant
+        """
+        self._plan_set_dist_accum()
+        poly_dist = [self.polyline[i].distance(self.polyline[i + 1]) for i in
+                     range(len(self.polyline) - 1)]
+
+        for i, row in enumerate(self.rows):
+
+            self.rewrite_obj(self.polyline[i], row)
+
+        if len(self.rows) < len(self.polyline):
+
+            self.polygon.open('rw', self.layer, with_z=True)
+
+            for i in range(len(self), len(self.polyline)):
+                self.rows.append(INIT_VALUES['_Plan'])
+                self.rows[i][0] = poly_dist[-1] + self.rows[i - 1][1]
+                self.polygon.write(self.polyline[i], i + 1, self.rows[i])
+
+            self.polygon.table.conn.commit()
+            self.polygon.close()
+
+    def _plan_set_dist_accum(self):
+        """Return
+        """
+        dist = 0
+        for i in range(0, len(self.rows) - 1):
+            self.rows[i][1] = dist
+            dist += self.polyline[i].distance(self.polyline[i + 1])
+        self.rows[-1][1] = dist
+
+
+# =============================================
+# PLANT
+# =============================================
+
+class RoadTables(object):
+    """ Return
+    """
+    def __init__(self, road_name, polygon=None):
+        """ Return
+        """
+        self.road_name = road_name
+        self.polygon = polygon
+
+        self.polygon.open('r')
+        self.polyline = self.polygon.cat(1, 'lines', 1)[0]
+        self.polygon.close()
+
+        self.tables = dict()
+
+        self.gen_tables()
+#        self.update_tables()
+
+    def get_tables_names(self):
+        """Return
+        """
+        names = []
+        for tab_name in TABLES_NAMES:
+            exist = 0
+            if tab_name == 'first':
+                names.insert(0, [self.road_name, '', ''])
+                continue
+            for tab in [link.table_name for link in self.polygon.dblinks]:
+
+                if tab_name in tab:
+                    names.append(tab.split(tab_name))
+                    names[-1].insert(1, tab_name)
+                    exist = 1
+            if not exist:
+                names.append([self.road_name, tab_name, ''])
+        return names
+
+    @time_func
+    def new_map(self, mapa, layer, tab_sufix, objs, values, tab_subname=''):
+        """Return
+        """
+        map_out = VectorTopo(mapa)
+        if objs == [] or objs is None:
+            return None
+
+        tab_sufix_out = OUT_TABLES_NAMES[tab_sufix]
+        tab_name = self.road_name + tab_sufix_out + tab_subname
+
+        columns = OUT_TABLES[tab_sufix]
+        if layer == 1:
+            map_out.open('w', layer=layer, with_z=True, tab_name=tab_name,
+                         tab_cols=columns)
+        else:
+            map_out.open('rw')
+            link = Link(layer, tab_name, tab_name, 'cat' + str(layer))
+            map_out.dblinks.add(link)
+            table = link.table()
+            if not table.exist():
+                table.create(columns)
+            table.conn.commit()
+            map_out.close()
+
+            map_out.open('rw', layer=layer, with_z=True)
+        for i, obj in enumerate(objs):
+            map_out.write(obj, i + 1, values[i])
+        map_out.table.conn.commit()
+        map_out.close()
+
+    @time_func
+    def gen_tables(self):
+        """Return None
+        """
+        for i, name in enumerate(self.get_tables_names()):
+            namedic = name[1] + name[2]
+            if name[1] == '':
+                namedic = 'first'
+
+            self.tables[namedic] = \
+                RoadTable(self.polygon, self.polyline, i + 1, name[0] +
+                          name[1] + name[2], name[1])
+
+    @time_func
+    def update_tables(self):
+        """Return None
+        """
+        for name, tab in self.tables.items():
+            if name == '_Plan':
+                tab.update_table_plan()
+            elif name != 'first':
+                tab.update_table()
+
+    @time_func
+    def update_tables_pnts(self, plant):
+        """Return None
+        """
+        for tab in self.tables.values():
+            if tab.name not in ['', '_Plan']:
+                tab.update_table(plant)
+
+    def add_table(self, tab_sufix, tab_subname):
+        """Return
+        """
+        if tab_sufix not in ['_Displ', '_Marks']:
+            grass.warning('Only Displ or Marks tables can be used')
+            return None
+        tab_name = self.road_name + tab_sufix + tab_subname
+        n_layer = self.polygon.dblinks.num_dblinks()
+        if tab_name in [link.table_name for link in self.polygon.dblinks]:
+            grass.warning('table exist')
+        else:
+            self.tables[tab_sufix + tab_subname] = \
+                RoadTable(self.polygon, self.polyline, n_layer + 1,
+                          tab_name, tab_sufix)
+
+    def add_row(self, list_pks, plant, tab_sufix, tab_subname):
+        """Return
+        """
+        self.tables[tab_sufix + tab_subname].add_row(list_pks, plant)
+
+    def get_tables_pks(self):
+        """Return
+        """
+        list_pks = []
+        for tab in self.tables.values():
+            if tab.name in ['_Displ', '_Terr']:
+                pks = tab.get_column('pk')[1:-1]
+                for npk in pks:
+                    if npk not in list_pks:
+                        list_pks.append(npk)
+        return list_pks
+
+    def create_backup(self, filename):
+        """Return
+        """
+        sal = 'echo "'
+        sal += 'L ' + str(len(self.polyline)) + ' 1\n'
+        for pnt in self.polyline:
+            sal += ' ' + str(pnt.x) + ' ' + str(pnt.y) + '\n'
+        sal += ' 1  1\n'
+
+        self.polygon.open('r')
+        for table in self.tables.values():
+            if table.name != '':
+                for row in table.rows:
+                    sal += 'P  1 1\n'
+                    pnt = self.polygon.cat(row[0], 'points', table.layer)[0]
+                    sal += ' ' + str(pnt.x) + ' ' + str(pnt.y) + '\n'
+                    sal += ' ' + str(table.layer) + '    ' + str(row[0]) + '\n'
+        self.polygon.close()
+
+        sal += '" | v.in.ascii -n input=- output=' + self.road_name
+        sal += ' format=standard --o \n\n'
+
+        for table in self.tables.values():
+            tab_name = table.name
+            cat = str(table.layer)
+            if tab_name == '':
+                tab_name = 'first'
+                cat = ''
+
+            cols = []
+            for key1, val1 in TABLES[tab_name][1:]:
+                if 'INTEGER' in val1:
+                    val1 = 'INT'
+                if 'TEXT' in val1:
+                    val1 = 'VARCHAR(25)'
+                cols.append((key1, val1))
+
+            sal += 'v.db.addtable map=' + self.road_name + \
+                   ' table=' + self.road_name + table.name + \
+                   ' layer=' + str(table.layer) + \
+                   ' key=cat' + cat + \
+                   ' columns="' + ','.join(["%s %s" % (key, str(val).lower())
+                                            for key, val in cols]) + '"\n'
+
+        sal += '\n' + 'echo "'
+        for table in self.tables.values():
+            for row in table.rows:
+                vals = ','.join(["%s='%s'" % (key, val) for key, val in
+                                 zip(table.cols_names[1:], row[1:])])
+                cond = "%s=%s" % (table.cols_names[0], row[0])
+                sal += 'UPDATE ' + self.road_name + table.name + \
+                       ' SET ' + vals + ' WHERE ' + cond + ';\n'
+        sal += '" | db.execute input=- \n'
+
+        with open(filename, 'w') as file:
+            file.write(sal)
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()


Property changes on: grass-addons/grass7/vector/v.civil/road_tables.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: grass-addons/grass7/vector/v.civil/road_terr.py
===================================================================
--- grass-addons/grass7/vector/v.civil/road_terr.py	                        (rev 0)
+++ grass-addons/grass7/vector/v.civil/road_terr.py	2016-07-01 22:30:22 UTC (rev 68831)
@@ -0,0 +1,382 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Thu Sep 11 00:29:15 2014
+
+ at author: meskal
+"""
+
+import math
+# import time
+
+import road_base as Base
+from grass.pygrass.raster import RasterRow
+
+from grass.pygrass.vector.geometry import Point
+from grass.pygrass.gis.region import Region
+from grass.pygrass.vector.geometry import Line
+from grass.pygrass.vector.geometry import Boundary
+from grass.pygrass.vector.geometry import Area
+
+def get_rgb(type_terr):
+    """ Return
+    """
+    if type_terr == 'Cut':
+        return '165:50:0'
+    else:
+        return '255:165:0'
+
+
+def get_side(left):
+    """ Return
+    """
+    if left:
+        return 'left'
+    else:
+        return 'right'
+
+
+# =============================================
+# PLANT
+# =============================================
+
+class Talud(object):
+    """ Return
+    """
+    def __init__(self, pks, cut, fill, left=True, terr=None):
+        """ Return
+        """
+        self.pks = pks
+        self.cut = [float(p) for p in cut]
+        self.fill = [float(p) for p in fill]
+        self.terr = terr
+
+        self.left = left
+
+        if self.left:
+            self.g90 = -math.pi / 2
+        else:
+            self.g90 = math.pi / 2
+
+        self.roadlines = []
+        self.roadline = None
+
+    def _get_cutfill_slope(self, r_pnt_d):
+        """Return
+        """
+        for i in range(len(self.pks) - 1):
+            if self.pks[i] <= r_pnt_d.npk < self.pks[i + 1]:
+
+                if r_pnt_d.z < r_pnt_d.terr:
+                    slope = self.cut
+                else:
+                    slope = self.fill
+
+                if slope[i] is not None or slope[i + 1] is not None:
+
+                    return slope[i] + ((r_pnt_d.npk - self.pks[i]) *
+                                       (slope[i + 1] - slope[i])) / \
+                                      (self.pks[i + 1] - self.pks[i])
+
+    def _funct(self, r_pnt_d, len_i, sig, azim, slope):
+        """ Return
+        """
+        x_1 = r_pnt_d.x + len_i * math.sin(azim)
+        y_1 = r_pnt_d.y + len_i * math.cos(azim)
+        z_t = self.terr.get_value(Base.Point(x_1, y_1))
+        z_1 = r_pnt_d.z + sig * len_i * slope
+        return dict(zip(['z_1', 'z_t', 'x_1', 'y_1'], [z_1, z_t, x_1, y_1]))
+
+    def get_pnt_slope(self, r_pnt, r_pnt_d):
+        """ Return
+        """
+        azim = r_pnt_d.azi + self.g90
+
+        if r_pnt_d.z > r_pnt_d.terr:  # Terraplen
+            sig = -1
+            type_t = 'Fill'
+        else:
+            sig = 1
+            type_t = 'Cut'
+
+        z_t = r_pnt_d.terr
+        z_1 = r_pnt_d.z
+
+        slop = self._get_cutfill_slope(r_pnt_d)
+        if slop is None:
+            return None
+
+        len_i = 0
+        while -sig * z_1 > -sig * z_t or len_i > 1000:
+            len_i += 1
+
+            x_1 = r_pnt_d.x + len_i * math.sin(azim)
+            y_1 = r_pnt_d.y + len_i * math.cos(azim)
+            z_t = self.terr.get_value(Base.Point(x_1, y_1))
+            z_1 = r_pnt_d.z + sig * len_i * slop
+
+        len_a = len_i - 1
+        len_b = len_i
+        len_c = (len_a + len_b) / 2.0
+
+        while (len_b - len_a) / 2.0 > 0.001:
+            eq_c = self._funct(r_pnt_d, len_c, sig, azim, slop)
+            eq_a = self._funct(r_pnt_d, len_a, sig, azim, slop)
+            if eq_c['z_1'] == eq_c['z_t']:
+                break
+            elif (eq_a['z_1'] - eq_a['z_t']) * (eq_c['z_1'] - eq_c['z_t']) < 0:
+                len_b = len_c
+            else:
+                len_a = len_c
+            len_c = (len_a + len_b) / 2.0
+
+        eq_c = self._funct(r_pnt_d, len_c, sig, azim, slop)
+        pnt = Base.RoadPoint(Point(eq_c['x_1'], eq_c['y_1'], eq_c['z_1']),
+                             r_pnt.npk, r_pnt_d.azi, '')
+        pnt.terr_type = type_t
+        pnt.dist_displ = pnt.distance(r_pnt)
+        return pnt
+
+    def get_pnts_slope(self, list_r_pnts, list_pnts_d):
+        """Return
+        """
+        list_pnts_t = []
+        for i, r_pnt_d in enumerate(list_pnts_d):
+            if r_pnt_d is not None:
+                pnt_t = self.get_pnt_slope(list_r_pnts[i], r_pnt_d)
+                list_pnts_t.append(pnt_t)
+            else:
+                list_pnts_t.append(None)
+        return list_pnts_t
+
+    def split_slope_line(self, rline):
+        """Return
+        """
+        list_pnts_t = [[]]
+        for line in rline:
+            if line is not None:
+                pnt_ant = line
+                break
+        for pnt_t in rline:
+            if pnt_t is not None:
+                if pnt_ant.terr_type != pnt_t.terr_type:
+                    list_pnts_t.append([])
+                list_pnts_t[-1].append(pnt_t)
+                pnt_ant = pnt_t
+            elif list_pnts_t[-1] != []:
+                list_pnts_t.append([])
+        if list_pnts_t[-1] == []:
+            del list_pnts_t[-1]
+        return list_pnts_t
+
+    def set_roadlines(self, roadline, roadline_d):
+        """ Return
+        """
+        self.terr.set_pnts_terr(roadline_d)
+
+        line1 = self.get_pnts_slope(roadline, roadline_d)
+        name = 'Slope_' + get_side(self.left)
+        attrs = [name, 1, get_side(self.left), 1, '0:0:0']
+        self.roadline = Base.RoadLine(line1, attrs, name)
+        lines = self.split_slope_line(line1)
+        for i, line in enumerate(lines):
+            if line != []:
+                # Name lenght type param rgb
+                name = 'Slope_' + get_side(self.left) + '_' + str(i + 1)
+                attrs = [name, -1, line[-1].terr_type, i + 1,
+                         get_rgb(line[-1].terr_type)]
+                self.roadlines.append(Base.RoadLine(line, attrs, name))
+
+
+# =============================================
+# Taludes
+# =============================================
+
+class Taludes(object):
+    """ Return
+    """
+    def __init__(self, polygon=None, tabla=None, terr=None):
+        """ Return
+        """
+        self.polygon = polygon
+        self.tabla = tabla
+        self.terr = terr
+
+        self.pks = []
+        self.cut = {'left': [], 'right': []}
+        self.fill = {'left': [], 'right': []}
+
+        self._init_talud()
+
+        self.talud_left = Talud(self.pks, self.cut['left'], self.fill['left'],
+                                left=True, terr=self.terr)
+        self.talud_right = Talud(self.pks, self.cut['right'],
+                                 self.fill['right'], left=False,
+                                 terr=self.terr)
+
+    def __repr__(self):
+        """ Return
+        """
+        return 'Taludes '
+
+    def _init_talud(self):
+        """ Return
+        """
+        for dat in self.tabla:
+
+            self.pks.append(dat['pk'])
+            self.cut['left'].append(dat['cut_left'])
+            self.cut['right'].append(dat['cut_right'])
+            self.fill['left'].append(dat['fill_left'])
+            self.fill['right'].append(dat['fill_right'])
+
+    def get_pnts(self, r_pnt, r_pnts_d):
+        """ Return
+        """
+        pto1 = None
+        pto2 = None
+        if r_pnts_d[0][-1] is not None:
+            pto1 = self.talud_left.get_pnt_slope(r_pnt, r_pnts_d[0][-1])
+        if r_pnts_d[1][-1] is not None:
+            pto2 = self.talud_right.get_pnt_slope(r_pnt, r_pnts_d[1][-1])
+        return [pto1, pto2]
+
+    def get_lines(self):
+        """ Return
+        """
+        list_lines = []
+        list_attrs = []
+        for r_line in self.talud_left.roadlines:
+            objs, values = r_line.get_line_attrs(set_leng=1)
+            list_lines.extend(objs)
+            list_attrs.extend(values)
+
+        for r_line in self.talud_right.roadlines:
+            objs, values = r_line.get_line_attrs(set_leng=1)
+            list_lines.extend(objs)
+            list_attrs.extend(values)
+
+        return list_lines, list_attrs
+
+    def set_roadlines(self, roadline, displ):
+        """ Return
+        """
+        if displ.displines == []:
+            return None, None
+
+        self.talud_left.set_roadlines(roadline,
+                                      displ.displines_left[-1].roadline)
+        self.talud_right.set_roadlines(roadline,
+                                       displ.displines_right[-1].roadline)
+
+    def get_areas(self, displ):
+        """ Return
+        """
+        areas = []
+        list_attrs = []
+
+        for r_line in self.talud_left.roadlines:
+            line2 = [displ.displines_left[-1].roadline.get_by_pk(r_pnt.npk)
+                     for r_pnt in r_line if r_pnt is not None]
+            lines = r_line.get_area(line2)
+
+            for j in range(len(lines)):
+                list_attrs.extend([r_line.attrs])
+            areas.extend(lines)
+
+        for r_line in self.talud_right.roadlines:
+            line2 = [displ.displines_right[-1].roadline.get_by_pk(r_pnt.npk)
+                     for r_pnt in r_line if r_pnt is not None]
+            lines = r_line.get_area(line2)
+
+            for j in range(len(lines)):
+                list_attrs.extend([r_line.attrs])
+            areas.extend(lines)
+
+        return areas, list_attrs
+
+    def get_hull(self, displ):
+        """ Return
+        """
+        line1 = []
+        for i, pnt_t in enumerate(self.talud_left.roadline):
+            if pnt_t is not None:
+                line1.append(pnt_t)
+            else:
+                for dline in displ.displines_left[::-1]:
+                    if dline.roadline[i] is not None:
+                        line1.append(dline.roadline[i])
+                        break
+        line2 = []
+        for i, pnt_t in enumerate(self.talud_right.roadline):
+            if pnt_t is not None:
+                line2.append(pnt_t)
+            else:
+                for dline in displ.displines_right[::-1]:
+                    if dline.roadline[i] is not None:
+                        line2.append(dline.roadline[i])
+                        break
+        line2 = line2[::-1]
+        line2.append(line1[0])
+        line1.extend(line2)
+        for i, pto in enumerate(line1):
+            line1[i].z = 0
+        line = Boundary(points=line1)
+        attrs = [['Hull', line.length()]]
+        return [line], attrs
+
+
+# =============================================
+# Terrain
+# =============================================
+
+class Terrain(object):
+    """ Return
+    """
+    def __init__(self, mapname=None):
+        """ Return
+        """
+        self.mapname = mapname
+
+        self.elev = []
+        self._init_elev()
+
+        region = Region()
+        self.xref = region.west
+        self.yref = region.north
+        self.xres = region.ewres
+        self.yres = region.nsres
+
+    def _init_elev(self):
+        """ Return
+        """
+        with RasterRow(self.mapname) as rrow:
+            for row in rrow:
+                self.elev.append([])
+                for elem in row:
+                    self.elev[-1].append(elem)
+
+    def get_value(self, point):
+        """ Return
+        """
+        pto_col = int((point.x - self.xref) / self.xres)
+        pto_row = int((self.yref - point.y) / self.yres)
+
+        return self.elev[pto_row][pto_col]
+
+    def set_pnts_terr(self, list_r_pnts):
+        """Return
+        """
+        for r_pnt in list_r_pnts:
+            if r_pnt is not None:
+                self.set_pnt_terr(r_pnt)
+            else:
+                return None
+
+    def set_pnt_terr(self, r_pnt):
+        """ Return
+        """
+        r_pnt.terr = self.get_value(r_pnt)
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()


Property changes on: grass-addons/grass7/vector/v.civil/road_terr.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: grass-addons/grass7/vector/v.civil/road_topotools.py
===================================================================
--- grass-addons/grass7/vector/v.civil/road_topotools.py	                        (rev 0)
+++ grass-addons/grass7/vector/v.civil/road_topotools.py	2016-07-01 22:30:22 UTC (rev 68831)
@@ -0,0 +1,434 @@
+#!/usr/bin/python
+
+"""
+Sample Python script to access vector data using GRASS Ctypes
+interface
+"""
+
+# import os, sys
+
+import grass.lib.gis as GrassGis
+import grass.lib.vector as GrassVect
+import time
+import os
+import sys
+import math
+import grass.script as grass
+# from grass.pygrass.gis.region import Region
+
+from grass.pygrass.vector import VectorTopo
+from grass.pygrass.vector.geometry import Point
+from grass.pygrass.vector.geometry import Line
+# from grass.pygrass.vector.geometry import Boundary
+# from grass.pygrass.vector.geometry import GEOOBJ as _GEOOBJ
+
+import road_base as Base
+
+
+def time_func(funcion_f):
+    """Return
+    """
+    def funcion_r(*arg):
+        """Return
+        """
+        t_1 = time.clock()
+        res = funcion_f(*arg)
+        t_2 = time.clock()
+        print('%s tarda %0.5f ms' % (funcion_f.__name__, (t_2 - t_1) * 1000.0))
+        return res
+    return funcion_r
+
+
+#########################################################
+class Topo(object):
+    """ Return
+    """
+    def __init__(self, name_map=''):
+        """ Return
+        """
+        self.name_map = name_map
+
+    def uppoints(self):
+        """ Return
+        """
+        name_map = self.name_map + '__Topo'
+        topo = VectorTopo(name_map)
+        topo.open('r', layer=1)
+
+        pts_org = []
+        pts_chg = []
+        attrs = []
+        for i in range(1, len(topo) + 1):
+            act = topo.read(i).attrs['action']
+            if act != '':
+                cat = topo.read(i).attrs['cat']
+                pto_org = topo.cat(cat, 'points', 1)[0]
+                pto_chg = Point(pto_org.x, pto_org.y, pto_org.z)
+                if topo.read(i).attrs['x'] is not None:
+                    pto_chg.x = float(topo.read(i).attrs['x'])
+                if topo.read(i).attrs['y'] is not None:
+                    pto_chg.y = float(topo.read(i).attrs['y'])
+                if topo.read(i).attrs['z'] is not None:
+                    pto_chg.z = float(topo.read(i).attrs['z'])
+
+                pts_org.append(pto_org)
+                pts_chg.append(pto_chg)
+                attrs.append([cat, topo.read(i).attrs['pk'],
+                              topo.read(i).attrs['name'],
+                              topo.read(i).attrs['azi'],
+                              topo.read(i).attrs['p_type'],
+                              topo.read(i).attrs['align'],
+                              topo.read(i).attrs['vparam'],
+                              topo.read(i).attrs['v_type'],
+                              topo.read(i).attrs['terr'],
+                              topo.read(i).attrs['t_type'],
+                              topo.read(i).attrs['dist_d'],
+                              pto_chg.x, pto_chg.y, pto_chg.z, ''])
+        topo.close()
+        if pts_org != []:
+            topo.open('rw', 1, with_z=True)
+            for i, pto in enumerate(pts_org):
+                topo.rewrite(pto, pts_chg[i], attrs[i][1:])
+            topo.table.conn.commit()
+            topo.close()
+
+    def pts_info(self, npk, road):
+        """ Return
+        """
+        r_pnt = road.plant.get_roadpoint(float(npk))
+        road.vert.set_elev(r_pnt)
+        road.terr.set_pnt_terr(r_pnt)
+        print('Axis point')
+        print(r_pnt.get_info())
+        r_pnts_d = road.displ.find_cutoff(r_pnt)
+
+        for side in r_pnts_d:
+            for pnt in side:
+                if pnt is not None:
+                    road.terr.set_pnt_terr(pnt)
+
+        r_pnts_t = road.taludes.get_pnts(r_pnt, r_pnts_d) or []
+        print('Slope points')
+        for pnt in r_pnts_t:
+            if pnt is not None:
+                print(pnt.get_info())
+        print('Displaced points')
+        for side in r_pnts_d:
+            for pnt in side:
+                if pnt is not None:
+                    print(pnt.get_info())
+
+    def roundabout(self, radio, radio2, azimut, center):
+        """ Return
+        """
+        center = [float(p) for p in center.split(',')]
+        pto_c = Base.RoadPoint(Point(center[0], center[1], 0))
+        radio = float(radio)
+        radio2 = float(radio2)
+        azi = float(azimut)
+
+        pto_1 = pto_c.project(radio2, azi)
+        pto_2 = pto_1.project(radio, azi + math.pi / 2)
+        pto_3 = pto_2.project(radio2, azi + math.pi)
+        pto_4 = pto_3.project(radio, azi + 3 * math.pi / 2)
+        pto_5 = pto_4.project(radio2, azi)
+        pto_6 = pto_5.project(radio, azi + math.pi / 2)
+
+        sal = ''
+        sal += "L   6  1\n"
+        for pto in [pto_1, pto_2, pto_3, pto_4, pto_5, pto_6]:
+            sal += ' ' + str(pto.x) + ' ' + str(pto.y) + ' ' + \
+                   str(pto.z) + '\n'
+        sal += "1  1\n"
+
+        grass.write_command('v.in.ascii', flags='nz',
+                            output=self.name_map, stdin=sal,
+                            input='-', format='standard', quiet=True)
+        grass.run_command('v.road', flags='r', name=self.name_map)
+
+        sal = ""
+        for i in range(1, 5):
+            sal += "UPDATE " + self.name_map + "_Plan SET "
+            sal += "radio=" + str(radio)
+            sal += " WHERE cat2=" + str(i + 1) + " ;\n"
+        grass.write_command('db.execute', stdin=sal, input='-', quiet=True)
+
+
+#########################################################
+class Triang(object):
+    """ Return
+    """
+    def __init__(self, name_map):
+        """ Return
+        """
+        self.name_map = name_map + '__Topo'
+        self.ptosmap = self.name_map + '_pts'
+        self.breakmap = self.name_map + '_blines'
+        self.contornomap = self.name_map + '_Hull'
+
+        self.nametin = self.name_map + '_Tin'
+        self.namelines = self.name_map + '_lines'
+        self.namecurved = self.name_map + '_Curves'
+
+    def split_maps(self):
+        """ Return
+        """
+        grass.message("Spliting in points and breaklines maps")
+
+        topo = VectorTopo(self.name_map)
+        topo.open('r')
+
+        points = []
+        lines = []
+        for algo in range(1, topo.number_of("points") + 1):
+            if isinstance(topo.read(algo), Point):
+                points.append(topo.read(algo))
+            if isinstance(topo.read(algo), Line):
+                lines.append(topo.read(algo))
+        topo.close()
+
+        new1 = VectorTopo(self.ptosmap)
+        new1.open('w', with_z=True)
+        for pnt in points:
+            new1.write(pnt)
+        new1.close()
+
+        new1 = VectorTopo(self.breakmap)
+        new1.open('w', layer=1, with_z=True)
+        for line in lines:
+            new1.write(line)
+        new1.close()
+
+    def get_area_hull(self):
+        """ Return
+        """
+        grass.run_command('v.centroids', input=self.contornomap,
+                          output=self.contornomap + '_area',
+                          overwrite=True, quiet=True)
+
+    def cut_by_hull(self):
+        """ Return
+        """
+        grass.run_command('v.category', input=self.namecurved,
+                          output=self.namecurved + '_cat', option='add',
+                          overwrite=True, quiet=True)
+
+        grass.run_command('v.db.addtable', map=self.namecurved + '_cat',
+                          columns="x double,y double,z double", quiet=True)
+
+        grass.run_command('v.to.db', map=self.namecurved + '_cat',
+                          option='start', columns='x,y,z', units='meters',
+                          overwrite=True, quiet=True)
+
+        grass.run_command('v.overlay', ainput=self.namecurved + '_cat',
+                          atype='line', binput=self.contornomap + '_area',
+                          operator='and', output=self.namecurved,
+                          overwrite=True, quiet=True)
+
+#    def tin_to_raster(self):
+#        """ Return
+#        """
+#        grass.run_command('v.tin.to.raster', map=self.nametin,
+#                          output=self.name_map+"_TinDem_borrar",
+#                          overwrite=True, quiet=True)
+#
+#        grass.run_command('v.to.rast', input=self.contornomap + '_area',
+#                          output=self.contornomap + '_area', use='val',
+#                          overwrite=True, quiet=True)
+#
+#        os.system("r.mapcalc '" + self.name_map + "_TinDem" +
+#                  " = if(" + self.contornomap + '_area' + "==1" + ", " +
+#                  self.name_map + "_TinDem_borrar" + ", null())' --o --q")
+#
+#        grass.run_command('r.contour', input=self.name_map + "_TinDem",
+#                          output=self.name_map + "_TinDemCurvas",
+#                          step=1, overwrite=True, quiet=True)
+#
+#        grass.run_command('g.remove', flags='f', type='raster',
+#                          name=self.name_map + "_TinDem_borrar")
+#
+#    def nnbathy(self):
+#        """ Return
+#        """
+#        grass.run_command('v.to.rast', input=self.name_map,
+#                          output=self.name_map, use='z',
+#                          overwrite=True, quiet=True)
+#
+#        os.system('/mnt/trb/addons/r.surf.nnbathy/r.surf.nnbathy.sh input=' +
+#                  self.name_map + ' output=' + self.name_map +
+#                  "_NNbathyDem_borrar" + ' alg=l --o --q')
+#
+#        grass.run_command('v.to.rast', input=self.contornomap + '_area',
+#                          output=self.contornomap + '_area', use='val',
+#                          overwrite=True, quiet=True)
+#
+#        os.system("r.mapcalc '" + self.name_map + "_NNbathyDem" +
+#                  " = if(" + self.contornomap + '_area' + "==1" + ", " +
+#                  self.name_map + "_NNbathyDem_borrar" + ", null())' --o --q")
+#
+#        grass.run_command('r.contour', input=self.name_map + "_NNbathyDem",
+#                          output=self.name_map + "_NNbathyDemCurvas",
+#                          step=1, overwrite=True, quiet=True)
+#
+#        grass.run_command('g.remove', flags='f', type='raster',
+#                          name=self.name_map+"_NNbathyDem_borrar")
+
+    def triangle(self):
+        """ Return
+        """
+        grass.message("Triangulating tin")
+        cmd = '/mnt/trb/addons/v.triangle/v.triangle.v7 points=' + self.ptosmap
+        if self.breakmap != "":
+            cmd += ' lines=' + self.breakmap
+        cmd += ' tin=' + self.nametin + ' --o --q'
+        os.system(cmd)
+
+    def delaunay(self):
+        """ Return
+        """
+        grass.run_command('v.delaunay', input=self.name_map,
+                          output=self.nametin,
+                          overwrite=True, quiet=True)
+
+    def curved(self):
+        """ Return
+        """
+        mapset = GrassGis.G_find_vector2(self.nametin, "")
+        if not mapset:
+            sys.exit("Vector map <%s> not found" % self.nametin)
+
+        # define map structure
+        map_info = GrassGis.pointer(GrassVect.Map_info())
+
+        # define open level (level 2: topology)
+        GrassVect.Vect_set_open_level(2)
+
+        # open existing vector map
+        GrassVect.Vect_open_old(map_info, self.nametin, mapset)
+
+        print('Calculating curves')
+
+        allrectas = []
+        rectas = self.get_rectas(map_info)
+
+        for nivel in rectas:
+            for recta in nivel:
+                allrectas.append(recta)
+
+        GrassVect.Vect_close(map_info)
+
+        new = VectorTopo(self.namelines)
+        new.open('w', with_z=True)
+
+        for line in allrectas:
+            new.write(Line(line))
+        new.close()
+
+        grass.run_command('v.build.polylines', input=self.namelines,
+                          output=self.namecurved,
+                          overwrite=True, quiet=True)
+
+    @time_func
+    def get_tin_maxmin(self, map_info):
+        """ Return
+        """
+        line1 = Line()
+        num_areas = GrassVect.Vect_get_num_areas(map_info)
+        max_z = 0
+        min_z = 100000
+        for area_id in range(1, num_areas + 1):
+
+            GrassVect.Vect_get_area_points(map_info, area_id, line1.c_points)
+
+            pto1_z = line1.c_points.contents.z[0]
+            pto2_z = line1.c_points.contents.z[1]
+            pto3_z = line1.c_points.contents.z[2]
+
+            min_ptos = min(pto1_z, pto2_z, pto3_z)
+            max_ptos = max(pto1_z, pto2_z, pto3_z)
+            if min_ptos < min_z:
+                min_z = min_ptos
+            if max_ptos > max_z:
+                max_z = max_ptos
+        return [int(math.floor(min_z)), int(math.ceil(max_z))]
+
+    @time_func
+    def get_rectas(self, map_info):
+        """ Return
+        """
+        line1 = Line()
+
+        max_min = self.get_tin_maxmin(map_info)
+        rectas = [[] for p in range(max_min[0], max_min[1] + 1)]
+        ptos = [[] for p in range(max_min[0], max_min[1] + 1)]
+
+        num_areas = GrassVect.Vect_get_num_areas(map_info)
+        for area_id in range(1, num_areas + 1):
+
+            GrassVect.Vect_get_area_points(map_info, area_id, line1.c_points)
+
+            pto1_x = line1.c_points.contents.x[0]
+            pto1_y = line1.c_points.contents.y[0]
+            pto1_z = line1.c_points.contents.z[0]
+            pto2_x = line1.c_points.contents.x[1]
+            pto2_y = line1.c_points.contents.y[1]
+            pto2_z = line1.c_points.contents.z[1]
+            pto3_x = line1.c_points.contents.x[2]
+            pto3_y = line1.c_points.contents.y[2]
+            pto3_z = line1.c_points.contents.z[2]
+
+            for i, z_z in enumerate(range(max_min[0], max_min[1] + 1)):
+
+                if pto1_z < z_z and pto2_z < z_z and pto3_z < z_z:
+                    continue
+                if pto1_z > z_z and pto2_z > z_z and pto3_z > z_z:
+                    continue
+                if pto1_z == z_z and pto2_z == z_z and pto3_z == z_z:
+                    continue
+
+                pts = [[pto1_x, pto1_y, pto1_z],
+                       [pto2_x, pto2_y, pto2_z],
+                       [pto3_x, pto3_y, pto3_z]]
+                inf = [pto for pto in pts if pto[2] < z_z]
+                equal = [pto for pto in pts if pto[2] == z_z]
+                sup = [pto for pto in pts if pto[2] > z_z]
+
+                if ((len(inf) == 0 and len(sup) == 2) or
+                        (len(inf) == 2 and len(sup) == 0)):
+                    continue
+
+                if len(equal) == 2:
+                    if equal[0] != equal[1]:
+                        if equal not in ptos[i] and equal[::-1] not in ptos[i]:
+                            rectas[i].append(equal)
+                            ptos[i].append(equal)
+                    continue
+
+                if len(inf) <= len(sup):
+                    inf.extend(equal)
+                else:
+                    sup.extend(equal)
+
+                if len(inf) < len(sup):
+                    pto_a = inf[0]
+                    pto_b = sup[0]
+                    pto_c = sup[1]
+                else:
+                    pto_a = sup[0]
+                    pto_b = inf[0]
+                    pto_c = inf[1]
+
+                t_1 = (z_z - pto_a[2]) / (pto_b[2] - pto_a[2])
+                xx1 = pto_a[0] + t_1 * (pto_b[0] - pto_a[0])
+                yy1 = pto_a[1] + t_1 * (pto_b[1] - pto_a[1])
+                pto_1 = Point(xx1, yy1, z_z)
+
+                t_2 = (z_z - pto_a[2]) / (pto_c[2] - pto_a[2])
+                xx2 = pto_a[0] + t_2 * (pto_c[0] - pto_a[0])
+                yy2 = pto_a[1] + t_2 * (pto_c[1] - pto_a[1])
+                pto_2 = Point(xx2, yy2, z_z)
+
+                rectas[i].append([pto_1, pto_2])
+
+        return rectas
+####################################################

Added: grass-addons/grass7/vector/v.civil/road_trans.py
===================================================================
--- grass-addons/grass7/vector/v.civil/road_trans.py	                        (rev 0)
+++ grass-addons/grass7/vector/v.civil/road_trans.py	2016-07-01 22:30:22 UTC (rev 68831)
@@ -0,0 +1,361 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Sat Aug  2 14:20:17 2014
+
+ at author: meskal
+"""
+
+#
+# import pygrass modules
+#
+import math
+
+# from grass.pygrass.vector import VectorTopo
+import road_base as Base
+
+# from grass.pygrass.vector.geometry import Point
+from grass.pygrass.vector.geometry import Line
+# from grass.pygrass.vector.geometry import Point
+
+
+class TransLine(object):
+    """ Return
+    """
+    def __init__(self, r_pnt=None, dist_left=None, dist_right=None):
+        """ Return
+        """
+        self.r_pnt = r_pnt
+        self.dist_left = dist_left
+        self.dist_right = dist_right
+
+        self.displ_left = []
+        self.displ_right = []
+
+        self.talud_left = None
+        self.talud_right = None
+
+        self.terr_pnts = None
+
+    def __str__(self):
+        """ Return
+        """
+        return "TransLine(" + str(self.r_pnt.npk) + ")"
+
+    def __repr__(self):
+        """ Return
+        """
+        return "TransLine(" + str(self.r_pnt.npk) + ")"
+
+    def length(self):
+        """ Return
+        """
+        return self.dist_left + self.dist_right
+
+    def _get_straight(self):
+        """ Return
+        """
+        p_left = self.r_pnt.parallel(self.dist_left, -math.pi / 2)
+        p_right = self.r_pnt.parallel(self.dist_right, math.pi / 2)
+        return Base.Straight(p_left, p_right)
+
+    def get_line(self):
+        """ Return
+        """
+        p_left = self.r_pnt.parallel(self.dist_left, -math.pi / 2)
+        p_right = self.r_pnt.parallel(self.dist_right, math.pi / 2)
+        return Line([p_left, p_right])
+
+    def set_displ(self, displaced):
+        """ Return
+        """
+        self.displ_left, self.displ_right = displaced.find_cutoff(self.r_pnt)
+
+    def set_talud(self, taludes, terr):
+        """ Return
+        """
+        if self.displ_left != [] and self.displ_left[-1] is not None:
+
+            terr.set_pnt_terr(self.displ_left[-1])
+            self.talud_left = \
+                taludes.talud_left.get_pnt_slope(self.r_pnt,
+                                                 self.displ_left[-1])
+#        if self.talud_left is None:
+#            self.talud_left = Base.RoadPoint(Point(0,0,0))
+#            self.talud_left.dist_displ = 0
+#            self.talud_left.npk = -1
+
+        if self.displ_right != [] and self.displ_right[-1] is not None:
+            terr.set_pnt_terr(self.displ_right[-1])
+            self.talud_right = \
+                taludes.talud_right.get_pnt_slope(self.r_pnt,
+                                                  self.displ_right[-1])
+#        if self.talud_right is not None:
+#            self.talud_right = Base.RoadPoint(Point(0,0,0))
+#            self.talud_right.dist_displ = 0
+#            self.talud_right.npk = -1
+
+    def set_terr_pnts(self, terr):
+        """ Return
+        """
+        max_left_width = self.max_left_width()
+        straight_1 = self._get_straight()
+        self.terr_pnts = straight_1.get_roadpnts(0, -1, 1)
+        terr.set_pnts_terr(self.terr_pnts)
+
+        if self.dist_left < max_left_width:
+            rest = max_left_width - self.dist_left
+            for i, r_pnt in enumerate(self.terr_pnts):
+                self.terr_pnts[i].npk = rest + r_pnt.npk
+
+    def get_ras_pnts(self):
+        """ Return
+        """
+        max_left_width = self.max_left_width()
+        line = []
+        if self.talud_left is not None:
+
+            self.talud_left.npk = max_left_width - self.talud_left.dist_displ
+            line.append(self.talud_left)
+
+        for r_pnt in self.displ_left[::-1]:
+            if r_pnt is not None:
+                r_pnt.npk = max_left_width - r_pnt.dist_displ
+                line.append(r_pnt)
+
+        r_pnt_c = Base.RoadPoint(self.r_pnt, max_left_width, self.r_pnt.azi)
+        line.append(r_pnt_c)
+
+
+        for r_pnt in self.displ_right:
+            if r_pnt is not None:
+                r_pnt.npk = max_left_width + r_pnt.dist_displ
+                line.append(r_pnt)
+
+        if self.talud_right is not None:
+            self.talud_right.npk = max_left_width + self.talud_right.dist_displ
+            line.append(self.talud_right)
+
+        return line
+
+    def max_left_width(self):
+        """ Return
+        """
+        if self.talud_left is not None:
+            return max(self.dist_left, self.talud_left.dist_displ)
+        return self.dist_left
+
+    def max_right_width(self):
+        """ Return
+        """
+
+        if self.talud_right is not None:
+            return max(self.dist_right, self.talud_right.dist_displ)
+        return self.dist_right
+
+    def _width_terr(self):
+        """ Return
+        """
+        return self.talud_left.dist_displ + self.talud_right.dist_displ
+
+    def _max_terr(self):
+        """ Return
+        """
+        return max([r_pnt.terr for r_pnt in self.terr_pnts])
+
+    def _min_terr(self):
+        """ Return
+        """
+        return min([r_pnt.terr for r_pnt in self.terr_pnts])
+
+    def _max_height_displ(self):
+        """ Return
+        """
+        lista = self.displ_left + self.displ_right
+        if self.talud_left is not None:
+            lista += [self.talud_left]
+        if self.talud_right is not None:
+            lista += [self.talud_right]
+        return max([r_pnt.z for r_pnt in lista if r_pnt is not None])
+
+    def _min_height_displ(self):
+        """ Return
+        """
+        lista = self.displ_left + self.displ_right
+        if self.talud_left is not None:
+            lista += [self.talud_left]
+        if self.talud_right is not None:
+            lista += [self.talud_right]
+        return min([r_pnt.z for r_pnt in lista if r_pnt is not None])
+
+    def max_height(self):
+        """ Return
+        """
+        return math.ceil(max(self._max_terr(), self._max_height_displ()))
+
+    def min_height(self):
+        """ Return
+        """
+        return math.floor(min(self._min_terr(), self._min_height_displ()))
+
+    def max_width(self):
+        """ Return
+        """
+        return max(self._width_terr(), self.length())
+
+
+class Trans(object):
+    """ Return
+    """
+    def __init__(self, polygon, tabla_iter, plant, vert, terr):
+        """ Return
+        """
+        self.polygon = polygon
+        self.tabla_iter = tabla_iter
+        self.plant = plant
+        self.vert = vert
+        self.terr = terr
+
+        self.t_aligns = []
+        self.leng_accum = [0]
+
+        self._init_trans()
+
+    def __getitem__(self, index):
+        return self.t_aligns[index]
+
+    def __setitem__(self, index, value):
+        self.t_aligns[index] = value
+
+    def __delitem__(self, index):
+        del self.t_aligns[index]
+
+    def __len__(self):
+        return len(self.t_aligns)
+
+    def __str__(self):
+        """ Return
+        """
+        string = "[\n"
+        for i in self.t_aligns:
+            string += str(i)
+        string += "]"
+        return string
+
+    def __repr__(self):
+        """ Return
+        """
+        string = "[\n"
+        for i in self.t_aligns:
+            string += str(i)
+        string += "]"
+        return string
+
+    def _init_trans(self):
+        """ Return
+        """
+        dat_1 = []
+        for i, dat_2 in enumerate(self.tabla_iter):
+
+            if i >= 1:
+                if dat_1['npk'] == 0:
+                    continue
+                start = dat_1
+                end = dat_2
+
+                r_pnts = self.plant.get_roadpnts(start['pk'], end['pk'],
+                                                 start['npk'], start['npk'])
+                self.vert.set_pnts_elev(r_pnts)
+
+                if self.terr is not None:
+                    self.terr.set_pnts_terr(r_pnts)
+
+                for r_pnt in r_pnts:
+
+                    dist_left = start['dist_left'] + \
+                        ((r_pnt.npk - start['pk']) * (end['dist_left'] -
+                         start['dist_left'])) / (end['pk'] - start['pk'])
+
+                    dist_right = start['dist_right'] + \
+                        ((r_pnt.npk - start['pk']) * (end['dist_right'] -
+                         start['dist_right'])) / (end['pk'] - start['pk'])
+
+                    trans = TransLine(r_pnt, dist_left, dist_right)
+                    self.t_aligns.append(trans)
+            dat_1 = dat_2
+
+    def get_trans(self):
+        """ Return
+        """
+        list_lines = []
+        list_attrs = []
+        for t_ali in self.t_aligns:
+            list_lines.append(t_ali.get_line())
+            list_attrs.append([t_ali.r_pnt.get_pk(),
+                               t_ali.r_pnt.get_azi(),
+                               t_ali.r_pnt.p_type,
+                               round(t_ali.dist_left, 4),
+                               round(t_ali.dist_right, 4), ''])
+        return list_lines, list_attrs
+
+    def get_pnts_trans(self, displ):
+        """ Return
+        """
+        list_pnts = []
+        list_attrs = []
+        for t_ali in self.t_aligns:
+            t_ali.set_displ(displ)
+
+#            list_pnts.extend(t_ali.displ_left + t_ali.displ_right)
+            for i, r_pnt in enumerate(t_ali.displ_left + t_ali.displ_right):
+                if r_pnt is not None:
+                    list_pnts.append(r_pnt)
+                    list_attrs.append([r_pnt.get_pk(),
+                                       r_pnt.get_azi(),
+                                       t_ali.r_pnt.get_pk(),
+                                       'Dist=' +
+                                       str(round(r_pnt.dist_displ, 4)),
+                                       'Displ=' + str(i + 1)])
+
+        return list_pnts, list_attrs
+
+    def get_pnts_trans_terr(self, displ, taludes, terr):
+        """ Return
+        """
+        list_pnts = []
+        list_attrs = []
+        for t_ali in self.t_aligns:
+            t_ali.set_talud(taludes, terr)
+
+            for i, r_pnt in enumerate([t_ali.talud_left, t_ali.talud_right]):
+                if r_pnt is not None and r_pnt.npk != -1:
+
+                    list_pnts.append(r_pnt)
+                    list_attrs.append([r_pnt.get_pk(),
+                                       r_pnt.get_azi(),
+                                       t_ali.r_pnt.get_pk(),
+                                       'Dist=' +
+                                       str(round(r_pnt.dist_displ, 4)),
+                                       'Terr=' + str(i + 1)])
+        return list_pnts, list_attrs
+
+    def generate_pks(self, start, end, dpk, mpk, len_d, len_m):
+        """ Return
+        """
+        r_pnts_d = self.plant.get_roadpnts(start, end, dpk, dpk)
+        r_pnts_m = self.plant.get_roadpnts(start, end, mpk, mpk)
+
+        list_trans = []
+        list_attrs = []
+        for r_pnt in r_pnts_d:
+            if r_pnt in r_pnts_m:
+                trans = TransLine(r_pnt, len_m, len_m)
+            else:
+                trans = TransLine(r_pnt, len_d, len_d)
+            list_trans.append(trans.get_line())
+            list_attrs.append([r_pnt.get_pk(), r_pnt.get_azi(), r_pnt.p_type,
+                               ''])
+        return list_trans, list_attrs
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()


Property changes on: grass-addons/grass7/vector/v.civil/road_trans.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: grass-addons/grass7/vector/v.civil/road_vertical.py
===================================================================
--- grass-addons/grass7/vector/v.civil/road_vertical.py	                        (rev 0)
+++ grass-addons/grass7/vector/v.civil/road_vertical.py	2016-07-01 22:30:22 UTC (rev 68831)
@@ -0,0 +1,338 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Wed Jul 23 20:36:10 2014
+
+ at author: meskal
+"""
+
+#
+# import pygrass modules
+#
+import math
+
+# from grass.pygrass.vector import VectorTopo
+# import road_base as Base
+
+# from grass.pygrass.vector.geometry import Point
+from grass.pygrass.vector.geometry import Line
+
+
+class Parabola(object):
+    """ Return
+    """
+    def __init__(self, k_v=0, pnt_1=None, pnt_v=None, pnt_2=None, plant=None):
+        """ Return
+        """
+        self.k_v = k_v
+        self.pnt_1 = pnt_1
+        self.pnt_v = pnt_v
+        self.pnt_2 = pnt_2
+
+        self.slope_in = self.pnt_1.slope2(self.pnt_v)
+        self.slope_out = self.pnt_v.slope2(self.pnt_2)
+
+        self.pnt_in = pnt_v
+        self.pnt_out = pnt_v
+
+        self._init_align(plant)
+#        self.vtype = None
+        self.vert_type()
+
+    def _init_align(self, plant):
+        """ Return
+        """
+        if self.k_v != 0:
+            # B=Kv*phi**2/8
+
+            self.pnt_in = plant.get_roadpoint(self.pnt_v.npk -
+                                              (self.length() / 2))
+
+            self.pnt_in.z = self.pnt_v.z - self.slope_in * (self.length() / 2)
+
+            self.pnt_out = plant.get_roadpoint(self.pnt_v.npk +
+                                               (self.length() / 2))
+            self.pnt_out.z = self.pnt_v.z + self.slope_out * (self.length() /
+                                                              2)
+
+        self.pnt_in.v_param = self.slope_in
+        self.pnt_in.v_type = 'in'
+        self.pnt_v.v_param = self.k_v
+        self.pnt_v.v_type = 'v'
+        self.pnt_out.v_param = self.slope_out
+        self.pnt_out.v_type = 'end'
+
+    def length(self):
+        """ Return
+        """
+        phi = (self.slope_in - self.slope_out)
+        len_tan = self.k_v * phi / 2
+        return 2 * len_tan
+
+    def true_length(self):
+        """ Return
+        """
+        return (self.pnt_2.npk - self.pnt_1.npk) / math.cos(self.slope_in)
+
+    def vert_type(self):
+        """ Return
+        """
+        if self.slope_in < 0 and self.slope_out > 0:
+            return 'Concave'
+        elif self.slope_in > 0 and self.slope_out < 0:
+            return 'Convex'
+        elif self.slope_in >= 0 and self.slope_out > 0:
+            if self.slope_in < self.slope_out:
+                return 'Concave'
+            else:
+                return 'Convex'
+        elif self.slope_in < 0 and self.slope_out <= 0:
+            if self.slope_in > self.slope_out:
+                return 'Concave'
+            else:
+                return 'Convex'
+
+    def grass_rgb(self):
+        """ Return
+        """
+        if self.vert_type() == 'Concave':
+            return '0:255:0'
+        else:
+            return '0:128:0'
+
+    def is_in(self, r_pnt):
+        """ Return
+        """
+        if self.pnt_in.npk <= r_pnt.npk <= self.pnt_out.npk:
+            return True
+        else:
+            return False
+
+    def get_elev(self, r_pnt):
+        """ Return
+        """
+        r_pnt.z = self.pnt_in.z + self.slope_in * \
+            (r_pnt.npk - self.pnt_in.npk) - \
+            (1 / (2 * self.k_v)) * (r_pnt.npk - self.pnt_in.npk) ** 2
+        r_pnt.v_type = self.vert_type()
+        r_pnt.v_param = round(100 * (self.slope_in - (1 / self.k_v) *
+                              (r_pnt.npk - self.pnt_in.npk)), 4)
+
+    def get_charact(self):
+        """ Return
+        """
+        return [self.pnt_in, self.pnt_v]
+
+    def get_charact_attrs(self):
+        """ Return
+        """
+        return [[self.pnt_in.get_pk(), self.pnt_in.v_type,
+                 round(self.pnt_in.v_param, 4)],
+                [self.pnt_v.get_pk(), self.pnt_v.v_type,
+                 round(self.pnt_v.v_param, 4)]]
+
+
+class VStraight(object):
+    """ Return
+    """
+    def __init__(self, pnt_in=None, pnt_out=None):
+        """ Return
+        """
+        self.pnt_in = pnt_in
+        self.pnt_out = pnt_out
+
+        self.slope_in = self.pnt_in.slope2(self.pnt_out)
+        self.pnt_in.v_param = self.slope_in
+        self.pnt_in.v_type = 'in'
+        self.pnt_out.v_param = self.slope_in
+        self.pnt_out.v_type = 'end'
+
+    def length(self):
+        """ Return
+        """
+        return self.pnt_out.npk - self.pnt_in.npk
+
+    def true_length(self):
+        """ Return
+        """
+        return (self.pnt_out.npk - self.pnt_in.npk) / math.cos(self.slope_in)
+
+    def vert_type(self):
+        """ Return
+        """
+        if self.slope_in > 0:
+            return 'Up'
+        else:
+            return 'Down'
+
+    def grass_rgb(self):
+        """ Return
+        """
+        if self.slope_in > 0:
+            return '0:0:255'
+        else:
+            return '255:0:0'
+
+    def is_in(self, r_pnt):
+        """ Return
+        """
+        if round(self.pnt_in.npk, 4) <= round(r_pnt.npk, 4) <= \
+                round(self.pnt_out.npk, 4):
+            return True
+        else:
+            return False
+
+    def get_elev(self, r_pnt):
+        """ Return
+        """
+        r_pnt.z = self.pnt_in.z + self.slope_in * (r_pnt.npk - self.pnt_in.npk)
+        r_pnt.v_type = self.vert_type()
+        r_pnt.v_param = round(100 * self.slope_in, 4)
+
+    def get_charact(self):
+        """ Return
+        """
+        return [self.pnt_in]
+
+    def get_charact_attrs(self):
+        """ Return
+        """
+        return [[self.pnt_in.get_pk(), self.pnt_in.v_type,
+                 round(self.pnt_in.v_param, 4)]]
+
+
+# =============================================
+# Vert
+# =============================================
+
+class Vert(object):
+    """ Return
+    """
+    def __init__(self, polygon, tabla_iter, plant):
+        """ Return
+        """
+        self.polygon = polygon
+        self.tabla_iter = tabla_iter
+        self.plant = plant
+
+        self.aligns = []
+        self.leng_accum = [0]
+
+        self._init_vert()
+
+    def __str__(self):
+        """ Return
+        """
+        string = "["
+        for i in self.aligns:
+            string += str(i)
+        string += "]"
+        return string
+
+    def _init_vert(self):
+        """ Return
+        """
+        dat_1 = []
+        dat_2 = []
+        leng_tot = 0
+        for i, dat_3 in enumerate(self.tabla_iter):
+
+            if i == 1:
+                end_pnt = self.plant.get_roadpoint(dat_2['pk'])
+                end_pnt.z = dat_2['elev']
+
+                pnt_2 = self.plant.get_roadpoint(-1)
+                pnt_2.z = dat_3['elev']
+
+            if i >= 2:
+                if i == 2:
+                    end_pnt = self.plant.get_roadpoint(dat_1['pk'])
+                    end_pnt.z = dat_1['elev']
+
+                pnt_v = self.plant.get_roadpoint(dat_2['pk'])
+                pnt_v.z = dat_2['elev']
+
+                pnt_2 = self.plant.get_roadpoint(dat_3['pk'])
+
+                pnt_2.z = dat_3['elev']
+
+                parabola = Parabola(dat_2['kv'], end_pnt, pnt_v, pnt_2,
+                                    self.plant)
+
+                straight = VStraight(end_pnt, parabola.pnt_in)
+
+                self.aligns.append(straight)
+                leng_tot += straight.length()
+                self.leng_accum.append(leng_tot)
+
+                self.aligns.append(parabola)
+                leng_tot += parabola.length()
+                self.leng_accum.append(leng_tot)
+
+                end_pnt = parabola.pnt_out
+
+            dat_1 = dat_2
+            dat_2 = dat_3
+
+            if i == len(self.tabla_iter) - 1:
+
+                straight = VStraight(end_pnt, pnt_2)
+                self.aligns.append(straight)
+                leng_tot += straight.length()
+                self.leng_accum.append(leng_tot)
+
+    def set_elev(self, r_pnt):
+        """ Return
+        """
+        for ali in self.aligns:
+            if ali.is_in(r_pnt):
+                ali.get_elev(r_pnt)
+
+    def set_pnts_elev(self, list_r_pnts):
+        """ Return
+        """
+        for r_pnt in list_r_pnts:
+            self.set_elev(r_pnt)
+
+    def set_lines_elev(self, list_r_lines):
+        """ Return
+        """
+        for list_r_lines in list_r_lines:
+            self.set_pnts_elev(list_r_lines)
+
+    def get_segments_pnts(self, list_r_pnts, line=False):
+        """Return
+        """
+        r_lines = []
+        list_attrs = []
+        for ali in self.aligns:
+            pnts_align = [ali.pnt_in]
+            for r_pnt in list_r_pnts:
+                if ali.is_in(r_pnt):
+                    pnts_align.append(r_pnt)
+            pnts_align.append(ali.pnt_out)
+            list_attrs.append([ali.pnt_in.get_pk(), ali.vert_type(),
+                               round(ali.length(), 4),
+                               round(ali.slope_in, 4), ali.grass_rgb()])
+            if line:
+                r_lines.append(Line(pnts_align))
+            else:
+                r_lines.append(pnts_align)
+        return r_lines, list_attrs
+
+    def get_charact_pnts(self):
+        """ Return
+        """
+        list_pnts = []
+        list_attrs = []
+        for ali in self.aligns:
+            list_pnts.extend(ali.get_charact())
+            list_attrs.extend(ali.get_charact_attrs())
+        ali = self.aligns[-1]
+        list_pnts.append(ali.pnt_out)
+        list_attrs.append([ali.pnt_out.get_pk(), ali.pnt_out.v_type,
+                           round(ali.pnt_out.v_param, 4)])
+        return list_pnts, list_attrs
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()


Property changes on: grass-addons/grass7/vector/v.civil/road_vertical.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: grass-addons/grass7/vector/v.civil/v.road.html
===================================================================
--- grass-addons/grass7/vector/v.civil/v.road.html	                        (rev 0)
+++ grass-addons/grass7/vector/v.civil/v.road.html	2016-07-01 22:30:22 UTC (rev 68831)
@@ -0,0 +1,828 @@
+<!-- <h2>DESCRIPTION</h2> -->
+
+<em>v.civil.road</em> generates a alignment for design roads, channels, ports...
+
+
+<h2>USAGE</h2>
+
+To run the program for the first time, a map with one horizontal polygon, is
+required. 
+
+<p>
+There are three options:
+The flag <em>-r</em> for run the program,
+The flag <em>-p</em> Update solution from polygon (if you modific the polygon), 
+The flag <em>-t</em> Update solution from table plan (walk with dc_ and lr_)
+
+<p>
+The other options are described below.
+
+
+
+
+<h2>Plan</h2>
+
+<h3>plan options</h3>
+<p>
+<em>plan</em> write the horizontal alignment.
+
+<p>
+<em>pks</em> write pk marks in horizontal.
+
+<p>
+<em>displ</em> write the displaced platform lines in horizontal.
+
+<p>
+<em>marks</em> write the marks in horizontal.
+
+
+<h3>options</h3>
+
+<p>
+<em>pkopt</em> define the distance between normal marks (npk),
+distance between principal marks (mpk), longitude of normal marks and
+longitude of principal marks.
+
+<p>
+<em>areaopt</em> write the areas defined with pairs of displaced lines.
+
+
+
+
+<h2>Vertical</h2>
+
+<h3>vert options</h3>
+<p>
+<em>vert</em>  write the vertical alignment in horizontal.
+
+<p>
+<em>profile</em> write longitudinal profile map.
+
+<h3>options</h3>
+<p>
+With the option <em>LPScale</em>, the vertical scale of the longitudinal
+profile can be given.
+
+<p>
+The <em>LPopt</em> option give the longitude of marks, distance between marks
+in axis x and y, and distance between lines of the guitar.
+
+
+
+
+<h2>Cross</h2>
+
+<h3>Cross options</h3>
+<p>
+<em>cross</em>  write cross section in horizontal
+
+<p>
+<em>sections</em> write cross sections map.
+
+<h3>options</h3>
+<p>
+With the option <em>LTScale</em>, the vertical scale of the longitudinal
+profile can be given.
+
+<p>
+The <em>LTopt</em> option give the longitude of marks, distance between marks
+in axis x and y, and distance between lines of the guitar.
+
+<p>
+The <em>LTopt2</em> option give the number of rows of cross-section to display,
+distance between cross-section in axis x and y.
+
+
+
+
+
+<h2>Terrain</h2>
+
+<h3>Terr options</h3>
+<p>
+<em>slopes</em> flag write the slope soil lines calculated with the last
+displaced lines (perpendicular to the central axis).
+
+<p>
+<em>sareas</em> write the areas map with slope soil lines and the last
+displaced lines in horizontal.
+
+<p>
+<em>tri</em> write points, lines and hull area  map.
+
+
+
+<h2>Tools</h2>
+
+<p>
+The flag <em>-a</em> add a new table. Displ or Marks.
+
+<p>
+The flag <em>-i</em> insert a rows in table. List of pks for each row. 
+
+<p>
+The flag <em>-n</em> add a new displ line, ei, a new column in displ table. 
+You must give a start and end distances and height. And number of column 
+and side to insert.
+
+<p>
+The flag <em>-d</em> del a displ line, ei, a column in displ table. A number
+of column and side is required.
+
+
+<h2>Tables</h2>
+
+<p>
+We have six parts: plant, vertical, displaced, terrain, tranversal and marks.
+
+<p>
+The tables stored in the polygon map are:
+
+<h3>Layer 1:</h3>
+<p>
+Created with only cat column (if not exist), is for free use to add columns
+with information of the road.
+
+
+
+<h3>Layer 2:</h3>
+<p>
+<b>"NameRoad"_Plan</b>, for insert the parameters of the horizontal
+alignment. This layer have all vertices and nodes of the horizontal polygon.
+No more points can be added to this layer with the insert point option.
+
+<p>
+The columns are:
+
+<ul>
+    <li><b>radio</b>: radio of curve
+        <p>+ for clockwise</p>
+        <p>- for anticlockwise</p>
+    </li>
+    <li><b>a_in</b>: Parameter A of input Clothoid</li>
+    <li><b>a_out</b>: Parameter A of output Clothoid</li>
+    <li><b>widening</b>: Widening of curve (where this widening is growing
+        in the clothoid, only in mode exact)</li>
+    <li><b>superelev</b>: Parameter A of input Clothoid</li>
+    <li><b>dc_</b>: longitude of curve. For use with flag <em>-t</em></li>
+    <li><b>lr_</b>: longitude of straight. For use with flag <em>-t</em></li>
+</ul>
+
+
+
+<h3>Layer 3:</h3>
+
+<p>
+<b>"NameRoad"_Vert</b>, for insert the parameters of the vertical
+alignment.This layer are created with the first an last vertices of the
+horizontal polygon. New point can be added by the flag 'e' TableTools option,
+or with edit gui. The added points, are inserted in the central axis
+referencing by pk.
+
+<p>
+The columns are:
+
+<ul>
+    <li><b>pk</b>: kilometric point of the central axis</li>
+    <li><b>elev</b>: Elevation of the vertice of the vertical alignment</li>
+    <li><b>kv</b>: Parameter Kv of the vertical alignment</li>
+    <li><b>l</b>: Leng of parabolic curve (no yet implemented)</li>
+    <li><b>B</b>: Height of vertice of vertical polygon to the parabolic
+                curve (no yet implemented)</li>
+</ul>
+
+
+<h3>Layer 4: </h3>
+
+<b>"NameRoad"_Displ</b>, for insert the parameters of the platform.
+This layer are created with the first an last vertices of the horizontal
+polygon. New point can be added by the flag 'e' TableTools option, or with edit
+gui. The added points, are inserted in the central axis referencing by pk.
+<p>
+The columns for editing by the user are:
+
+<ul>
+    <li><b>pk</b>: kilometric point of the central axis</li>
+    <li><b>sec_left, sec_right</b>: For defining left and right platform lines
+        (distance and height to the central axis), separated by ";" </li>
+    <li><b>type_left, type_right</b>: Types of left and right lines
+        (types are: l,e,r,0). You can enter the type of multiple lines
+        separated by ";"
+        <b>l</b>: linear approximation between definition points.
+        <b>e</b>: displaced lines, mode exact.
+        <b>c</b>: ellipse between definition points.
+        <b>rR,A</b>: circle between definition points ((x-A)^2+y^2=R^2))</li>
+</ul>
+
+<p>
+Between two points, if the second input distance equal zero, the line will be
+stopped. If the second input distance equal -1, this point will not be processed
+and the next one will be considered.
+
+
+
+<h3>Layer 5: </h3>
+
+<b>"NameRoad"_Terr</b>, for insert the parameters for slopes.
+This layer are created with the first an last vertices of the horizontal
+polygon. New point can be added by the flag 'e' TableTools option, or with edit
+gui. The added points, are inserted in the central axis referencing by pk.
+<p>
+The columns for editing by the user are:
+
+<ul>
+    <li><b>cut_left</b>: Cut slope left</li>
+    <li><b>cut_right</b>: Cut slope right</li>
+    <li><b>fill_left</b>: Fill slope left</li> 
+    <li><b>fill_right</b>: Fill slope right</li>
+</ul>
+
+
+
+
+<h3>Layer 6:</h3>
+<p>
+<b>"NameRoad"_Trans</b>, for insert the parameters of transects to the central
+axis.
+This layer are created with the first an last vertices of the horizontal
+polygon. New point can be added by the flag 'e' TableTools option, or with edit gui.
+The added points, are inserted in the central axis referencing by pk.
+<p>
+The columns for editing by the user are:
+
+<ul>
+    <li><b>pk</b>: kilometric point of the central axis</li>
+    <li><b>dist_left,dist_right</b>: Distance left and right from the central
+axis</li>
+    <li><b>npk</b>: Distance between trans</li>
+</ul>
+
+
+
+
+<h3>Layer 7:</h3>
+<p>
+<b>"NameRoad"_Marks</b>, for insert the parameters of Marks.
+This layer are created with the first an last vertex of the horizontal
+polygon. New point can be added by the flag 'e' TableTools option, or with edit gui.
+The added points, are inserted in the central axis referencing by pk.
+<p>
+The columns for editing by the user are:
+
+<ul>
+    <li><b>dist</b>: distance left and right from the central axis</li>
+    <li><b>elev</b>: Elevation left and right from the central
+axis</li>
+    <li><b>azi</b>: 1 for azimuth of the point of the road or -1</li>
+    <li><b>name</b>: Name of mark</li>
+    <li><b>cod</b>: Code of mark</li>
+</ul>
+
+
+<h2>Example:</h2>
+
+<p>
+This example is done in the North Carolina data set.
+</p>
+
+<p>
+At the end of this example, there is a backup that can be executed to play with this example.
+</p>
+
+<p>
+The example start creating a closed polygon with the editor, in a created map named Circuit.
+
+<p>
+<img src="./img1.png" width="500" height="406" alt="">
+
+<p>
+After that, run the next command to get all tables in the map Circuit
+
+<pre><code>
+v.road -r name=Circuit
+</code></pre>
+
+<p>
+<img src="./img_tables1.png" width="400" height="166" alt="">
+
+
+<!-- ########################## Plant ############################## -->
+
+<h3>Plant</h3>
+<p>
+For each vertex of the polygon we define a radio and in and out clothoids. So we can write the plant and pks maps.
+
+<p>
+<img src="./img_tables2.png" width="400" height="221" alt="">
+
+<p>
+<img src="./img_a_plan.png" width="300" height="241" alt="">
+
+<pre><code>
+v.road -r name=Circuit plan=plan,pks
+</code></pre>
+
+<p>
+And we obtain the map <em>Circuit__Plant</em> and <em>Circuit__Pks</em>, and their tables.
+
+<p>
+<img src="./img2.png" width="500" height="406" alt="">
+
+<p>
+<img src="./img_tables2_2.png" width="400" height="200" alt="">
+
+<p>
+If we move some vertex of polygon we must run with the flag 'p' to update the road.
+
+<p>
+<img src="./img2_1.png" width="500" height="406" alt="">
+
+<p>
+If we change some values of columns 'dc_' (long of circle) or 'lr_' (long of straight), or fill the last line (with 'dc_' and 'lr_' too, 
+a new vertex are inserted and a new line) we must run with the flag 't' to update the road.
+
+<p>
+<img src="./img_tables2_3.png" width="400" height="200" alt="">
+
+<p>
+The distance between points of each alignments is of 1 meters by default, but this can be changed in the Interval in straights and Interval in curves options.
+
+<!-- ########################## Vertical ############################## -->
+
+<h3>Vertical</h3>
+
+At first, we have only the nodes of polygon, and if we set elev we will obtain a straight with slope. To get more
+vertices we have to add new rows to this table with <em>tabletools</em> giving the pk of the vertex.
+
+<p>
+<img src="./img_a_tooladdrow.png" width="300" height="229" alt="">
+
+<p>
+And now we have to set the elevation of those vertices and the <em>kv</em> parameter.
+
+<p>
+<img src="./img_tables3.png" width="400" height="166" alt="">
+
+<p>
+Now choose vertical option to get the vertical map in horizontal and the longitudinal profile, and give a 
+<em>DEM</em> in the terrain option.
+
+<pre><code>
+v.road -r name=Circuit vert=vert,profile dem=elev_lid792_1m
+</code></pre>
+
+<p>
+And we obtain the map <em>Circuit__Vertical</em> and <em>Circuit__LongProfile </em>, and their tables. 
+
+<p>
+<img src="./img3_2.png" width="500" height="406" alt="">
+
+
+<!-- ########################## Displaced ############################## -->
+
+<h3>Displaced</h3>
+<p>
+For first time, this table have two rows, who are the nodes of the polygon, and for that the first and the last points of the central axis.
+
+<p>
+The displaced lines are defined in sec_left,sec_right columns with a list separated with ";", starting from left to right in each side of the central axis. 
+Each displaced line is defined with distance to the central axis and height to the central axis (d,h).
+
+<p>
+The mode to calculate the displaced lines is defined in the type_left,type_right columns,for each line separated by ";".
+
+<p>
+To get more vertices we have to add new rows to this table with <em>tabletools</em> giving the pk of the vertex.
+
+<p>
+In this example we are going to define two displaced lines in the left side to the central axis and two for right side with slope 2%  to out.
+ 
+<p>
+<img src="./img_tables4_1.png" width="400" height="166" alt="">
+
+<p>
+The platform lines define, the lanes of a road, the platform limits, ... Those lines can be parallel to the central axis of a road (or not). 
+If it's so, we need to know that the parallel to a clothoid is not a clothoid. Then we have two ways to do the platform lines.
+
+<p>
+In the first way, mode exact "e", we need to calculate a new displaced central axis, e.i., a parallel to the polygon not to the central axis. 
+The new alignment or displaced line created within the new polygon have new clothoids for the transitions. 
+To run this mode, the first and the last points, of a section of the road, must have the same displaced distance.
+
+<p>
+The widening parameter of the section above, only will be calculate in this mode, because the widening growing in the clothoid, 
+then is applied only to the displaced lines calculated with clothoid.
+
+<p>
+The second way, mode lineal "l", we calculate the perpendicular displaced distance to each point of the central axis, 
+to obtain a parallel to it, where the transitions won't be clothoids. Then we can't know where are the tangents of transitions. 
+But in this mode, the displaced distance for the first and the last points don't have to be the same in a section of the road. A lineal variation will be done between those points.
+
+<p>
+For this example, the first and last are defined as lineal and the rest are in mode exact.
+
+<p>
+Into this second way, the variation don't have to be only lineal. We can define a circumference in the displaced line with the option "rR,A".
+
+<p>
+Between two points, if the second input distance equal zero, the line will be stopped. If the second input distance equal -1, this point will not be processed and the next one will be considered.
+
+<pre><code>
+v.road -r name=Circuit plan=displ 
+</code></pre>
+
+And we obtain the map Circuit__Displaced, and their tables. 
+
+<p>
+<img src="./img4.png" width="500" height="406" alt="">
+
+<p>
+With distance to the central axis and height of the lines we can obtain different forms, that we'll see in the cross sections. 
+
+<p>
+<img src="./img_a_vcivilroad_7.png" width="400" height="200" alt="">
+
+<p>
+Now we can add new lines by hand or with TableTools option. 
+
+<pre><code>
+v.road -e name=Circuit displline=add side=left ncol=3 sedist="10 -0.2; 10 -0.2"
+v.road -e name=Circuit displline=add side=right ncol=3 sedist="10 -0.2; 10 -0.2"
+</code></pre>
+
+
+<p>
+And add new points. We are going to cut the last line in pk 900 and 1700.
+
+<pre><code>
+v.road -e name=Circuit at road add=row tab_type=Displ pklist=876,900,1074,1690,1700,1811 
+</code></pre>
+
+<p>
+<img src="./img_tables4_2.png" width="400" height="166" alt="">
+
+<p>
+<img src="./img4_1.png" width="500" height="406" alt="">
+
+<p>
+Mode exact "e" in the first two lines, without widening and with widening set to 0.2.
+
+<p>
+<img src="./img4_2.png" width="350" height="275" alt="">
+<img src="./img4_3.png" width="350" height="275" alt="">
+
+
+<!-- ########################## Terr ############################## -->
+
+<h3>Terr</h3>
+
+<p>
+The cut/fill are calculated with the first displaced line of the left side and the last displaced line of the right side, 
+and with the slope given in the columns cut_left, cut_right, fill_left, fill_right.
+
+<p>
+To get more vertices we have to add new rows to this table with <em>tabletools</em> giving the pk of the vertex.
+
+<p>
+<img src="./img_tables5_1.png" width="400" height="166" alt="">
+
+<p>
+We can generate points of the different alignments, breaklines and a hull of all points.
+
+<pre><code>
+v.road -r name=Circuit terr=slopes,sareas,topo dem=elev_lid792_1m
+</code></pre>
+
+<p>
+And we obtain the map Circuit__Slopes, Circuit__Slopes_Areas, Circuit__Topo and Circuit__Topo_Hull, and their tables. 
+
+<p>
+<img src="./img5.png" width="500" height="406" alt="">
+
+
+
+<!-- ########################## Displaced ############################## -->
+
+<h3>Transversal</h3>
+
+<p>
+In this table where we are going to define transversals 2D lines to the central axis, to obtain later, the cross sections.
+
+<p>
+This lines contains the cutoff with the displaced lines.
+
+<p>
+When this table is created, have two rows, who are the first and the last points of the central axis. 
+
+<p>
+In the columns dist_left, dist_right we can define the distance left and right to the central axis and in the column npk the distance between lines. 
+
+<p>
+<img src="./img_tables6_1.png" width="400" height="166" alt="">
+
+<p>
+We can obtain the transversal profiles selecting it too.
+
+<pre><code>
+v.road -r name=Circuit trans=trans,profiles dem=elev_lid792_1m
+</code></pre>
+
+<p>
+And we obtain the map Circuit__Trans and Circuit__TransProfiles, and their tables. 
+
+<p>
+<img src="./img6.png" width="500" height="406" alt="">
+
+<p>
+<img src="./img6_1.png" width="500" height="406" alt="">
+
+
+<h3>Marks</h3>
+We can define marks or road objects by pk.
+<p>
+<img src="./img_tables7_1.png" width="400" height="166" alt="">
+
+<p>
+<img src="./img7.png" width="500" height="406" alt="">
+
+
+
+<!-- ########################## Displaced ############################## -->
+
+<h3>TopoTools</h3>
+
+<p>
+With the Circuit_Topo map created, we can triangulate with triangle or delaunay, and obtain the curves.
+
+<p>
+In this example we must delete the points that cross the road, for a good triangulation. We can run this.
+
+<pre><code>
+v.edit map=Circuit__Topo type=point tool=delete ids=0-999999 where="pk > 876 AND pk < 1074"
+v.edit map=Circuit__Topo type=point tool=delete ids=0-999999 where="pk > 1690 AND pk < 1811"
+
+db.execute sql="DELETE FROM Circuit__Topo WHERE pk > 876 and pk < 1074"
+db.execute sql="DELETE FROM Circuit__Topo WHERE pk > 1690 and pk < 1811"
+</code></pre>
+
+<p>
+And obtain the Circuit__Topo like this. The hull must be changed too.
+
+
+<p>
+<img src="./img8_1.png" width="500" height="406" alt="">
+
+
+<p>
+<img src="./img_a_topotools_1.png" width="399" height="339" alt="">
+
+<pre><code>
+v.road -o name=Circuit dem=elev_lid792_1m topotools=delaunay,curved,cut_hull
+</code></pre>
+
+<p>
+And we obtain the map Circuit__Topo_Tin and Circuit__Topo_Curves, and their tables. 
+
+<p>
+<img src="./img8_2.png" width="500" height="406" alt="">
+
+
+<!-- ########################## Displaced ############################## -->
+
+<h3>Backup</h3>
+
+<p>
+After run the backup you can run this to obtain all maps.
+
+<pre><code>
+v.road -r name=Circuit plan=plan,pks,displ,marks vert=vert,profile trans=trans,profiles terr=slopes,sareas,topo dem=elev_lid792_1m
+</code></pre>
+
+<pre><code>
+echo "L 15 1
+ 638602.453907 220281.587467
+ 638872.438983 220266.927644
+ 638731.321851 220395.256912
+ 638781.230311 220495.669832
+ 638890.64791 220489.728605
+ 638750.420421 220565.326292
+ 638662.05161 220298.095029
+ 638632.866458 220535.678384
+ 638483.222668 220543.750924
+ 638406.451001 220388.023737
+ 638502.195923 220398.284828
+ 638721.795144 220655.135048
+ 638656.193203 220404.828666
+ 638268.15133 220299.739643
+ 638602.453907 220281.587467
+ 1  1
+P  1 1
+ 638602.453907 220281.587467
+ 2    1
+P  1 1
+ 638872.438983 220266.927644
+ 2    2
+P  1 1
+ 638731.321851 220395.256912
+ 2    3
+P  1 1
+ 638781.230311 220495.669832
+ 2    4
+P  1 1
+ 638890.64791 220489.728605
+ 2    5
+P  1 1
+ 638750.420421 220565.326292
+ 2    6
+P  1 1
+ 638662.05161 220298.095029
+ 2    7
+P  1 1
+ 638632.866458 220535.678384
+ 2    8
+P  1 1
+ 638483.222668 220543.750924
+ 2    9
+P  1 1
+ 638406.451001 220388.023737
+ 2    10
+P  1 1
+ 638502.195923 220398.284828
+ 2    11
+P  1 1
+ 638721.795144 220655.135048
+ 2    12
+P  1 1
+ 638656.193203 220404.828666
+ 2    13
+P  1 1
+ 638268.15133 220299.739643
+ 2    14
+P  1 1
+ 638602.453907 220281.587467
+ 2    15
+P  1 1
+ 638602.453907 220281.587467
+ 8    1
+P  1 1
+ 638602.453907 220281.587467
+ 8    2
+P  1 1
+ 638602.453907 220281.587467
+ 4    1
+P  1 1
+ 638634.426432 220500.061126
+ 4    2
+P  1 1
+ 638621.330858 220519.982685
+ 4    3
+P  1 1
+ 638465.368943 220506.786855
+ 4    4
+P  1 1
+ 638666.507984 220451.258691
+ 4    5
+P  1 1
+ 638662.328095 220442.177014
+ 4    6
+P  1 1
+ 638573.410617 220382.409616
+ 4    7
+P  1 1
+ 638602.453907 220281.587467
+ 4    8
+P  1 1
+ 638602.453907 220281.587467
+ 3    1
+P  1 1
+ 638794.637722 220294.628116
+ 3    2
+P  1 1
+ 638791.485541 220543.187779
+ 3    3
+P  1 1
+ 638641.56261 220464.886873
+ 3    4
+P  1 1
+ 638621.266312 220399.660839
+ 3    5
+P  1 1
+ 638406.371565 220315.000175
+ 3    6
+P  1 1
+ 638602.453907 220281.587467
+ 3    7
+P  1 1
+ 638602.453907 220281.587467
+ 7    1
+P  1 1
+ 638634.610948 220499.596419
+ 7    2
+P  1 1
+ 638465.368943 220506.786855
+ 7    3
+P  1 1
+ 638666.507984 220451.258691
+ 7    4
+P  1 1
+ 638654.577521 220429.350321
+ 7    5
+P  1 1
+ 638637.711356 220410.985026
+ 7    6
+P  1 1
+ 638616.836773 220397.342402
+ 7    7
+P  1 1
+ 638593.594427 220388.201219
+ 7    8
+P  1 1
+ 638573.410617 220382.409616
+ 7    9
+P  1 1
+ 638602.453907 220281.587467
+ 7    10
+P  1 1
+ 638602.453907 220281.587467
+ 5    1
+P  1 1
+ 638693.765832 220585.688009
+ 5    2
+P  1 1
+ 638691.041172 220537.792247
+ 5    3
+P  1 1
+ 638535.766657 220372.214897
+ 5    4
+P  1 1
+ 638602.453907 220281.587467
+ 5    5
+P  1 1
+ 638602.453907 220281.587467
+ 6    1
+P  1 1
+ 638602.453907 220281.587467
+ 6    2
+" | v.in.ascii -n input=- output=Circuit format=standard --o 
+
+v.db.addtable map=Circuit table=Circuit_Plan layer=2 key=cat2 columns="pk_eje double precision,radio double precision,a_in double precision,a_out double precision,widening double precision,superelev varchar(25),dc_ double precision,lr_ double precision"
+v.db.addtable map=Circuit table=Circuit_Displ layer=8 key=cat8 columns="pk double precision,sec_left varchar(25),sec_right varchar(25),type_left varchar(25),type_right varchar(25)"
+v.db.addtable map=Circuit table=Circuit_Displ layer=4 key=cat4 columns="pk double precision,sec_left varchar(25),sec_right varchar(25),type_left varchar(25),type_right varchar(25)"
+v.db.addtable map=Circuit table=Circuit_Vert layer=3 key=cat3 columns="pk double precision,elev double precision,kv double precision,l double precision,b double precision"
+v.db.addtable map=Circuit table=Circuit_Marks layer=7 key=cat7 columns="pk double precision,dist varchar(25),elev varchar(25),azi varchar(25),name varchar(25),cod varchar(25)"
+v.db.addtable map=Circuit table=Circuit_Terr layer=5 key=cat5 columns="pk double precision,cut_left double precision,cut_right double precision,fill_left double precision,fill_right double precision,height double precision,leng double precision"
+v.db.addtable map=Circuit table=Circuit_Trans layer=6 key=cat6 columns="pk double precision,dist_left double precision,dist_right double precision,npk double precision"
+v.db.addtable map=Circuit table=Circuit layer=1 key=cat columns="name varchar(25)"
+
+echo "UPDATE Circuit_Plan SET pk_eje='0.0',radio='0.0',a_in='0.0',a_out='0.0',widening='0.0',superelev='',dc_='0.0',lr_='140.002162531' WHERE cat2=1;
+UPDATE Circuit_Plan SET pk_eje='270.382786955',radio='-40.0',a_in='35.0',a_out='35.0',widening='0.0',superelev='',dc_='67.689561716',lr_='18.521314174' WHERE cat2=2;
+UPDATE Circuit_Plan SET pk_eje='461.124617255',radio='40.0',a_in='30.0',a_out='30.0',widening='0.0',superelev='',dc_='29.2637172691',lr_='39.7863972502' WHERE cat2=3;
+UPDATE Circuit_Plan SET pk_eje='573.256721368',radio='30.0',a_in='25.0',a_out='25.0',widening='0.0',superelev='',dc_='14.0798000021',lr_='1.81890329525' WHERE cat2=4;
+UPDATE Circuit_Plan SET pk_eje='682.835501948',radio='-15.0',a_in='15.0',a_out='15.0',widening='0.0',superelev='',dc_='25.5209406839',lr_='47.3026773599' WHERE cat2=5;
+UPDATE Circuit_Plan SET pk_eje='842.142623261',radio='-20.0',a_in='20.0',a_out='20.0',widening='0.0',superelev='',dc_='14.9175006172',lr_='100.00718402' WHERE cat2=6;
+UPDATE Circuit_Plan SET pk_eje='1123.60593223',radio='30.0',a_in='25.0',a_out='25.0',widening='0.0',superelev='',dc_='60.1666666667',lr_='24.9072874929' WHERE cat2=7;
+UPDATE Circuit_Plan SET pk_eje='1362.97515278',radio='-60.0',a_in='45.0',a_out='45.0',widening='0.0',superelev='',dc_='49.9304491395',lr_='25.1574394299' WHERE cat2=8;
+UPDATE Circuit_Plan SET pk_eje='1512.8365209',radio='-60.0',a_in='45.0',a_out='45.0',widening='0.0',superelev='',dc_='36.2500000006',lr_='68.9069121541' WHERE cat2=9;
+UPDATE Circuit_Plan SET pk_eje='1686.45923111',radio='-20.0',a_in='20.0',a_out='20.0',widening='0.0',superelev='',dc_='22.711648047',lr_='24.7225033281' WHERE cat2=10;
+UPDATE Circuit_Plan SET pk_eje='1782.75242935',radio='-40.0',a_in='25.0',a_out='25.0',widening='0.0',superelev='',dc_='14.6414158745',lr_='213.435753539' WHERE cat2=11;
+UPDATE Circuit_Plan SET pk_eje='2120.68119964',radio='20.0',a_in='20.0',a_out='20.0',widening='0.0',superelev='',dc_='33.810837057',lr_='71.3354524078' WHERE cat2=12;
+UPDATE Circuit_Plan SET pk_eje='2379.441513',radio='100.0',a_in='75.0',a_out='75.0',widening='0.0',superelev='',dc_='48.75',lr_='140.918379815' WHERE cat2=13;
+UPDATE Circuit_Plan SET pk_eje='2781.46165959',radio='-25.0',a_in='25.0',a_out='25.0',widening='0.0',superelev='',dc_='45.5718116349',lr_='160.427746506' WHERE cat2=14;
+UPDATE Circuit_Plan SET pk_eje='3116.25669305',radio='0.0',a_in='0.0',a_out='0.0',widening='0.0',superelev='',dc_='0.0',lr_='0.0' WHERE cat2=15;
+UPDATE Circuit_Displ SET pk='0.0',sec_left='6 0;3.5 0',sec_right='3.5 0;6 0',type_left='',type_right='' WHERE cat8=1;
+UPDATE Circuit_Displ SET pk='2208.88779535',sec_left='6 0;3.5 0',sec_right='3.5 0;6 0',type_left='',type_right='' WHERE cat8=2;
+UPDATE Circuit_Displ SET pk='0.0',sec_left='10 -0.34;8 -0.19;6.5 -0.13;4 -0.08',sec_right='4 -0.08;6.5 -0.13;8 -0.19;10 -0.34',type_left='l;l;e;e',type_right='e;e;l;l' WHERE cat4=1;
+UPDATE Circuit_Displ SET pk='876.0',sec_left='10 -0.34;-1 0;-1 0;-1 0',sec_right='-1 0;-1 0;-1 0;10 -0.34',type_left='l;l;l;l',type_right='l;l;l;l' WHERE cat4=2;
+UPDATE Circuit_Displ SET pk='900.0',sec_left='0 0;-1 0;-1 0;-1 0',sec_right='-1 0;-1 0;-1 0;0 0',type_left='l;l;l;l',type_right='l;l;l;l' WHERE cat4=3;
+UPDATE Circuit_Displ SET pk='1074.0',sec_left='10 -0.34;-1 0;-1 0;-1 0',sec_right='-1 0;-1 0;-1 0;10 -0.34',type_left='l;l;l;l',type_right='l;l;l;l' WHERE cat4=4;
+UPDATE Circuit_Displ SET pk='1690.0',sec_left='10 -0.34;-1 0;-1 0;-1 0',sec_right='-1 0;-1 0;-1 0;10 -0.34',type_left='l;l;l;l',type_right='l;l;l;l' WHERE cat4=5;
+UPDATE Circuit_Displ SET pk='1700.0',sec_left='0 0;-1 0;-1 0;-1 0',sec_right='-1 0;-1 0;-1 0;0 0',type_left='l;l;l;l',type_right='l;l;l;l' WHERE cat4=6;
+UPDATE Circuit_Displ SET pk='1811.0',sec_left='10 -0.34;-1 0;-1 0;-1 0',sec_right='-1 0;-1 0;-1 0;10 -0.34',type_left='l;l;l;l',type_right='l;l;l;l' WHERE cat4=7;
+UPDATE Circuit_Displ SET pk='2208.88779535',sec_left=' 10 -0.34;8 -0.19;6.5 -0.13;4 -0.08',sec_right='4 -0.08;6.5 -0.13;8 -0.19; 10 -0.34',type_left='l;l;l;l',type_right='l;l;l;l' WHERE cat4=8;
+UPDATE Circuit_Vert SET pk='0.0',elev='118.0',kv='0.0',l='0.0',b='0.0' WHERE cat3=1;
+UPDATE Circuit_Vert SET pk='200.0',elev='116.0',kv='-2500.0',l='0.0',b='0.0' WHERE cat3=2;
+UPDATE Circuit_Vert SET pk='550.0',elev='133.0',kv='3000.0',l='0.0',b='0.0' WHERE cat3=3;
+UPDATE Circuit_Vert SET pk='840.0',elev='114.0',kv='-2000.0',l='0.0',b='0.0' WHERE cat3=4;
+UPDATE Circuit_Vert SET pk='1760.0',elev='133.0',kv='3000.0',l='0.0',b='0.0' WHERE cat3=5;
+UPDATE Circuit_Vert SET pk='2000.0',elev='121.0',kv='-2000.0',l='0.0',b='0.0' WHERE cat3=6;
+UPDATE Circuit_Vert SET pk='2208.88779535',elev='118.0',kv='0.0',l='0.0',b='0.0' WHERE cat3=7;
+UPDATE Circuit_Marks SET pk='0.0',dist='',elev='',azi='',name='',cod='' WHERE cat7=1;
+UPDATE Circuit_Marks SET pk='875.5',dist='0',elev='0',azi='1',name='Bridge1',cod='a1' WHERE cat7=2;
+UPDATE Circuit_Marks SET pk='1074.0',dist='0',elev='0',azi='-1',name='Bridge2',cod='a1' WHERE cat7=3;
+UPDATE Circuit_Marks SET pk='1690.0',dist='0',elev='0',azi='1',name='Tunel1',cod='a2' WHERE cat7=4;
+UPDATE Circuit_Marks SET pk='1715.0',dist='0',elev='0',azi='1',name='Pila',cod='' WHERE cat7=5;
+UPDATE Circuit_Marks SET pk='1740.0',dist='0',elev='0',azi='1',name='Pila',cod='' WHERE cat7=6;
+UPDATE Circuit_Marks SET pk='1765.0',dist='0',elev='0',azi='1',name='Pila',cod='' WHERE cat7=7;
+UPDATE Circuit_Marks SET pk='1790.0',dist='0',elev='0',azi='1',name='Pila',cod='' WHERE cat7=8;
+UPDATE Circuit_Marks SET pk='1811.0',dist='0',elev='0',azi='-1',name='Tunel2',cod='a2' WHERE cat7=9;
+UPDATE Circuit_Marks SET pk='2208.88779535',dist='',elev='',azi='',name='',cod='' WHERE cat7=10;
+UPDATE Circuit_Terr SET pk='0.0',cut_left='2.0',cut_right='2.0',fill_left='0.5',fill_right='0.5',height='0.0',leng='0.0' WHERE cat5=1;
+UPDATE Circuit_Terr SET pk='1550.0',cut_left='2.0',cut_right='2.0',fill_left='0.5',fill_right='0.5',height='0.0',leng='0.0' WHERE cat5=2;
+UPDATE Circuit_Terr SET pk='1600.0',cut_left='2.0',cut_right='2.0',fill_left='4.0',fill_right='4.0',height='0.0',leng='0.0' WHERE cat5=3;
+UPDATE Circuit_Terr SET pk='1850.0',cut_left='2.0',cut_right='2.0',fill_left='0.5',fill_right='0.5',height='0.0',leng='0.0' WHERE cat5=4;
+UPDATE Circuit_Terr SET pk='2208.88779535',cut_left='2.0',cut_right='2.0',fill_left='0.5',fill_right='0.5',height='0.0',leng='0.0' WHERE cat5=5;
+UPDATE Circuit_Trans SET pk='0.0',dist_left='20.0',dist_right='20.0',npk='20.0' WHERE cat6=1;
+UPDATE Circuit_Trans SET pk='2208.88779535',dist_left='20.0',dist_right='20.0',npk='20.0' WHERE cat6=2;
+UPDATE Circuit SET name='Circuit' WHERE cat=1;
+" | db.execute input=- 
+</code></pre>


Property changes on: grass-addons/grass7/vector/v.civil/v.road.html
___________________________________________________________________
Added: svn:mime-type
   + text/html
Added: svn:keywords
   + Author Date Id
Added: svn:eol-style
   + native

Added: grass-addons/grass7/vector/v.civil/v.road.py
===================================================================
--- grass-addons/grass7/vector/v.civil/v.road.py	                        (rev 0)
+++ grass-addons/grass7/vector/v.civil/v.road.py	2016-07-01 22:30:22 UTC (rev 68831)
@@ -0,0 +1,832 @@
+#!/usr/bin/env python
+# -*- coding: utf-8
+"""
+Created on Wed Jul 23 18:37:36 2014
+
+ at author: jfcr
+"""
+############################################################################
+#
+# MODULE:       v.align, v0.6.0
+#
+# AUTHOR:       Jesús Fernández-Capel Rosillo
+#               Civil Engineer, Spain
+#               jfc at alcd net
+#
+# PURPOSE:      Desing roads, channels, ports...
+#
+# COPYRIGHT:    (c) 2014 Jesús Fernández-Capel Rosillo.
+#
+#               This program is free software under the GNU General Public
+#               License (>=v2). Read the file COPYING that comes with GRASS
+#               for details.
+#
+#############################################################################
+
+#%Module
+#% description: Generate a alignment for desing roads, channels, ports...
+#% keywords: vector, ROADS, CHANNELS, PORTS.
+#%End
+
+#######################
+### Required section
+#######################
+
+#%option G_OPT_V_INPUT
+#% key: name
+#% type: string
+#% description: Name of road map
+#% required: yes
+#%end
+
+#######################
+### Plant section
+#######################
+
+#%option G_OPT_V_TYPE
+#% key: plan
+#% options: plan,pks,displ,marks
+#% answer:
+#% required: no
+#% description: Plan options
+#% guisection: Plan
+#%end
+
+#%option
+#% key: pkopt
+#% type: string
+#% description:  Pks marks options values. (npk,mpk,dist,m)
+#% required: no
+#% answer: 20,100,2,4
+#% guisection: Plan
+#%end
+
+#%option G_OPT_DB_TABLE
+#% key: dtable
+#% description: Other displaced table (Default all)
+#% required: no
+##% guidependency: ocolumn,scolumns
+#% guisection: Plan
+#%end
+
+#%option G_OPT_DB_TABLE
+#% key: mtable
+#% description: Other marks table (Default all)
+#% required: no
+##% guidependency: ocolumn,scolumns
+#% guisection: Plan
+#%end
+
+#%option
+#% key: areaopt
+#% type: string
+#% description:  Pair of displaced lines for areas (1-2,2-5,5-6)
+#% required: no
+#% guisection: Plan
+#%end
+
+#######################
+### Alz section
+#######################
+
+#%option G_OPT_V_TYPE
+#% key: vert
+#% options: vert,profile
+#% answer:
+#% required: no
+#% description: Vertical options
+#% guisection: Vert
+#%end
+
+#%option
+#% key: lpscale
+#% type: integer
+#% description: Long profile vertical scale (V/H, V/1)
+#% options: 0-100
+#% answer : 4
+#% required: no
+#% guisection: Vert
+#%end
+
+#%option
+#% key: lpopt
+#% type: string
+#% description: Long profile values Longmark,distMark_x,distMark_y,DistGitarr.
+#% required: no
+#% answer: 2,20,1,20
+#% guisection: Vert
+#%end
+
+#%option
+#% key: lpoffset
+#% type: string
+#% description: Long profile offset from origin of region
+#% required: no
+#% answer: 0,0
+#% guisection: Vert
+#%end
+
+#%option
+#% key: camber
+#% type: string
+#% description: General camber
+#% required: no
+#% answer: 0
+#% guisection: Vert
+#%end
+
+#%option
+#% key: displrot
+#% type: string
+#% description: Displaced lines to rotate
+#% required: no
+#% answer: 0,0
+#% guisection: Vert
+#%end
+
+#######################
+### Trans section
+#######################
+
+#%option G_OPT_V_TYPE
+#% key: trans
+#% options: trans,profiles
+#% answer:
+#% required: no
+#% description: Vertical options
+#% guisection: Trans
+#%end
+
+#%option
+#% key: ltscale
+#% type: double
+#% description: Cross section vertical scale (V/H, V/1)
+#% required: no
+#% answer: 2
+#% guisection: Trans
+#%end
+
+#%option
+#% key: ltopt1
+#% type: string
+#% description: Cross section options values Longmark,distMark_x,distMark_y.
+#% required: no
+#% answer: 1,20,2
+#% guisection: Trans
+#%end
+
+#%option
+#% key: ltopt2
+#% type: string
+#% description: Trans section options values for nrows,distTP_x,distTP_y.
+#% required: no
+#% answer: 10,10,10
+#% guisection: Trans
+#%end
+
+#%option
+#% key: ltoffset
+#% type: string
+#% description: Trans sections profile offset from origin of region
+#% required: no
+#% answer: 0,0
+#% guisection: Trans
+#%end
+
+#########################
+### Terrain section
+#########################
+
+#%option G_OPT_V_TYPE
+#% key: terr
+#% options: slopes,sareas,topo
+#% answer:
+#% required: no
+#% description: Terrain options
+#% guisection: Terr
+#%end
+
+#%option G_OPT_R_INPUT
+#% key: dem
+#% key_desc: raster dem
+#% description: Name of DEM raster
+#% required: no
+#% guisection: Terr
+#%end
+
+#########################
+### TopoTools section
+#########################
+
+#%flag
+#% key: o
+#% description: TopoTools
+#% guisection: TopoTools
+#%end
+
+#%option G_OPT_V_TYPE
+#% key: actions
+#% options: uppoints, pnt_info
+#% answer:
+#% required: no
+#% description: Points tools
+#% guisection: TopoTools
+#%end
+
+#%option
+#% key: pk_info
+#% type: double
+#% description: PK
+#% required: no
+#% answer: 0
+#% guisection: TopoTools
+#%end
+
+#%option G_OPT_V_TYPE
+#% key: topotools
+#% options: triangle,delaunay,curved,cut_hull
+#% answer:
+#% required: no
+#% description: Triangulate and curved
+#% guisection: TopoTools
+#%end
+
+##%option G_OPT_V_TYPE
+##% key: tinraster
+##% options: tintorast,nnbathy
+##% answer:
+##% required: no
+##% description: Triangulate and curved
+##% guisection: TopoTools
+##%end
+
+
+#%option G_OPT_V_TYPE
+#% key: roundabout
+#% options: roundabout
+#% answer:
+#% required: no
+#% description: Roundabout tools
+#% guisection: TopoTools
+#%end
+
+#%option
+#% key: rround1
+#% type: string
+#% description: Minus radio for roundabout edge
+#% required: no
+#% guisection: TopoTools
+#%end
+
+#%option
+#% key: rround2
+#% type: string
+#% description: Mayor radio for roundabout edge
+#% required: no
+#% guisection: TopoTools
+#%end
+
+#%option
+#% key: azround
+#% type: string
+#% description: Azimut for roundabout start point
+#% required: no
+#% guisection: TopoTools
+#%end
+
+#%option
+#% key: cround
+#% type: string
+#% description: Center for roundabout
+#% required: no
+#% guisection: TopoTools
+#%end
+
+#%option
+#% key: roundname
+#% type: string
+#% description: Name for roundabout
+#% required: no
+#% guisection: TopoTools
+#%end
+
+#########################
+### TableTools section
+#########################
+
+#%flag
+#% key: e
+#% description: TableTools
+#% guisection: TableTools
+#%end
+
+#%option G_OPT_V_TYPE
+#% key: add
+#% options: table, row
+#% answer:
+#% required: no
+#% description: Add new table or add row to table
+#% guisection: TableTools
+#%end
+
+#%option
+#% key: tab_type
+#% type: string
+#% label: Name of table for new table or to add row
+#% description: To add new table only Displ or Marks table are supported
+#% options: Vert,Displ,Trans,Terr,Marks
+#% required: no
+#% guisection: TableTools
+#%end
+
+#%option
+#% key: tab_subname
+#% type: string
+#% label: Table subname for new table or row or displ subname to add or del col
+#% required: no
+#% guisection: TableTools
+#%end
+
+#%option
+#% key: pklist
+#% type: string
+#% label: List of Pks
+#% required: no
+#% guisection: TableTools
+#%end
+
+#%option G_OPT_V_TYPE
+#% key: displline
+#% options: add,del
+#% answer:
+#% required: no
+#% description: Add or del displaced line
+#% guisection: TableTools
+#%end
+
+#%option
+#% key: side
+#% type: string
+#% label: left or right side of Displ
+#% options: left,right
+#% required: no
+#% guisection: TableTools
+#%end
+
+#%option
+#% key: ncol
+#% type: integer
+#% label: Number of Displ to insert
+#% required: no
+#% guisection: TableTools
+#%end
+
+#%option
+#% key: sedist
+#% type: string
+#% label: start and end distance and height
+#% required: no
+#% guisection: TableTools
+#%end
+
+#########################
+### CrossTools section
+#########################
+
+#%flag
+#% key: c
+#% description: CrossTools
+#% guisection: CrossTools
+#%end
+
+#%option G_OPT_V_TYPE
+#% key: intersect
+#% options: left1, right1, left2, right2, in, out, rounda, write
+#% answer:
+#% required: no
+#% description: Plan options
+#% guisection: CrossTools
+#%end
+
+#%option G_OPT_V_INPUT
+#% key: plant1
+#% key_desc: map plant 1
+#% description: Name of first map plant
+#% required: no
+#% guisection: CrossTools
+#%end
+
+#%option
+#% key: cat1
+#% type: integer
+#% label: Categorie of align
+#% required: no
+#% answer: 1
+#% guisection: CrossTools
+#%end
+
+
+#%option G_OPT_V_INPUT
+#% key: plant2
+#% key_desc: map plant 2
+#% description: Name of second map plant
+#% required: no
+#% guisection: CrossTools
+#%end
+
+#%option
+#% key: cat2
+#% type: integer
+#% label: Categorie of align
+#% required: no
+#% answer: 1
+#% guisection: CrossTools
+#%end
+
+#%option
+#% key: dist1
+#% type: string
+#% description: Displaced distances for aling 1
+#% required: no
+#% guisection: CrossTools
+#%end
+
+#%option
+#% key: dist2
+#% type: string
+#% description: Displaced distances for aling 2
+#% required: no
+#% guisection: CrossTools
+#%end
+
+#%option
+#% key: radios
+#% type: string
+#% description: Intersections radios
+#% required: no
+#% guisection: CrossTools
+#%end
+
+#########################
+### #Options section
+#########################
+
+#%flag
+#% key: r
+#% description: Run
+#%end
+
+#%flag
+#% key: p
+#% description: Update solution from polygon
+#%end
+
+#%flag
+#% key: t
+#% description: Update solution from table plan distances_
+#%end
+
+#%option
+#% key: intr
+#% type: integer
+#% label: Interval in straights
+#% required: no
+#% answer: 1
+#%end
+
+#%option
+#% key: intc
+#% type: integer
+#% label: Interval in curves
+#% required: no
+#% answer: 1
+#%end
+
+#%option
+#% key: startend
+#% type: string
+#% label: start and end pks (last pk = -1)
+#% required: no
+#% answer: 0,-1
+#%end
+
+#%option G_OPT_F_OUTPUT
+#% key: backup
+#% description: Create backup file
+#% required: no
+#%end
+
+# ######################
+
+import os
+import sys
+
+sys.path.insert(1, os.path.join(os.path.dirname(sys.path[0]), 'etc', 'v.road'))
+
+# import math
+# import road as Road
+import grass.script as grass
+import road_road as Road
+import road_crosstools as Tools2
+import road_topotools as Topotools
+
+
+# =============================================
+# Main
+# =============================================
+
+def main():
+    """Manage v.road
+    >>> road = Road.Road('Circuit')
+    >>>
+
+    """
+    if '@' in options['name']:
+        name_map = options['name'].split('@')[0]
+    else:
+        name_map = options['name']
+
+    plan_opt = options['plan'].split(',')
+    vert_opt = options['vert'].split(',')
+    trans_opt = options['trans'].split(',')
+    terr_opt = options['terr'].split(',')
+
+    add = options['add'].split(',')
+    displline = options['displline'].split(',')
+
+    intersect = options['intersect'].split(',')
+    topotools = options['topotools'].split(',')
+    actions = options['actions'].split(',')
+    roundabout = options['roundabout'].split(',')
+    # tinraster = options['tinraster'].split(',')
+
+    startend = [float(opt) for opt in options['startend'].split(',')]
+    pkopt = [float(opt) for opt in options['pkopt'].split(',')]
+
+    if options['tab_subname']:
+        options['tab_subname'] = '_' + options['tab_subname']
+
+    if options['tab_type']:
+        options['tab_type'] = '_' + options['tab_type']
+
+### Init road
+    road = Road.Road(name_map)
+
+################### TableTools ##################
+
+    if flags['e']:
+        # Insert new point
+        if 'row' in add:
+
+            road.plant_generate()
+
+            if ',' in options['pklist']:
+                list_pks = options['pklist'].split(',')
+            else:
+                list_pks = [options['pklist']]
+
+            road.rtab.add_row(list_pks, road.plant, options['tab_type'],
+                         options['tab_subname'])
+            sys.exit(0)
+
+        # Add new table
+        if 'table' in add:
+            road.rtab.add_table(options['tab_type'], options['tab_subname'])
+            sys.exit(0)
+
+        # Add column to Displ table
+        if 'add' in displline or 'del' in displline:
+            add_col = True
+            if 'del' in displline:
+                add_col = False
+            road.rtab.tables['_Displ' + options['tab_subname']].displ_add_del_col(
+                options['ncol'], options['side'], options['sedist'], add_col)
+        sys.exit(0)
+
+################### CrossTools ##################
+
+    if flags['c']:
+        inout = 'In'
+        if 'out' in intersect:
+            inout = 'Out'
+        rounda = False
+        if 'rounda' in intersect:
+            rounda = True
+        izq1 = 'Izq'
+        if 'right1' in intersect:
+            izq1 = 'Der'
+        izq2 = 'Izq'
+        if 'right2' in intersect:
+            izq2 = 'Der'
+
+        if '@' in options['plant1']:
+            name_plant1 = options['plant1'].split('@')[0]
+        else:
+            name_plant1 = options['plant1']
+
+        if '@' in options['plant2']:
+            name_plant2 = options['plant2'].split('@')[0]
+        else:
+            name_plant2 = options['plant2']
+
+        inter = Tools2.Intersections(name_plant1, int(options['cat1']), izq1,
+                                     name_plant2, int(options['cat2']), izq2,
+                                     inout, rounda)
+        inter.dist2 = [float(p) for p in options['dist2'].split(',')]
+        inter.dist1 = [float(p) for p in options['dist1'].split(',')]
+        inter.radios = [float(p) for p in options['radios'].split(',')]
+
+        if 'write' in intersect:
+            inter.make_intersect(True)
+        else:
+            inter.make_intersect()
+        sys.exit(0)
+
+################### Topotools ##################
+
+    if flags['o']:
+        if actions != ['']:
+            if 'uppoints' in actions:
+                topo = Topotools.Topo(name_map)
+                topo.uppoints()
+
+        if roundabout != ['']:
+            if 'roundabout' in roundabout:
+                topo = Topotools.Topo(options['roundname'])
+                topo.roundabout(options['rround1'], options['rround1'],
+                                options['azround'], options['cround'])
+
+        if topotools != ['']:
+            tri = Topotools.Triang(name_map)
+            if 'triangle' in topotools:
+                tri.split_maps()
+                tri.triangle()
+            elif 'delaunay' in topotools:
+                tri.delaunay()
+            tri.get_area_hull()
+            if 'curved' in topotools:
+                tri.curved()
+            if 'cut_hull' in topotools:
+                tri.cut_by_hull()
+
+        # if tinraster != ['']:
+            # tin = Topotools.Triang(name_map)
+            # if 'tintorast' in tinraster:
+                # tin.tin_to_raster()
+            # if 'nnbathy' in tinraster:
+                # tin.nnbathy()
+
+        else:
+            sys.exit(0)
+
+################### Backup ##################
+
+    if options['backup']:
+        road.rtab.create_backup(options['backup'])
+        grass.message('backup created')
+        sys.exit(0)
+
+##################### Run ###################
+
+    if flags['r']:
+
+        if flags['t']:
+            road.plant_generate(True, float(options['camber']))
+            road.rtab.update_tables()
+        elif flags['p']:
+            road.plant_generate(False, float(options['camber']))
+            road.rtab.update_tables()
+        else:
+            road.plant_generate(False, float(options['camber']))
+
+        if 'plan' in plan_opt:
+            road.rtab.update_tables_pnts(road.plant)
+
+        road.elev_generate()
+
+        road.displ_generate()
+
+        if options['dem']:
+
+            road.terr_generate(options['dem'])
+
+            road.taludes_generate()
+
+            road.trans_generate()
+
+            if 'profile' in vert_opt:
+                road.long_profile_generate(options['lpopt'],
+                                           options['lpscale'],
+                                           options['lpoffset'])
+
+            if 'profiles' in trans_opt:
+                road.trans_profiles_generate(options['ltopt1'],
+                                             options['ltopt2'],
+                                             options['ltscale'],
+                                             options['ltoffset'])
+        else:
+            road.trans_generate()
+
+        if 'marks' in plan_opt:
+            road.marks_generate()
+
+### Write maps
+
+        if flags['o']:
+            if actions != ['']:
+                if 'pnt_info' in actions:
+                    pto_inf = Topotools.Topo(name_map)
+                    pto_inf.pts_info(options['pk_info'], road)
+            sys.exit(0)
+
+        #
+        road.plant.set_roadline(startend[0], startend[1],
+                                float(options['intr']), float(options['intc']))
+        road.plant.add_pks(road.rtab.get_tables_pks())
+
+        road.vert.set_pnts_elev(road.plant.roadline)
+
+        road.displ.set_roadlines(road.plant.roadline)
+
+        #
+        if 'plan' in plan_opt:
+            grass.message('writing plan')
+            road.plant_write()
+
+        if 'displ' in plan_opt:
+            grass.message('writing displ')
+            road.displ_write()
+
+        if 'marks' in plan_opt:
+            grass.message('writing marks')
+            road.marks_write()
+
+        if 'pks' in plan_opt:
+            grass.message('writing pks')
+            road.trans_write_pks(startend, pkopt)
+
+        #
+        if 'vert' in vert_opt:
+            grass.message('writing elev')
+            road.elev_write()
+
+        #
+        if 'trans' in trans_opt:
+            grass.message('writing trans')
+            road.trans_write()
+
+        if options['dem']:
+
+            road.terr.set_pnts_terr(road.plant.roadline)
+
+            road.taludes.set_roadlines(road.plant.roadline, road.displ)
+
+            #
+            if 'profile' in vert_opt:
+                grass.message('writing profile')
+                road.long_profile_write()
+
+            if 'profiles' in trans_opt:
+                grass.message('writing profiles')
+                road.trans_profiles_write()
+
+            #
+            if 'slopes' in terr_opt:
+                grass.message('writing slopes')
+                road.taludes_write()
+
+            if 'sareas' in terr_opt:
+                grass.message('writing slopes_areas')
+                road.taludes_areas_write()
+
+            if 'topo' in terr_opt:
+                grass.message('writing pnts, breakliness and hull for \
+                               triangulation')
+                road.tri_write()
+
+        tab_subname_d = ''
+        if options['dtable']:
+            tab_subname_d = options['dtable'].split('_Displ')[-1]
+            road.displ_generate(tab_subname_d)
+            road.displ.set_roadlines(road.plant.roadline)
+            road.displ_write('_' + tab_subname_d)
+
+        if options['mtable']:
+            road.marks_generate(options['mtable'])
+            tab_subname_m = '_' + options['mtable'].split('_Marks')[-1]
+            road.marks_write(tab_subname_m)
+
+        if options['areaopt']:
+            grass.message('writing displ_areas')
+            road.displ_areas_write(options['areaopt'], tab_subname_d)
+
+    sys.exit(0)
+
+if __name__ == "__main__":
+    if len(sys.argv) == 2 and sys.argv[1] == '--doctest':
+        import doctest
+        doctest.testmod()
+
+    else:
+        options, flags = grass.parser()
+        main()


Property changes on: grass-addons/grass7/vector/v.civil/v.road.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native



More information about the grass-commit mailing list