Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5187fded02 | |||
| 370825838a | |||
| bc8eece488 | |||
| 4222b1721d | |||
| b475bc96af | |||
| f9ac7319ae | |||
| 2ce3e9150f |
@@ -185,26 +185,6 @@ module SpeckleConnector
|
|||||||
create_folder_layers(folder_layer_arrays, folder)
|
create_folder_layers(folder_layer_arrays, folder)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @param page [Sketchup::Page] scene to update -update properties-
|
|
||||||
def set_page_update_properties(page, update_properties)
|
|
||||||
update_properties.each do |prop, value|
|
|
||||||
page.instance_variable_set(:"@#{prop}", value)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# @param rendering_options [Sketchup::RenderingOptions] rendering options of scene (page)
|
|
||||||
def set_rendering_options(rendering_options, speckle_rendering_options)
|
|
||||||
speckle_rendering_options.each do |prop, value|
|
|
||||||
next if rendering_options[prop].nil?
|
|
||||||
|
|
||||||
rendering_options[prop] = if value.is_a?(Hash)
|
|
||||||
SpeckleObjects::Others::Color.to_native(value)
|
|
||||||
else
|
|
||||||
value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# @param headless_layers [Array<String>] headless layer names.
|
# @param headless_layers [Array<String>] headless layer names.
|
||||||
# @param folder [Sketchup::Layers, Sketchup::LayerFolder] layer folder to create commit layers under it.
|
# @param folder [Sketchup::Layers, Sketchup::LayerFolder] layer folder to create commit layers under it.
|
||||||
def create_headless_layers(headless_layers, folder)
|
def create_headless_layers(headless_layers, folder)
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module SpeckleConnector
|
||||||
|
# Operations related to {SketchupModel}.
|
||||||
|
module SketchupModel
|
||||||
|
# Works directly with/on SketchUp Entities of different kinds (Groups, Faces, Edges, ...).
|
||||||
|
module Utils
|
||||||
|
# Static methods to do plane calculations with sketchup geom objects like Point3d and Vector3d.
|
||||||
|
class Plane
|
||||||
|
ORTHOGONAL_TOLERANCE = 1e-5
|
||||||
|
LENGTH_TOLERANCE = 1e-8
|
||||||
|
|
||||||
|
# Create plane from 3 points
|
||||||
|
# @param origin [Geom::Point3d] the point on the plane that wil become the origin of the local coordinate system
|
||||||
|
# @param point_1 [Geom::Point3d] the point that defines first direction
|
||||||
|
# @param point_2 [Geom::Point3d] the third point on the plane
|
||||||
|
# @return [Plane] the parametrization of the plane that goes through the given points
|
||||||
|
def self.from_points(origin, point_1, point_2)
|
||||||
|
direction_x = origin.vector_to(point_1).normalize
|
||||||
|
direction_x = direction_x.normalize
|
||||||
|
normal = direction_x.cross(origin.vector_to(point_2))
|
||||||
|
direction_y = direction_x.cross(normal.normalize)
|
||||||
|
new(origin: origin, direction_u: direction_x, direction_v: direction_y)
|
||||||
|
end
|
||||||
|
|
||||||
|
# @return [Geom::Vector3d] the direction of the u-axis on the plane
|
||||||
|
attr_reader :direction_u
|
||||||
|
|
||||||
|
# @return [Geom::Vector3d] the direction of the v-axis on the plane
|
||||||
|
attr_reader :direction_v
|
||||||
|
|
||||||
|
# @return [Geom::Point3d] the origin of the local coordinate system on the plane
|
||||||
|
attr_reader :origin
|
||||||
|
|
||||||
|
# @param origin [Geom::Point3d] the origin of the coordinate system on the plane
|
||||||
|
# @param direction_u [Geom::Vector3d] the direction of the x-axis
|
||||||
|
# @param direction_v [Geom::Vector3d] the direction of the y-axis
|
||||||
|
def initialize(origin:, direction_u:, direction_v:)
|
||||||
|
@origin = origin
|
||||||
|
raise ArgumentError, 'directions must me orthogonal' if direction_u.dot(direction_v) > ORTHOGONAL_TOLERANCE
|
||||||
|
raise ArgumentError, 'directions must be of length 1' if (direction_u.length - 1).abs > LENGTH_TOLERANCE
|
||||||
|
raise ArgumentError, 'directions must be of length 1' if (direction_v.length - 1).abs > LENGTH_TOLERANCE
|
||||||
|
|
||||||
|
@direction_u = direction_u
|
||||||
|
@direction_v = direction_v
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get the point object in global coordinates for the point on the plane with local coordinates (u,v).
|
||||||
|
# @param coordinate_u [Float] the u-coordinate on the plane
|
||||||
|
# @param coordinate_v [Float] the v-coordinate on the plane
|
||||||
|
# @return [Geom::Point3d] the point in space that corresponds to the given (u, v) coordinates
|
||||||
|
def point_at(coordinate_u, coordinate_v)
|
||||||
|
scaled_direction_u = Geom::Vector3d.new(direction_u.x * coordinate_u,
|
||||||
|
direction_u.y * coordinate_u,
|
||||||
|
direction_u.z * coordinate_u)
|
||||||
|
scaled_direction_v = Geom::Vector3d.new(direction_v.x * coordinate_v,
|
||||||
|
direction_v.y * coordinate_v,
|
||||||
|
direction_v.z * coordinate_v)
|
||||||
|
origin + scaled_direction_u + scaled_direction_v
|
||||||
|
end
|
||||||
|
|
||||||
|
# Find local (u, v) coordinates of the projection of the given point to the plane
|
||||||
|
# @param point [Geom::Point3d] the point that will be projected to the plane
|
||||||
|
# @return [(Float, Float)] the local coordinates on the plane that correspond to the projected point
|
||||||
|
def plane_coordinates(point)
|
||||||
|
origin_to_point = origin.vector_to(point)
|
||||||
|
coordinate_u = origin_to_point.dot(direction_u)
|
||||||
|
coordinate_v = origin_to_point.dot(direction_v)
|
||||||
|
[coordinate_u, coordinate_v]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Project a given point to the plane
|
||||||
|
# @param point [Geom::Point3d] the point that will be projected to the plane
|
||||||
|
# @return [Geom::Point3d] the projected point on the plane
|
||||||
|
def project_to_plane(point)
|
||||||
|
coordinate_u, coordinate_v = plane_coordinates(point)
|
||||||
|
point_at(coordinate_u, coordinate_v)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Check if the given point lies on the plane
|
||||||
|
# @param point [Geom::Point3d] the point to check
|
||||||
|
# @return [Boolean] whether the point lies on the plane
|
||||||
|
def on_plane?(point)
|
||||||
|
point.distance(project_to_plane(point)).to_m < LENGTH_TOLERANCE
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -50,6 +50,7 @@ module SpeckleConnector
|
|||||||
# rubocop:disable Metrics/AbcSize
|
# rubocop:disable Metrics/AbcSize
|
||||||
# rubocop:disable Metrics/PerceivedComplexity
|
# rubocop:disable Metrics/PerceivedComplexity
|
||||||
# rubocop:disable Metrics/CyclomaticComplexity
|
# rubocop:disable Metrics/CyclomaticComplexity
|
||||||
|
# rubocop:disable Metrics/MethodLength
|
||||||
def self.to_native(obj, sketchup_model)
|
def self.to_native(obj, sketchup_model)
|
||||||
views = collect_views(obj)
|
views = collect_views(obj)
|
||||||
return if views.empty?
|
return if views.empty?
|
||||||
@@ -72,11 +73,35 @@ module SpeckleConnector
|
|||||||
page = sketchup_model.pages[name]
|
page = sketchup_model.pages[name]
|
||||||
set_page_update_properties(page, view['update_properties']) if view['update_properties']
|
set_page_update_properties(page, view['update_properties']) if view['update_properties']
|
||||||
set_rendering_options(page.rendering_options, view['rendering_options']) if view['rendering_options']
|
set_rendering_options(page.rendering_options, view['rendering_options']) if view['rendering_options']
|
||||||
|
rescue StandardError => e
|
||||||
|
puts("Failed to convert view (name: #{name})")
|
||||||
|
puts(e)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# rubocop:enable Metrics/AbcSize
|
# rubocop:enable Metrics/AbcSize
|
||||||
# rubocop:enable Metrics/PerceivedComplexity
|
# rubocop:enable Metrics/PerceivedComplexity
|
||||||
# rubocop:enable Metrics/CyclomaticComplexity
|
# rubocop:enable Metrics/CyclomaticComplexity
|
||||||
|
# rubocop:enable Metrics/MethodLength
|
||||||
|
|
||||||
|
# @param page [Sketchup::Page] scene to update -update properties-
|
||||||
|
def self.set_page_update_properties(page, update_properties)
|
||||||
|
update_properties.each do |prop, value|
|
||||||
|
page.instance_variable_set(:"@#{prop}", value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# @param rendering_options [Sketchup::RenderingOptions] rendering options of scene (page)
|
||||||
|
def self.set_rendering_options(rendering_options, speckle_rendering_options)
|
||||||
|
speckle_rendering_options.each do |prop, value|
|
||||||
|
next if rendering_options[prop].nil?
|
||||||
|
|
||||||
|
rendering_options[prop] = if value.is_a?(Hash)
|
||||||
|
SpeckleObjects::Others::Color.to_native(value)
|
||||||
|
else
|
||||||
|
value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def self.collect_views(obj)
|
def self.collect_views(obj)
|
||||||
views = []
|
views = []
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ require_relative '../geometry/bounding_box'
|
|||||||
require_relative '../other/render_material'
|
require_relative '../other/render_material'
|
||||||
require_relative '../../convertors/clean_up'
|
require_relative '../../convertors/clean_up'
|
||||||
require_relative '../../sketchup_model/dictionary/dictionary_handler'
|
require_relative '../../sketchup_model/dictionary/dictionary_handler'
|
||||||
|
require_relative '../../sketchup_model/utils/plane_utils'
|
||||||
|
|
||||||
module SpeckleConnector
|
module SpeckleConnector
|
||||||
module SpeckleObjects
|
module SpeckleObjects
|
||||||
@@ -48,6 +49,25 @@ module SpeckleConnector
|
|||||||
end
|
end
|
||||||
# rubocop:enable Metrics/ParameterLists
|
# rubocop:enable Metrics/ParameterLists
|
||||||
|
|
||||||
|
# Checks 4 points are planar or not.
|
||||||
|
def self.check_4_points_planar(points)
|
||||||
|
plane = SketchupModel::Utils::Plane.from_points(points[0], points[1], points[2])
|
||||||
|
plane.on_plane?(points[3])
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add quad mesh to sketchup native mesh by checking planarity.
|
||||||
|
# @param native_mesh [Geom::Mesh] sketchup mesh to convert them later faces.
|
||||||
|
# @param polygon_points [Array<Geom::Point3d>] sketchup points to add them with polygon to mesh.
|
||||||
|
def self.add_quad_mesh(native_mesh, polygon_points)
|
||||||
|
is_planar = check_4_points_planar(polygon_points)
|
||||||
|
if is_planar
|
||||||
|
native_mesh.add_polygon(polygon_points)
|
||||||
|
else
|
||||||
|
native_mesh.add_polygon([polygon_points[0], polygon_points[1], polygon_points[2]])
|
||||||
|
native_mesh.add_polygon([polygon_points[0], polygon_points[2], polygon_points[3]])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# @param entities [Sketchup::Entities] entities to add
|
# @param entities [Sketchup::Entities] entities to add
|
||||||
# rubocop:disable Metrics/MethodLength
|
# rubocop:disable Metrics/MethodLength
|
||||||
# rubocop:disable Metrics/AbcSize
|
# rubocop:disable Metrics/AbcSize
|
||||||
@@ -68,7 +88,13 @@ module SpeckleConnector
|
|||||||
# 0 -> 3, 1 -> 4 to preserve backwards compatibility
|
# 0 -> 3, 1 -> 4 to preserve backwards compatibility
|
||||||
num_pts += 3 if num_pts < 3
|
num_pts += 3 if num_pts < 3
|
||||||
indices = faces.shift(num_pts)
|
indices = faces.shift(num_pts)
|
||||||
native_mesh.add_polygon(indices.map { |index| points[index] })
|
polygon_points = indices.map { |index| points[index] }
|
||||||
|
# Quad mesh
|
||||||
|
if num_pts == 4
|
||||||
|
add_quad_mesh(native_mesh, polygon_points)
|
||||||
|
else
|
||||||
|
native_mesh.add_polygon(polygon_points)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
state, _materials = Other::RenderMaterial.to_native(state, mesh['renderMaterial'],
|
state, _materials = Other::RenderMaterial.to_native(state, mesh['renderMaterial'],
|
||||||
layer, entities, &convert_to_native)
|
layer, entities, &convert_to_native)
|
||||||
@@ -84,6 +110,8 @@ module SpeckleConnector
|
|||||||
added_faces = entities.grep(Sketchup::Face).last(native_mesh.polygons.length)
|
added_faces = entities.grep(Sketchup::Face).last(native_mesh.polygons.length)
|
||||||
added_faces.each do |face|
|
added_faces.each do |face|
|
||||||
face.layer = layer
|
face.layer = layer
|
||||||
|
# Smooth edges if they already soft
|
||||||
|
face.edges.each { |edge| edge.smooth = true if edge.soft? }
|
||||||
unless mesh['sketchup_attributes'].nil?
|
unless mesh['sketchup_attributes'].nil?
|
||||||
SketchupModel::Dictionary::DictionaryHandler
|
SketchupModel::Dictionary::DictionaryHandler
|
||||||
.attribute_dictionaries_to_native(face, mesh['sketchup_attributes']['dictionaries'])
|
.attribute_dictionaries_to_native(face, mesh['sketchup_attributes']['dictionaries'])
|
||||||
|
|||||||
Reference in New Issue
Block a user