Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into toolbar
Browse files Browse the repository at this point in the history
* upstream/master:
  solves BlockResearchGroup#60
  when no scale is used the manual modification works
  solves BlockResearchGroup#50
  • Loading branch information
duchaoyu committed Aug 11, 2020
2 parents 732196e + 1517257 commit 615bfd2
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 23 deletions.
17 changes: 14 additions & 3 deletions scripts/test_where_dual.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@
form = FormDiagram.from_graph(graph)
force = ForceDiagram.from_formdiagram(form)

for edge in force.edges_where_dual({'is_external': True}):
dual_edge = force.dual_edge(edge)
print(edge, (form.halfedge[dual_edge[0]][dual_edge[1]], form.halfedge[dual_edge[1]][dual_edge[0]]))
form.edge_force((0, 1), +10.0)
form.edge_force((2, 3), +10.0)
form.edge_force((4, 5), +10.0)

# for edge in force.edges_where_dual({'is_external': True}):
# dual_edge = force.dual_edge(edge)
# print(edge, (form.halfedge[dual_edge[0]][dual_edge[1]], form.halfedge[dual_edge[1]][dual_edge[0]]))

# print(list(form.edges()))
# print(form.edge_index())
print(list(force.edges()))
# print([force.dual_edge(edge) for edge in force.edges()])
print(all(form.has_edge(force.dual_edge(edge)) for edge in force.edges()))
print(list(force.edges_where_dual({'is_ind': True})))
76 changes: 76 additions & 0 deletions scripts/test_zero_rhino_interactive.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import os

import compas_rhino

from compas_ags.diagrams import FormGraph
from compas_ags.diagrams import FormDiagram
from compas_ags.diagrams import ForceDiagram
from compas_ags.rhino import Scene

from compas.rpc import Proxy

graphstatics = Proxy('compas_ags.ags.graphstatics')
graphstatics.restart_server()

# this file has unloaded, 2-valent nodes
# they will be removed automatically
# and the result renumbered
HERE = os.path.dirname(__file__)
FILE = os.path.join(HERE, '../data/debugging/zero.obj')

graph = FormGraph.from_obj(FILE)
form = FormDiagram.from_graph(graph)
force = ForceDiagram.from_formdiagram(form)
scene = Scene()

# fix the supports
form.vertices_attribute('is_fixed', True, [8, 7])

# set the loads
form.edge_force((0, 1), +10.0)
form.edge_force((2, 3), +10.0)
form.edge_force((4, 5), +10.0)

# compute initial form and force diagrams
form.data = graphstatics.form_update_q_from_qind_proxy(form.data)
force.data = graphstatics.force_update_from_form_proxy(force.data, form.data)

form_id = scene.add(form, name="Form", layer="AGS::FormDiagram")
force_id = scene.add(force, name="Force", layer="AGS::ForceDiagram")

form_obj = scene.find(form_id)
force_obj = scene.find(force_id)

force_obj.artist.anchor_vertex = 0
force_obj.artist.anchor_point = [35, 0, 0]
force_obj.artist.scale = 0.5

form_obj.artist.settings['scale.forces'] = 0.02

scene.clear()
scene.update()

while True:
vertices = force_obj.select_vertices()
if not vertices:
break
if vertices and force_obj.move_vertices(vertices):
scene.clear()
scene.update()

# toggle = compas_rhino.rs.GetString("Keep selecting?", defaultString="True", strings=["True", "False"])
# if toggle == "True":
# continue
# else:
# break

scene.update()

# fix some of the nodes in the from diagram
# to constraint the problem to a single solution
form.vertices_attribute('is_fixed', True, [0, 2, 5])

# update the form diagram
form.data = graphstatics.form_update_from_force_proxy(form.data, force.data)

scene.update()
76 changes: 76 additions & 0 deletions scripts/test_zero_rhino_interactive2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import os

import compas_rhino

from compas_ags.diagrams import FormGraph
from compas_ags.diagrams import FormDiagram
from compas_ags.diagrams import ForceDiagram
from compas_ags.rhino import Scene

from compas.rpc import Proxy

graphstatics = Proxy('compas_ags.ags.graphstatics')
graphstatics.restart_server()

# this file has unloaded, 2-valent nodes
# they will be removed automatically
# and the result renumbered
HERE = os.path.dirname(__file__)
FILE = os.path.join(HERE, '../data/debugging/zero.obj')

graph = FormGraph.from_obj(FILE)
form = FormDiagram.from_graph(graph)
force = ForceDiagram.from_formdiagram(form)
scene = Scene()

# fix the supports
form.vertices_attribute('is_fixed', True, [8, 7])

# set the loads
form.edge_force((0, 1), +10.0)
form.edge_force((2, 3), +10.0)
form.edge_force((4, 5), +10.0)

# compute initial form and force diagrams
form.data = graphstatics.form_update_q_from_qind_proxy(form.data)
force.data = graphstatics.force_update_from_form_proxy(force.data, form.data)

form_id = scene.add(form, name="Form", layer="AGS::FormDiagram")
force_id = scene.add(force, name="Force", layer="AGS::ForceDiagram")

form_obj = scene.find(form_id)
force_obj = scene.find(force_id)

force_obj.artist.anchor_vertex = 0
force_obj.artist.anchor_point = [35, 0, 0]
force_obj.artist.scale = 0.5

form_obj.artist.settings['scale.forces'] = 0.02

scene.clear()
scene.update()

while True:
vertices = force_obj.select_vertices()
if not vertices:
break
if vertices and force_obj.move_vertices(vertices):
scene.clear()
scene.update()

# toggle = compas_rhino.rs.GetString("Keep selecting?", defaultString="True", strings=["True", "False"])
# if toggle == "True":
# continue
# else:
# break

scene.update()

# fix some of the nodes in the from diagram
# to constraint the problem to a single solution
form.vertices_attribute('is_fixed', True, [0, 2, 5])

# update the form diagram
form.data = graphstatics.form_update_from_force_proxy(form.data, force.data)

scene.update()
2 changes: 1 addition & 1 deletion src/compas_ags/ags/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def update_form_from_force(xy, _xy, free, leaves, i_nbrs, ij_e, _C, kmax=100):

n = _t[ij_e[(i, j)], None] # the direction of the line (the line parallel to the corresponding line in the force diagram)

if normrow(n)[0, 0] < 0.0001:
if normrow(n)[0, 0] < 0.001:
continue

r = I - n.T.dot(n) # projection into the orthogonal space of the direction vector
Expand Down
7 changes: 5 additions & 2 deletions src/compas_ags/diagrams/forcediagram.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def edges_where_dual(self, conditions, data=False):
>>>
"""
for edge in self.edges():
for edge in list(self.edges()):
is_match = True

dual_edge = self.dual_edge(edge)
Expand Down Expand Up @@ -148,7 +148,9 @@ def dual_edge(self, edge):
"""
for u, v in self.dual.face_halfedges(edge[0]):
if self.dual.halfedge[v][u] == edge[1]:
return u, v
if self.dual.has_edge((u, v)):
return u, v
return v, u

def is_dual_edge_external(self, edge):
"""Verify if the corresponding edge in the diagram's dual is marked as "external".
Expand Down Expand Up @@ -242,6 +244,7 @@ def edge_index(self, form=None):
f1 = form.halfedge[u][v]
f2 = form.halfedge[v][u]
edge_index[f1, f2] = index
# the weird side-effect of this is that edges get rotated if necessary
return edge_index

def ordered_edges(self, form):
Expand Down
25 changes: 17 additions & 8 deletions src/compas_ags/rhino/diagramartist.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from compas.geometry import add_vectors
from compas.geometry import subtract_vectors
from compas.geometry import centroid_points
from compas.geometry import distance_point_point
from compas.utilities import color_to_colordict as colordict
from compas_rhino.artists import MeshArtist

Expand Down Expand Up @@ -86,6 +87,7 @@ def __init__(self, diagram, *args, **kwargs):
'color.tension': (255, 0, 0),
'color.anchor': (255, 0, 0),
'scale.forces': 0.1,
'tol.edges': 1e-3,
'tol.forces': 1e-3,
})
self._anchor_point = None
Expand Down Expand Up @@ -283,7 +285,7 @@ def draw_vertexlabels(self, text=None, color=None):
The GUIDs of the created Rhino objects.
"""
vertex_text = textdict(text, list(self.diagram.vertices()))
vertex_color = colordict(color, vertex_text.keys(), default=self.settings.get('color.vertices'), colorformat='rgb', normalize=False)
vertex_color = colordict(color, vertex_text.keys(), default=self.settings['color.vertices'], colorformat='rgb', normalize=False)
vertex_xyz = self.vertex_xyz
labels = []
for vertex in vertex_text:
Expand Down Expand Up @@ -312,12 +314,17 @@ def draw_edges(self, keys=None, color=None):
The GUIDs of the created Rhino objects.
"""
edges = keys or list(self.diagram.edges())
edge_color = colordict(color, edges, default=self.settings.get('color.edges'), colorformat='rgb', normalize=False)
edge_color = colordict(color, edges, default=self.settings['color.edges'], colorformat='rgb', normalize=False)
vertex_xyz = self.vertex_xyz
lines = []
for edge in edges:
lines.append({'start': vertex_xyz[edge[0]],
'end': vertex_xyz[edge[1]],
start = vertex_xyz[edge[0]]
end = vertex_xyz[edge[1]]
if distance_point_point(start, end) < self.settings['tol.edges']:
continue

lines.append({'start': start,
'end': end,
'color': edge_color[edge],
'name': "{}.edge.{}-{}".format(self.diagram.name, *edge)})
guids = compas_rhino.draw_lines(lines, layer=self.layer, clear=False, redraw=False)
Expand All @@ -341,18 +348,20 @@ def draw_edgelabels(self, text=None, color=None):
The GUIDs of the created Rhino objects.
"""
if text is None:
edge_text = {(u, v): "{}-{}".format(u, v) for u, v in self.diagram.edges()}
edge_text = {edge: "{}-{}".format(*edge) for edge in self.diagram.edges()}
elif isinstance(text, dict):
edge_text = text
else:
raise NotImplementedError

edge_color = colordict(color, edge_text.keys(), default=self.settings.get('color.edges'), colorformat='rgb', normalize=False)
edge_color = colordict(color, edge_text.keys(), default=self.settings['color.edges'], colorformat='rgb', normalize=False)
vertex_xyz = self.vertex_xyz
labels = []
for edge in edge_text:
start = vertex_xyz[edge[0]]
end = vertex_xyz[edge[1]]
if distance_point_point(start, end) < self.settings['tol.edges']:
continue
pos = [0.5 * (a + b) for a, b in zip(start, end)]
labels.append({'pos': pos,
'color': edge_color[edge],
Expand Down Expand Up @@ -382,7 +391,7 @@ def draw_faces(self, keys=None, color=None):
The GUIDs of the created Rhino objects.
"""
faces = keys or list(self.diagram.faces())
face_color = colordict(color, faces, default=self.settings.get('color.faces'), colorformat='rgb', normalize=False)
face_color = colordict(color, faces, default=self.settings['color.faces'], colorformat='rgb', normalize=False)
vertex_xyz = self.vertex_xyz
faces_ = []
for face in faces:
Expand Down Expand Up @@ -411,7 +420,7 @@ def draw_facelabels(self, text=None, color=None):
The GUIDs of the created Rhino objects.
"""
face_text = textdict(text, list(self.diagram.faces()))
face_color = colordict(color, face_text.keys(), default=self.settings.get('color.faces'), colorformat='rgb', normalize=False)
face_color = colordict(color, face_text.keys(), default=self.settings['color.faces'], colorformat='rgb', normalize=False)
vertex_xyz = self.vertex_xyz
labels = []
for face in face_text:
Expand Down
29 changes: 21 additions & 8 deletions src/compas_ags/rhino/diagramobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,25 +154,31 @@ def OnDynamicDraw(sender, e):
diagram = self.diagram
vertex_xyz = self.artist.vertex_xyz
scale = 1 / self.artist.scale
origin = self.artist.anchor_point
anchor_xyz = diagram.vertex_attributes(self.artist.anchor_vertex, 'xyz')

color = Rhino.ApplicationSettings.AppearanceSettings.FeedbackColor
if '_is_edge' in diagram.default_edge_attributes:
nbrs = [vertex_xyz[nbr] for nbr in diagram.vertex_neighbors(vertex) if diagram.edge_attribute((vertex, nbr), '_is_edge')]
else:
nbrs = [vertex_xyz[nbr] for nbr in diagram.vertex_neighbors(vertex)]

nbrs = [Point3d(*xyz) for xyz in nbrs]
gp = Rhino.Input.Custom.GetPoint()
gp.SetCommandPrompt('Point to move to?')
gp.DynamicDraw += OnDynamicDraw
if constraint:
gp.Constrain(constraint, allow_off)

gp.Get()
if gp.CommandResult() != Rhino.Commands.Result.Success:
return False
pos1 = vertex_xyz[vertex]
pos2 = list(gp.Point())
vector = scale_vector(subtract_vectors(pos2, pos1), scale)
xyz = diagram.vertex_attributes(vertex, 'xyz')
diagram.vertex_attributes(vertex, 'xyz', add_vectors(xyz, vector))

point = list(gp.Point())

dxyz = scale_vector(subtract_vectors(point, origin), scale)
diagram.vertex_attributes(vertex, 'xyz', add_vectors(anchor_xyz, dxyz))

return True

def move_vertices(self, vertices):
Expand Down Expand Up @@ -203,6 +209,9 @@ def OnDynamicDraw(sender, e):
diagram = self.diagram
vertex_xyz = self.artist.vertex_xyz
scale = 1 / self.artist.scale
origin = self.artist.anchor_point
anchor_xyz = diagram.vertex_attributes(self.artist.anchor_vertex, 'xyz')

color = Rhino.ApplicationSettings.AppearanceSettings.FeedbackColor
lines = []
connectors = []
Expand All @@ -218,6 +227,7 @@ def OnDynamicDraw(sender, e):
lines.append(line)
else:
connectors.append(line)

gp = Rhino.Input.Custom.GetPoint()
gp.SetCommandPrompt('Point to move from?')
gp.Get()
Expand All @@ -236,10 +246,13 @@ def OnDynamicDraw(sender, e):
return False

end = gp.Point()
vector = scale_vector(list(end - start), scale)
vector = list(end - start)

for vertex in vertices:
xyz = diagram.vertex_attributes(vertex, 'xyz')
diagram.vertex_attributes(vertex, 'xyz', add_vectors(xyz, vector))
dxyz = subtract_vectors(add_vectors(vertex_xyz[vertex], vector), origin)
dxyz = scale_vector(dxyz, scale)
diagram.vertex_attributes(vertex, 'xyz', add_vectors(anchor_xyz, dxyz))

return True

def modify_vertices(self, vertices=None, names=None):
Expand Down
4 changes: 3 additions & 1 deletion src/compas_ags/rhino/forceartist.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ def draw(self):
self.draw_vertexlabels(text=text, color=color)
# edge labels
if self.settings['show.edgelabels']:
text = {edge: index for index, edge in enumerate(self.diagram.ordered_edges(self.diagram.dual))}
edge_index = self.diagram.edge_index(self.diagram.dual)
edge_index.update({(v, u): index for (u, v), index in edge_index.items()})
text = {edge: edge_index[edge] for edge in self.diagram.edges()}
color = {}
color.update({edge: self.settings['color.edges'] for edge in self.diagram.edges()})
color.update({edge: self.settings['color.edges:is_external'] for edge in self.diagram.edges_where_dual({'is_external': True})})
Expand Down

0 comments on commit 615bfd2

Please sign in to comment.